けせらせらのブログ

数学やプログラミングを中心に感想を流していきます。

爆弾人が取り敢えず完成

取り敢えず殆どオリジナルで作ったボンバーマン(爆弾人)が完成しました(第7章~8章に当たる部分)。期間にして大体1週間ちょいですかね。
ソースコードこちら

ということで本書の7章~8章を(ここで初めて)読んだうえでの感想を書いていきます。


反省点

  1. エラーが残っている
  2. プレイヤーの座標の取り方
  3. ステージのパラメータ

・1について
この反省点がある時点で完成しているとは言い難い状況なのは重々承知ですが、明確に原因を究明するのが現時点で厳しそうなので保留にしました。
今現在わかっていることは、長期間残っているエラーはSAFE_DELETEの使い方(または、それ自体)に問題がありそうだということです。この推論に至った理由は、残っているログの使用されている関数を見ると必ずSAFE_DELETEを使っている関数で終わっているという点、また実際にSAFE_DELETEを消すことにより解消した例外が存在したという2点です。後者はソースコード内のSequence::Game::Parent内のsetStateという関数において観測されました。

・2について
座標の値を実際の画素の1000倍の値をとることにより細かなスピードの調整が(intにおいて)できるというものです。僕のコードでは画素単位の座標をそのまま持ってしまっているのでそのようなことができません。

・3について
ステージのパラメータをもって、それを基にステージの自動生成を行うというものです。僕が書いたコードにも似たようなものはありますが、特定の数の敵を必ず配置するなど実現できていない部分があるので書き直す必要がありそうです。


工夫した点

  1. 連続した操作の確率
  2. ボムの当たり判定

だけです()
正確に言うと、壁に当たっても滑る処理など工夫した点はほかにもあるのですが、本書に書いてあるものは割愛しました。

・1について
先に言っておくと、この工夫は別に必要ありませんでした。悲しい。
そのうえで興味のある人は読んでください。

これの目的は、選択肢が与えられたときに等確率でその選択肢を選ぶことです。
この工夫が必要な理由ですが、大まかに言うと、与えられた選択肢を同時に選ぶ場合(以下でいうp_0,p_1,…)と順番に選ぶ場合(以下でいうhoge(0),hoge(1),…を実行すること)で特定の選択肢を選ぶ確率が異なるからです。
今、選択肢に0,1,2,…と番号を付けます。p_0を0を選ぶ確率、f_0を確率p_0でtrueを返す関数とした時、選択肢をif (f_0) hoge(0); else if (f_1) hoge(1); else if …のようにつないだ時に互いの選択肢を選ぶという事象が独立ではなくなってしまうので、p_0== p_1 == …となるようにしても、厳密には(hoge(0)を実行する確率)>=(hoge(1)を実行する確率)>=…となってしまいます。 今それぞれを選ぶ確率は p_0, (1-p_0)p_1, (1-p_0)(1-p_1)p_2,… となっているので、これらが等しくなるようにすればよいです。具体的に等式を解いてみると、p_(i+1) = p_i / (1 - p_i) (i = 0,1,…)という漸化式が成り立ち、p_i = p_0 / (1 - i * p_0) (i = 0,1,…)という式が成り立ちそうなのがわかります。
実際にこの式が正しいことは数学的帰納法により証明できます。 あとはこのように定めたp_iに対してf_iを本書内のpercentのように定義してあげればよいだけです。

あとから気づいたのですが、最初に言った通りこんなことしなくてもできます。
選択肢に0,1,2,…とラベル付けをしてgetRandom(選択肢の数-1)としてあげてから、その値によってif文で分けるほうが簡単で分かりやすいです……

・2について
これは本書とは違う実装になったので解説しておきます。
まず今回の問題点は、ボムを置いた直後「移動後にボムに触れる場合は動かない」という判定により動けなくなってしまいそのままボムの餌食になってしまうことでした。
本書の解決法では一度ボムから離れたら先ほどの当たり判定を用いるというものです。
僕の場合ですが、「今現在ボムに触れていない かつ 移動先でボムに触れている」の場合のみを当たり判定に用いました。そうすれば問題点は解消できますし、壁やブロックに対して同じ判定を用いても問題ないのでこっちのほうが便利です(きっと)。


感想

結構時間がかかり、普通に疲れました。
一番反省が必要なのはやはりエラーが残ってしまったことですね。これでも頑張って減らしたほうだと思っていますが…
この点に関して軽く調べてみるとスマートポインタなるものが存在するらしいです。
後で調べてみます(きっと…)
また、作業中の笑ってしまうようなバグには結構癒されました。 本書で紹介されている「爆弾の上でただひたすら死を待つだけのバグ」は僕もやりましたし、他に覚えているのは「敵を1体倒すと他の敵が透明化するバグ」とか「開始直後に死ぬバグ」とか「動いたら死ぬバグ」ですかね。
なんか、死んでばっかだな。

こんな感じで色々ありましたが一応それっぽいものは完成したので結構楽しかったです。
またこの調子で続きも勉強していきます。