ページ 1 / 1
4つそろったら消えるプログラム
Posted: 2012年8月25日(土) 15:57
by icon01
今作っているパズルゲームで、同じ画像が縦横斜めのどれかに4つ以上そろったら消すプログラムを組もうと思ったのですが、
色々調べると、皆さん配列を使って
[0][0][0][0][0]
[0][1][2][1][0]
[0][0][1][3][0]
[0][0][0][0][0]
みたいな書き方をしていらっしゃいます。([0]は壁)そして同じ数字が並んだら消す~といった処理をしていくようなのですが・・・
ですが私は、
コード:
//while文の外で初期化処理
int Block[16]; //読み込んだ画像16分割
int MAP[12][12];//マップのサイズ
int Leng,Wid; //縦・横
int random; //乱数取得
for( Leng = 0; Leng <12 ; Leng++)
{
for( Wid = 0; Wid < 12; Wid++)
{
random =GetRand(12);
if(Leng == 0||Leng == 11||Wid == 0||Wid == 11)
{
MAP[Leng][Wid] = Block[7];
}
else
{
MAP[Leng][Wid] = Block[random];
}
}
}
//while文の中で描画
for( Leng = 0; Leng < 12; Leng++)
{
for( Wid = 0; Wid < 12; Wid++)
{
DrawGraph( Wid*32, Leng*32 , MAP[Leng][Wid], TRUE );
}
}
今現在上記のようにして、外枠以外の中の画像をランダムで選び表示したマップを製作しています。
今後そこからBlock[n]の中に、対応するstateを入れて、そのstateをif文で判断して4つ以上なら消すように書けばいいのではないかと頭の中で考えているのですが、いかんせん頭の中に描いているだけで何もしていないので、このやり方が「書くのがめんどくさい」「見にくいプログラム」「そもそも動かない」など皆さんの意見をお聞かせ願いたいのです。
そもそも、パズルゲームと聞くと皆さん[0][0][1][2]・・・とかくのはやはり理由があるのでしょうか?それが引っ掛かって、制作が滞っているのです。
どなたかの回答をお待ちしております。
Re: 4つそろったら消えるプログラム
Posted: 2012年8月25日(土) 16:22
by nil
>パズルゲームと聞くと皆さん[0][0][1][2]・・・とかくのはやはり理由があるのでしょうか?
というのがよくわかりませんでしたが、プログラムについていくつか気になったことがあったので、
まず
>int MAP[12][12];//マップのサイズ
1.何故MAPは大文字なのか。
2.コメントはマップのサイズではなくマップの中身あたりが妥当かと
そして、
マジックナンバーが多い、定数が少ない。
Block[7]
このようにアクセスするのではなく
コード:
// Cの場合
#define BLOCK_WALL (7)
// C++の場合
const int BLOCK_WALL = 7;
Block[ BLOCK_WALL ]
このようにするか、列挙体を使ってアクセスすべきです。
同様に
コード:
for( Leng = 0; Leng <12 ; Leng++)
for( Wid = 0; Wid < 12; Wid++)
ではなく、
コード:
const int MAP_WIDTH = 12;
const int MAP_HEIGHT = 12;
for( Leng = 0; Leng <MAP_WIDTH ; Leng++)
for( Wid = 0; Wid < MAP_HEIGHT; Wid++)
とすべき。
(Wid, LengはそれぞれWidth, Lengthの略記であるのだと思いますが、
Widthは横幅、Lengthは長さの意味合いであり、用途と語の意味が異なっている)
>random =GetRand(12);
16ではないのか。
マジックナンバーの多用の弊害です。
一見しただけでは間違いとわかりづらい。
あと、7が壁であるのならば
GetRand(12)の範囲に7が入るため、マップ内にも壁が配置されることになる。
あと乱数が必要なのはelse節の中だけなので、else節の中でGetRandを使うべきです。
あと、設計として
画像ハンドルをマップ配列に渡すのではなく、
マップ配列の値を使って画像ハンドルにアクセスすべきです。
コード:
// 例
MAP[0][0] = 7;
DrawGraph( Wid*32, Leng*32 , Block[ MAP[Leng][Wid] ], TRUE );
ブロックが4つ並んでいるかの判定は
僕ならば現在指しているブロックから上下、左右、斜めのブロックが、そのブロックと同じかを判定する関数を再帰的に呼び出し、その総数が4以上であればブロックを消す処理を行うようにプログラムを組みます(もちろん上下、左右、斜めは別々に判定します)。
Re: 4つそろったら消えるプログラム
Posted: 2012年8月25日(土) 16:33
by softya(ソフト屋)
>そもそも、パズルゲームと聞くと皆さん[0][0][1][2]・・・とかくのはやはり理由があるのでしょうか?それが引っ掛かって、制作が滞っているのです。
気にする必要はありません。自分の好きなように書いてください。
やっていれば、そのうち効率の悪い方法やバグが起きにくい方法がわかってきます。
みんながそのようにしているからと最初から同じ方法を選ぶのは悩んで知恵を学ぶチャンスを失います。
助言を受けるのは悪いことではないですが色々試した後でも良いはずです。
なにより、色々試した後のほうが助言の意味が分かると思います。
Re: 4つそろったら消えるプログラム
Posted: 2012年8月25日(土) 17:17
by icon01
返信ありがとうございます。
マジックナンバーのことを失念していました。一人よがりのプログラムで、他人に全く配慮していませんでした。申し訳ありません以後気を付けます。
さて、涼雅さんがおっしゃっていた、「画像ハンドルをマップ配列に渡すのではなく、マップ配列の値を使って画像ハンドルにアクセスすべきです。」という言葉の意味についてですが、これは処理速度の関係ですか?それともソースの見栄え?ためしにやってみたらアクセス違反だと怒られてしまったので、書き方が悪い僕がいけないんですけど、やる必要があるのかなと怠惰癖が出てしまいまして・・・。
マジックナンバーについては変更させていただきました。ご指摘ありがとうございました。
softya(ソフト屋)さんも、回答ありがとうございました。自分なりに試行錯誤してみます。
Re: 4つそろったら消えるプログラム
Posted: 2012年8月26日(日) 07:39
by へにっくす
icon01 さんが書きました: さて、涼雅さんがおっしゃっていた、「画像ハンドルをマップ配列に渡すのではなく、マップ配列の値を使って画像ハンドルにアクセスすべきです。」という言葉の意味についてですが、これは処理速度の関係ですか?それともソースの見栄え?ためしにやってみたらアクセス違反だと怒られてしまったので、書き方が悪い僕がいけないんですけど、やる必要があるのかなと怠惰癖が出てしまいまして・・・。
処理速度の関係や見栄えとかでなく、変数の用途が間違っているといいたいのではと思いますが。
別にMAPに直接ハンドルを入れるのも構いませんが、普通そういうことはしないですね。だってMAPって、その位置に何があるかを入れるべきでしょう?
それなのに画像のハンドルって変だと思うのですが、貴方はどう思いますか?
画像ハンドルが入っているBlock変数はあくまでもそのハンドルが必要な処理にのみ使用するべきなのです。
怠惰癖が出てしまって、、と言いますけど、何人かでチーム組んで、分担してやっているときにそんな言葉吐けますかね?
自分ひとりでやる分には構いませんが、プログラマーを目指しているなら、そんな言葉はゴミ箱に捨ててくださいね。
Re: 4つそろったら消えるプログラム
Posted: 2012年8月26日(日) 11:05
by softya(ソフト屋)
一つだけ言うと、ハンドルを直接MAPに入れた場合はすごくデバックが困難になります。
ハンドルの数値を見てもどの画像のこと分かりませんが、 0,1,2なら見てすぐ判別できますよね。
まぁ、こういうことも含めて試行錯誤して欲しいんですけどね。
> さて、涼雅さんがおっしゃっていた、「画像ハンドルをマップ配列に渡すのではなく、マップ配列の値を使って画像ハンドルにアクセスすべきです。」という言葉の意味についてですが、これは処理速度の関係ですか?それともソースの見栄え?ためしにやってみたらアクセス違反だと怒られてしまったので、書き方が悪い僕がいけないんですけど、やる必要があるのかなと怠惰癖が出てしまいまして・・・。
なので、答えは自分のためです。
Re: 4つそろったら消えるプログラム
Posted: 2012年8月26日(日) 14:53
by icon01
へにっくすさん
softyaさん
返信ありがとうございます。
コード:
while文の外で初期化
int Hig,Wid; //縦・横(涼雅さんのご指摘に則して変更)
int Block_Wall = 7;
int random;
int Block_Wall;
for( Hig = 0; Hig <12 ; Hig++)
{
for( Wid = 0; Wid < 12; Wid++)
{
if(Hig == 0||Hig == 11||Wid == 0||Wid == 11)
{
MAP[Hig][Wid] = Block_Wall;
}
else
{
random =GetRand(12);
MAP[Hig][Wid] = random;
}
}
}
while文の中で描画処理
for( Hig = 0; Hig < 12; Hig++)
{
for( Wid = 0; Wid < 12; Wid++)
{
DrawGraph( Wid*32, Hig*32 , Block[MAP[Hig][Wid]], TRUE );
}
}
自分なりにプログラムを書き直してみましたが、こういうことでよろしいのでしょうか?
動作に変化がなく、いまいち実感が湧かないので・・・
Re: 4つそろったら消えるプログラム
Posted: 2012年8月26日(日) 15:01
by softya(ソフト屋)
デバッガで確認するときぐらいしか実感がわかないと思います。
あるいは、MAPに何らかの操作する時でしょうか。
ところで、パズルなのでMAPと言う名称はあまりふさわしくない気がします。
PanelとかBoardの方がふさわしくないでしょうか?
Re: 4つそろったら消えるプログラム
Posted: 2012年8月26日(日) 15:14
by へにっくす
icon01 さんが書きました:自分なりにプログラムを書き直してみましたが、こういうことでよろしいのでしょうか?
動作に変化がなく、いまいち実感が湧かないので・・・
動作の指摘というよりは、書き方の指摘ですからねえ。
実感がわくタイミングは、softyaさんの言う通りだと思います。
あと涼雅さんの指摘で
としたのでしょうが、そう書いていないですよね?
コード:
// Cの場合
#define BLOCK_WALL (7)
// C++の場合
const int BLOCK_WALL = 7;
Block[ BLOCK_WALL ]
定数を宣言するときはconstを入れましょうね?
また、高さと幅の定義も同じようにしなさいと指摘されていたと思いますが、、
Re: 4つそろったら消えるプログラム
Posted: 2012年8月26日(日) 15:20
by icon01
時間差で、へにっくすさんのコメントを見逃していましたので追記
すみません、本当はヘッダファイルが別にありEXTERNしてあるのを投稿用に書き直していました。それも含めて最初に書いておくべきでしたね。誤解を与えてしまい、申し訳ありませんでした。
縦と横の定義に関しては失念しておりました。返す言葉もございません。涼雅さんがこの文章を読むかはわかりませんが、この場を借りて頭を下げさせていただきます。
Re: 4つそろったら消えるプログラム
Posted: 2012年8月26日(日) 15:31
by icon01
投稿したつもりができていないせいで文章がへんになっていました。
MAPに関してはPanelとして書き直させていただきます(←これをへにっくすさんの投稿の前に書いたつもりでした。)
今まで的確なアドバイスどうもありがとうございました。またお世話になることがございましたら、その時はどうぞよろしくお願いいたします。
この文章を最後に、「解決」とさせていただきます。