ページ 11

バグの原因は・・・

Posted: 2012年8月31日(金) 22:27
by icon01
 短いスパンでの投稿となり、自分の未熟さが悔しさを募らせます。

いまだにパズルゲームの製作に手間取っています。

以前、再帰関数について質問させていただき、皆さんの助言のおかげで今、4つブロックをそろえて消し、消えたところは上の段のブロックが下にずれて埋め、上の空いたところに、新たにランダムにブロックを配置するというプログラムを組むところまで来ました。しかし、たまにバグります。4つ揃えても消えなかったり、揃えていないところが、なぜか消えたり、白いブロック(意図していない)が生み出されたり(たぶん、二つ以上の数字が同時にブロックを参照したため?)etc...

今私の考えでは、おそらくScenePly.cppの188行目と222行目のg_DeletePanelW[h2][w2]とg_DeletePanelH[h2][w2]の初期化が行われていないからだと推測して、色々策を講じているのですが、うまくいきません。ブロックが瞬時に切り替わってしまうので視認しずらいのも一役買っています。(この演出方法も何かうまい方法があれば教えていただきたいと思っているのは別のお話)

ソースファイルは、スパゲッティになる前のg_DeletePanelW[h2][w2]とg_DeletePanelH[h2][w2]の初期化をしていない過去のものを載せておきます。

皆さんもお忙しい中、デバッグになんか付き合ってられねーよと思われるかもしれませんが、ご助言だけでもいただけると幸いです。
どうかよろしくお願いいただけないでしょうか。

Re: バグの原因は・・・

Posted: 2012年8月31日(金) 22:41
by icon01
そういえば、
操作方法とか書いていませんでした。

方向キーとスペースキーのみ

スタートにカーソルを合わせてスペースでゲーム開始、Xキーでタイトルに戻る
ゲーム終了に合わせてスペースでゲーム終了。
ほかの、おまけとかには触らないでください(何もないので戻れなくなります)
プレイ画面
方向キーで薄緑色のカーソル移動。任意の場所でスペースを押すと、その真下の画像が左右入れ替わる。
4つ以上縦または横にそろうと消え、・・・・

Re: バグの原因は・・・

Posted: 2012年9月01日(土) 00:41
by softya(ソフト屋)
チェックと消えた状態管理の配列が多いのがバグりやすい原因かと思いますので、出来るだけ単純なアルゴリズムにするとバグが減るかと思います。
消去ルールって縦横が4つ以上揃ったらで消えた後は鉄のブロックになって鉄のブロックも移動可能で良いんですよね?

だとしたらg_Panel以外の
int g_DeletePanelW[PANEL_SIZE][PANEL_SIZE],g_DeletePanelH[PANEL_SIZE][PANEL_SIZE]; // 1なら消える
int g_CheckPanelW[PANEL_SIZE][PANEL_SIZE],g_CheckPanelH[PANEL_SIZE][PANEL_SIZE]; // 1ならチェック済み
は4つも不要で1つだけの配列で処理できるのと思うのですが。
その1つの配列もチェックをはじめる時に初期化すれば良いと思います。

Re: バグの原因は・・・

Posted: 2012年9月01日(土) 00:52
by icon01
[quote="softya(ソフト屋)"]
消去ルールって縦横が4つ以上揃ったらで消えた後は鉄のブロックになって鉄のブロックも移動可能で良いんですよね?
quote]
 
sofutoyaさん返信ありがとうございます。

すみません、自分がどうしたいかを書いていませんでした。フォーラムルールに抵触していますね。

鉄ブロックに変えたのはあくまで便宜的なので、最終的には完全に消去して、上段のブロックを下にスライドさせ、上の空きを新規ブロックで埋める。←これを目的にしています。(ちなみに縦と横は別々に判定します。)

仮にそうだとしても、変数の数は減らしてもいいみたいですね、少し、試してみます。

Re: バグの原因は・・・

Posted: 2012年9月01日(土) 00:59
by softya(ソフト屋)
ルール的に抜けを感じるのですが揃ったら横のブロックがずれる事はないのでしょうか?
あと縦横同時にそろったら、どちらが優先されるのでしょうか?それとも同時に消去されるのでしょうか?

Re: バグの原因は・・・

Posted: 2012年9月01日(土) 01:18
by icon01
消した後はy方向しか見ていないので、横にずれることは(たぶん)ないと思います。

縦と横を同時に消すと、ウォータフォールにのっとり横が優先されるようです。

Re: バグの原因は・・・

Posted: 2012年9月01日(土) 11:06
by softya(ソフト屋)
ルール的には下にしかズレ無いということですね。
それと横が優先と言うことですね。
「優先されるようです。」ってのが曖昧で気になりますが。

次の場合の動作イメージは、これで合ってますか?

(1)4つ縦横で揃う 数値は何らかの図柄
■333
■222
■111
■■■■

(2)横が消滅
■333
■222
■111
□□□□

(3)上からズレる。
4444
■333
■222
■111

そういえば落下するなら連鎖もするんですよね?

後々返ってややこしくなるので、鉄のブロックに置き換えるのではなく最初から消滅するロジックで書くことをおすすめします。

Re: バグの原因は・・・

Posted: 2012年9月01日(土) 11:33
by icon01
sofutyaさん返信ありがとうございます。

動作のイメージはまさにその通りです。連鎖もします。(といっても一瞬で処理が進むので視認しづらいですが)

ブロックの画像はお持ちかと思いますが、#difine BLOCK_NO 15 として、消えたなら15番目の真っ白なブロックに代わるようにしています。

コード:

if(g_DeletePanelH[h2][w2] == 1){
SetDrawBlendMode( DX_BLENDMODE_ALPHA,  0 );
g_Panel[h2][w2] =  BLOCK_NO;
SetDrawBlendMode( DX_BLENDMODE_NOBLEND,0 );
}
みたいにしていました。

今気づきましたがこの加算ブレンドの処理はDrowGraph()を挟む以外は無意味なようですね。

Re: バグの原因は・・・

Posted: 2012年9月01日(土) 11:36
by softya(ソフト屋)
icon01 さんが書きました: 今気づきましたがこの加算ブレンドの処理はDrowGraph()を挟む以外は無意味なようですね。
はい。無意味です。

Re: バグの原因は・・・

Posted: 2012年9月01日(土) 19:35
by icon01
 あれからしばらく原因を探ってみましたがまだ完全にバグは治りません。

色々調べて分かったことは、

・#difine BLOCK_NO 15 の数字を変えただけでバグが増える(spaceを押していないのにあるところにカーソルを合わせるとブロックが変化する・カーソルが端まで動かせない「spaceを押すと見当違いの場所のブロックが入れ替わる」)等々

・一番上のブロックを横に並べると白いブロック(意図していないもの)で埋まる
(これは修正できたと思います)

・たぶん4つ揃えても消えないバグはなくなった?と思う。

・ネットで調べた情報ですがZeroMemoryで初期化するのはよろしくない(らしい)とのことなので、for文で回してみました

以上を踏まえたうえで、皆さんのお力をもう一度お貸し願えないでしょうか?

頼ってばかりで申し訳ないですが、どうかよろしくお願いいたします。最新のファイルScenePlyファイルのみ添付しておきます。

Re: バグの原因は・・・

Posted: 2012年9月01日(土) 20:59
by softya(ソフト屋)
一時的に画面の横幅を広げてg_DeletePanelWやg_DeletePanelHの情報を表示するようにしてみてください。
問題があれば目に見えて分かると思います。追いかけ辛いプログラムなのでお願いします。

私としては、g_DeletePanelWとg_DeletePanelHの2つの分かれている理由がわかりません。
それとg_DeletePanelWとg_DeletePanelHの値をずっと保持している理由もです。
チェックするときだけ必要な配列なんじゃないでしょうか?

Re: バグの原因は・・・

Posted: 2012年9月01日(土) 21:08
by icon01
softya(ソフト屋) さんが書きました:一時的に画面の横幅を広げてg_DeletePanelWやg_DeletePanelHの情報を表示するようにしてみてください。
問題があれば目に見えて分かると思います。追いかけ辛いプログラムなのでお願いします。

私としては、g_DeletePanelWとg_DeletePanelHの2つの分かれている理由がわかりません。
それとg_DeletePanelWとg_DeletePanelHの値をずっと保持している理由もです。
チェックするときだけ必要な配列なんじゃないでしょうか?
softoyaさん返信ありがとうございます。

g_DeletePanelWとg_DeletePanelHは縦と横を別々に判定して4つ塊があれば勝手に消えるのを防ぐためにしているつもりだったのですが・・・1つで事足りるのでしょうか?

あとグローバル変数ではなくSearchDelBlock()の関数の中でローカルとして使うべきということでしょうか?

Re: バグの原因は・・・

Posted: 2012年9月01日(土) 21:17
by softya(ソフト屋)
icon01 さんが書きました: g_DeletePanelWとg_DeletePanelHは縦と横を別々に判定して4つ塊があれば勝手に消えるのを防ぐためにしているつもりだったのですが・・・1つで事足りるのでしょうか?
同時に使用しないなら1つで足りるでしょう。
icon01 さんが書きました: あとグローバル変数ではなくSearchDelBlock()の関数の中でローカルとして使うべきということでしょうか?
そういう意味ではなく、常に値を保持する必要はないでしょうと言う意味です。
チェックをはじめる時に現状のg_Panelに合わせて初期化して結果は再び使う必要がないのでは?

Re: バグの原因は・・・

Posted: 2012年9月03日(月) 14:25
by バグ
私なりの解釈でサンプルを作成してみたのですが、最終的に目指している動きはこんな感じ(添付exeファイル参照)でしょうか?

※ソースコードを提示することは可能ですが、かなりの部分を私の都合の良いように改造してしまっているのであまり参考にならないかもしれません。

※不具合がありましたので、サンプルのDLは最新のレスからお願いします。

Re: バグの原因は・・・

Posted: 2012年9月03日(月) 14:36
by バグ
icon01 さんが書きました: g_DeletePanelWとg_DeletePanelHは縦と横を別々に判定して4つ塊があれば勝手に消えるのを防ぐためにしているつもりだったのですが・・・1つで事足りるのでしょうか?

これは以前のスレで私が確認したことですね。
何か必要があって、縦方向と横方向の両方のフラグを持っているのかということですね。
消える場所かそうでないかの管理だけであれば1つでいいのでは?という意味です。

バグ さんが書きました: 横方向に並んで消える、縦方向に並んで消えるという情報は必要なのでしょうか?
それとも消えるか消えないかの情報だけでも構わないのでしょうか?

Re: バグの原因は・・・

Posted: 2012年9月03日(月) 14:43
by softya(ソフト屋)
バグさんへ。
添付のコードですが起動はするのですがパズル画面に移行できません。
起動状態でウィンドウを動かそうとすると応答なしになり、起動直後にそのままスペースキーを押しても反応がありません(音楽は流れた状態)。
Log.txtには特にエラーは出ていません。icon01さんのは動いていたんですが。

Re: バグの原因は・・・

Posted: 2012年9月03日(月) 14:59
by バグ
>>softyaさん
あら?こちらの環境では普通に動いているんですが・・・?
うーん、原因がよく分からないので、ソースコード載っけますね。

こちらの環境は、XP、VS2008、DxLib_Ver3.07a・・・です。

※ソースコードのDLは最新のレスからお願いします。

Re: バグの原因は・・・

Posted: 2012年9月03日(月) 15:28
by softya(ソフト屋)
ソースコードにProcessMessage()が無いんですが動いていますか?
while (!::ClearDrawScreen() && CKeyboard::GetInstance()->Refresh() && scene.Update() && !::ScreenFlip());
 ↓ こうすればうごく。
while (!::ClearDrawScreen() && !::ProcessMessage() && CKeyboard::GetInstance()->Refresh() && scene.Update() && !::ScreenFlip());
そのほうが不思議なんですが。

Re: バグの原因は・・・

Posted: 2012年9月03日(月) 15:59
by バグ
>>softyaさん
あぁ、やらかしてた・・・失礼しました・・・orz
ただ、こちらのexeが普通に動いてるのも本当なんですよ。
うーむ・・・どうしてなんでしょうね・・・?

まぁ、なんにしても、動いているのが「たまたま」なのは間違いないでしょうけど・・・(苦笑)

という訳で、修正版を再添付します。m(_ _)m

Re: バグの原因は・・・

Posted: 2012年9月04日(火) 21:23
by icon01
 バグさん、softoyaさん返信ありがとうございます。

 諸事情によりパソコンからしばらく離れていたので返信が遅れてしまい申し訳ありませんでした。

 さて、バグさんのソースコードを読ませていただきました。が、まさかほぼ百パーセントの回答をいただけるとはつゆほども思っていなかったので、しばらくあいた口がふさがりませんでした(笑)。このまま丸コピするつもりはありませんので、C言語に自分の書き方で直した後、そのソースを張って、この質問を「解決」としたいと思います。

ではまた後程。

Re: バグの原因は・・・

Posted: 2012年9月05日(水) 05:47
by icon01
 大変申し上げにくいのですが・・・。

バグさんのプログラムバグってます。たまに4つ揃えてもいないのに消えたり、別のブロックが巻き添えになったりします。

熟練のプログラマーさんでもこのようなミスか引き起こされるとは・・・自分には敷居が高すぎたかな・・・orz。

Re: バグの原因は・・・

Posted: 2012年9月05日(水) 09:41
by softya(ソフト屋)
icon01 さんが書きました: 大変申し上げにくいのですが・・・。

バグさんのプログラムバグってます。たまに4つ揃えてもいないのに消えたり、別のブロックが巻き添えになったりします。

熟練のプログラマーさんでもこのようなミスか引き起こされるとは・・・自分には敷居が高すぎたかな・・・orz。
プロでもだれでもバグる可能性はあります。
全部自分で作ったコードじゃない場合や作りなれたものじゃない場合は特にですね。
パズルコードは、綺麗に組みさえすればバグが出る可能性が減らせられますのでシンプルにすることを目指してください。

Re: バグの原因は・・・

Posted: 2012年9月05日(水) 10:06
by バグ
>>icon01さん
あぁ・・・すみません。まだやらかしてましたか(^_^;)
とりあえず動きを見る為のサンプルなので、あんまりデバッグ作業を詰めてないです。(ProcessMessageを書き忘れているほどなのでw)

落ち物パズルゲームは割りと敷居は低い方だと思います。
ちなみに、私がプログラムを勉強しはじめて最初に作ったのはコラムスと呼ばれる落ち物パズルゲームでした。

http://dixq.net/sm/

ここに載せてもらっている「ぷよぷよもどき」や「ColorDrop」なんかは(今見ると赤面もののソースコードなのであまり紹介はしたくないのですがw)勉強を始めた初期のころの作品です。よければ遊んでみてください。

Re: バグの原因は・・・

Posted: 2012年9月05日(水) 16:52
by ISLe
icon01 さんが書きました:熟練のプログラマーさんでもこのようなミスか引き起こされるとは・・・自分には敷居が高すぎたかな・・・orz。
統計的には、ミスは誰にでも一定の確率で発生すると言われています。
確率で発生するわけですから、試行錯誤を繰り返すとミスの発生する確率はどんどん増えていきます。
コード量を減らせば、ミスも減ります。

経験者はミスをしないのではありません。
シンプルに実装し、試行錯誤が少なく、他人が気付く前に修正するのが経験者です。

あと、ゲームのルールのようなロジックを考えるときは、母国語で考えたほうが遥かに効率が良いと思います。