「一気に最後まで読んだ」本、教えて下さい!

ダメージ計算関数のテストをしてみたんですが、実行結果がおかしかったのデバックビルドをしたら、変数damage_seed(ダメージ計算の素となる値)がスクリーンショットの通り、おかしな値になっていました。
どこが問題なのか教えてください。
実行環境は、Visual Studio Community 2015です。
すごく初歩的な部分なんですが、よろしくお願いします。

int damage(int hit_probability, int critical_probability, int attack_level, int attack, int defence) {
/*
第1引数:攻撃のヒット率
第2引数:クリティカル率
第3引数:攻撃する人のレベル
第4引数:攻撃する人の攻撃力
第5引数:攻撃される人の守備力
*/
int damage_seed = attack - defence + random(attack_level, 0);
if (damage_seed <= 0 && judgement(50)) damage_seed = 1;
else damage_seed = 0;
if (!judgement(hit_probability)) damage = 0;
else if (judgement(critical_probability)) return static_cast<int>(((damage_seed)* 3 >> 2) + (1 >> 2));
else return damage_seed;
}

int main(void) {
int hp = 150;
hp -= damage(100, 10, 15, 155, 100);
std::cout << hp << std::endl;
}
他にも攻撃が当たるかやクリティカルが発生するかを判定するjudgement関数(bool型/引数:確率)と、乱数を返すrandom関数(int型/第1引数:乱数の最大値 第2引数:乱数の最小値)が存在しますが、そこには問題はなかったので省略しました。

「変数の値がおかしい」の質問画像

A 回答 (2件)

#1 の最後で指摘してされている点はどちらもエラーですな. ポインタ変数に 0 を代入するのは OK だけど, 関数名から変換されたポインタ値に代入するのはさすがにアウト. あと, 値を返す (つまり返り値の型が void でない) 関数は, main を除いて返り値を伴う return の実行が必須 (main だけは「return を実行しなかったら関数の最後に return 0; という文があるものとみなす」ことになっている).



以下おまけ:
まず, 「judgement」は関数名としてどうなんだろうか. 判定して bool値を返すのはいいけど, この名前から「どういうときに true を返してどういうときに false を返すのか」は読み取れないねぇ. この手の「ひどい名前」は有名なソフトウェアでも見かけることがある (そしてときどきバグが混入している) んだけど, やっぱり気を付けた方がいいと思うな.

それから
return static_cast<int>(((damage_seed)* 3 >> 2) + (1 >> 2));
の部分は
・damage_seed になぜ括弧をつけているのか
・1>>2 の結果は 0 だから加算の意味がない
・右辺はそもそも int なので static_cast が完全に余計
と, 無駄だらけ. ついでにいうとこの計算結果が damage_seed より小さいことに気づいてる?
    • good
    • 0
この回答へのお礼

damage = 0部分は、前の関数名の時にあった変数が残ってただけです。すいません。

static_castの部分はクリティカルヒット時のダメージ計算を行う部分なんですが、出てくる値に問題があったので変えました。
damage_seedが括弧で囲まれてるのはミスです。すいません。

そして原因は#1の方へのお礼のところにも書きました通り、3行目のelse文でした。

ありがとうございました。

お礼日時:2015/09/12 07:15

>スクリーンショットの通り、おかしな値になっていました。



それを確認したのは、どの位置にブレークポイント設定した時ですか?

>int damage_seed = attack - defence + random(attack_level, 0);
の行であれば、後に書かれた計算式の処理前なので不定値が入っているのは正常です。
-858993460を16進数にすると0xCCCCCCCCなので…VC系のデバッグビルド時の未初期化ローカル変数としては正常な値でしょう。
# VCのデバッグビルドでは未初期化のローカル変数は0xCCで埋められます。
# よく文字列を表示してみたら最後に”フフフフフフフフ”って続くんですけどなんでしょう?とか書かれることがありますが。
# 「VC デバッグビルド 0xCC」辺りで検索して見てくださいな。
# リリースビルドだと本当に不定値が入っています。実行するたびに値が変わる可能性が高いですね。

んで…いろいろ端折っているのかも知れませんが、上記のdamage()にはおかしいところがあります。
インデントが見にくいので整形すると……

>int damage(int hit_probability, int critical_probability, int attack_level, int attack, int defence) {
> /*
>  略
> */
> int damage_seed = attack - defence + random(attack_level, 0);
> if (damage_seed <= 0 && judgement(50))
>  damage_seed = 1;
> else
>  damage_seed = 0;
>
> if (!judgement(hit_probability))
>  damage = 0;
> else if (judgement(critical_probability))
>  return static_cast<int>(((damage_seed)* 3 >> 2) + (1 >> 2));
> else
>  return damage_seed;
>}

if (!judgement(hit_probability))
 damage = 0;
で、関数ポインタに0を代入(?)しています。
ビルド通るんですか?
で、この条件以外ではreturnで値を返却していますが、このルートに入ると戻り値なしで関数抜けます。
# ビルド時にエラーになっていませんかね?
    • good
    • 0
この回答へのお礼

damage = 0
ここはreturn 0です。
元の関数の名前がdamage_calcで、その中にdamageっていう変数があったのがそのままになってました。すいません。

あと、処理の3行目のelse文が原因で、damage_seedが0にされてました。

スクリーンショットの件は、ブレークポイントの位置を間違えていたことが原因でした。

ありがとうございました。

お礼日時:2015/09/12 07:04

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報