トップページ > 記事閲覧
マインスイーパーについて
名前:FFGX 日時: 2020/04/20 13:50

マインスイーパーを作っています。 #include<DxLib.h> #define ONE 20 #define PX 96 #define BOMB 40 typedef struct { bool bomb; bool mine; bool flag; }CELL; CELL cells[ONE][ONE]; int f[ONE][ONE]; int T[11]; int cx, cy; int count(int _x, int _y) { int n = 0; for (int y = -1; y <= 1; y++) for (int x = -1; x <= 1; x++) { if (x == 0 && y == 0) continue; int x2 = _x + x, y2 = _y + y; if (x2 < 0 || x2 >= ONE || y2 < 0 || y2 >= ONE) continue; if (cells[y2][x2].bomb) n++; } return n; } void P() { int s = PX / 6; for (int y = 0; y < ONE; y++) { for (int x = 0; x < ONE; x++) { DrawExtendGraph(x * s, y * s, x * s+s, y * s+s, T[],false); } } } void open(int _x, int _y) { if ( cells[_y][_x].bomb || !cells[_y][_x].mine || _x < 0 || _x >= ONE || _y < 0 || _y >= ONE || count(_x, _y) > 0 ) return; cells[_y][_x].mine = false; for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { if (x == 0 && y == 0) continue; int x2 = _x + x, y2 = _y + y; open(x2, y2); } } } int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { SetOutApplicationLogValidFlag(false); SetWindowText("マインスイーパー"); ChangeWindowMode(true); DxLib_Init(); LoadDivGraph("madia\\a.png", 11, 4, 3, 96, 96, T, false); SRand(GetRand(9999)); { int n = 0; do { int x = GetRand(ONE) % ONE, y = GetRand(ONE) % ONE; if (!cells[y][x].bomb) { cells[y][x].bomb = true; n++; } } while (n < BOMB); } for (int y = 0; y < ONE; y++) for (int x = 0; x < ONE; x++) cells[y][x].mine = true; bool exp = false; bool clear = false; while (1) { ClearDrawScreen(); P(); if (exp || clear) { WaitKey(); break; } while (1) { if ((GetMouseInput() & MOUSE_INPUT_LEFT) != 0) { } if ((GetMouseInput() & MOUSE_INPUT_RIGHT) != 0) { GetMousePoint(&cx, &cy); cells[cy / PX][cx / PX].flag = true; } } } WaitKey(); DxLib_End(); return 0; } T[]の中にcellsを渡して描画したいのですが、 bool形になっています それを配列化したいのですがどうすればよいのでしょうか。
メンテ

Page: 1 | 2 |

Re: マインスイーパーについて ( No.1 )
名前:管理人 日時:2020/04/21 10:42

> T[]の中にcellsを渡して描画したいのですが、 > bool形になっています > それを配列化したいのですがどうすればよいのでしょうか。 Tは要素数11の配列のようですが、それぞれ何の状態のときに配列の 何番目の要素のグラフィックハンドルで描画されたいのでしょうか?
メンテ
Re: マインスイーパーについて ( No.2 )
名前:FFGX 日時:2020/04/21 12:50

すみませんでした。Tの要素数は12で 開拓されていない状態、地雷が周りにない状態、1個ある状態、2個 ...8個、旗、地雷が詰まったのがa.pngです。 バックアップ用の配列をF[ONE][ONE]とします。 こちらに地雷の情報を埋め込んで、 一つづつ盤の状態を調べそのデータをfに書き込んで、 cells[y][x].mine = trueならその場所のデータを0(開拓されていない状態)にする。 cells[y][x].flag = trueならその場所のデータを11(旗)にする。 cells[y][x].bomb = trueならその場所のデータを0(開拓されていない状態)にする。 bombの周りに数値を振る。 もし開拓されていない状態をクリックしたらbombかどうかを調べる。 もし開拓されていない状態をクリックしたら地雷が周りにない状態かどうかを調べる。 地雷が周りにない状態ならば隣接する地雷が周りにない状態を開く。 その時に開く回数を1回増やし、数値を見えるようにする。 また、数値を開いた場合そこだけを開く。 という感じです
メンテ
Re: マインスイーパーについて ( No.3 )
名前:NNN 日時:2020/04/21 16:17

CELLにint numという変数を追加してそこに <cells[y][x].mine = trueならその場所のデータを0(開拓されていない状態)にする。 <cells[y][x].flag = trueならその場所のデータを11(旗)にする。 <cells[y][x].bomb = trueならその場所のデータを0(開拓されていない状態)にする。 この条件で値を代入して、T[ cells[y][x].num ]で良いのではないかと思いますが 質問者さんがどの部分が分からないのかが読み取れません。 個人的に他者にソースを見せる場合はTとかPとか本人しか分からない変数にせず ImagesやDrawCellsのような名前にするだけで意図を汲み取りやすくなります。
メンテ
Re: マインスイーパーについて ( No.4 )
名前:FFGX 日時:2020/04/22 07:24

DrawExtendGraph(x * s, y * s, x * s + s, y * s + s, Image[], false); この部分です。 意味が分からないです もっと具体的に説明してください。
メンテ
Re: マインスイーパーについて ( No.5 )
名前:NNN 日時:2020/04/22 08:25

No.2の回答でアルゴリズムはしっかり分かっているという認識で記載したのですが、具体的にどの段階が分からないのでしょうか? 1.CELLにint numという変数を追加して 2.この条件で値を代入して 3.T[ cells[y][x].num ]で良いのではないかと思います 例えば以下のようにすればすべてのマスが開拓されていない状態で描画されると思います DrawExtendGraph(x * s, y * s, x * s + s, y * s + s, T[0], false); なので後は[0]の部分を変数化して、 例えば旗の位置は「cells[y][x].num」が11になれば良いと思います
メンテ
Re: マインスイーパーについて ( No.6 )
名前:FFGX 日時:2020/04/22 10:18

わかりました。こんな感じでどうでしょうか。 #include<DxLib.h> #include<time.h> #define ONE 20 #define PX 96 #define BOMB 40 typedef struct { bool bomb; bool mine; bool flag; int num; }CELL; CELL cells[ONE][ONE]; int f[ONE][ONE]; int T[12]; int cx, cy; int count(int _x, int _y) { int n = 0; for (int y = -1; y <= 1; y++) for (int x = -1; x <= 1; x++) { if (x == 0 && y == 0) continue; int x2 = _x + x, y2 = _y + y; if (x2 < 0 || x2 >= ONE || y2 < 0 || y2 >= ONE) continue; if (cells[y2][x2].bomb) n++; } return n; } void P() { int s = PX / 6; for (int y = 0; y < ONE; y++) { for (int x = 0; x < ONE; x++) { DrawExtendGraph(x * s, y * s, x * s + s, y * s + s, T[cells[y][x].num], false); } } } void open(int _x, int _y) { if ( cells[_y][_x].bomb || !cells[_y][_x].mine || _x < 0 || _x >= ONE || _y < 0 || _y >= ONE || count(_x, _y) > 0 ) return; cells[_y][_x].mine = false; for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { if (x == 0 && y == 0) continue; int x2 = _x + x, y2 = _y + y; open(x2, y2); } } } void bomb_set() { int n = 0; SRand((unsigned int)time(NULL)); do { int x = GetRand(ONE) % ONE, y = GetRand(ONE) % ONE; if (!cells[y][x].bomb) { cells[y][x].bomb = true; n++; } } while (n < BOMB); } void mine_set() { for (int y = 0; y < ONE; y++) for (int x = 0; x < ONE; x++) cells[y][x].mine = true; } int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { SetOutApplicationLogValidFlag(false); SetWindowText("マインスイーパー"); ChangeWindowMode(true); DxLib_Init(); LoadDivGraph("madia\\a.png", 12, 4, 3, 96, 96, T, false); bomb_set(); mine_set(); bool exp = false; bool clear = false; while (1) { ClearDrawScreen(); P(); if (exp) { WaitKey(); break; } if (clear) { WaitKey(); break; } while (1) { if ((GetMouseInput() & MOUSE_INPUT_LEFT) != 0) { GetMousePoint(&cx, &cy); if (!cells[cy / PX][cx / PX].flag) { cells[cy][cx].mine = false; if (cells[cy / PX][cx / PX].bomb) { exp = true; for (int y = 0; y < ONE; y++) for (int x = 0; x < ONE; x++) { cells[y][x].mine; cells[y][x].flag = false; } break; } { clear = true; for (int y = 0; y < ONE; y++) { for (int x = 0; x < ONE; x++) { if (!cells[y][x].bomb && cells[y][x].mine) { clear = false; } } } } for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { if (x == 0 && y == 0) continue; int x2 = cx + x, y2 = cy + y; open(x2, y2); } } } if ((GetMouseInput() & MOUSE_INPUT_RIGHT) != 0) { GetMousePoint(&cx, &cy); cells[cy / PX][cx / PX].flag = !cells[cy / PX][cx / PX].flag; if (cells[cy / PX][cx / PX].num == -0) { if (cells[cy / PX][cx / PX].flag) { cells[cy / PX][cx / PX].num = 10; } else { cells[cy / PX][cx / PX].num = 0; } } } } } if (ProcessMessage()) { break; } if (CheckHitKey(KEY_INPUT_ESCAPE)) { break; } } DxLib_End(); return 0; } これだと何も起こらないのでどこが悪いか教えてください。 1.地雷をランダムに置く 2.地雷の8方向に数値を振る 3.もしそれが重なったなら数値をインクリメントする 4.鉱石で隠す 5.もし左クリックしたら 6.もしそこが地雷ならゲームオーバー 7.もしそこが数値が、地雷が置いてない場所なら隣接する数値、地雷が置いてない場所を開く。その時に隣接する数値を開く 8.もしそこが数値だったらそこだけを開く 9.もしそこが旗だったら開けない 10.もし右クリックしたら旗を立てる 11.旗の所で右クリックすると旗を外す 12.地雷の数だけ旗を設置したかつ地雷の位置があってたらゲームクリア という流れです
メンテ
Re: マインスイーパーについて ( No.7 )
名前:名無三 日時:2020/04/22 13:42

通るわけないだろってとこ > cells[cy][cx].mine = false; あと配列はなぜ(y,x)で示してるの?普通(x,y)だと思うけど
メンテ
Re: マインスイーパーについて ( No.8 )
名前:FFGX 日時:2020/04/22 14:41

初歩的な間違いでした。すみません。 (y,x)が逆だと、[2][1]が[1][2]になるからです。
メンテ
Re: マインスイーパーについて ( No.9 )
名前:FFGX 日時:2020/04/22 17:24

#include<DxLib.h> #include<time.h> #define ONE 18 #define PX 96 #define BOMB 40 int cells[ONE][ONE]; //数値&地雷のデータ int f[ONE][ONE]; //mine & 0 & 旗のデータ int CELL[ONE][ONE]; //すべてのデータ int T[12]; int cx, cy; int count(int _x, int _y) { int n = 0; for (int y = -1; y <= 1; y++) for (int x = -1; x <= 1; x++) { if (x == 0 && y == 0) continue; int x2 = _x + x, y2 = _y + y; if (x2 < 0 || x2 >= ONE || y2 < 0 || y2 >= ONE) continue; if (cells[y2][x2] == 11) n++; } return n; } void Paint() { int s = PX / 6; for (int y = 0; y < ONE; y++) { for (int x = 0; x < ONE; x++) { DrawExtendGraph(x * s, y * s, x * s + s, y * s + s, T[CELL[y][x]], false); } } } void Drawnum(int _x, int _y) { for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { if (x == 0 && y == 0) { continue; } int num = count(x, y); if (num == 0) { cells[_y][_x] = 0; } else { cells[_y][_x] = num; } } } } void open(int _x, int _y) { if ( cells[_y][_x] == 11 || f[_y][_x] == 10 || !f[_y][_x] == 0 || _x < 0 || _x >= ONE || _y < 0 || _y >= ONE || count(_x, _y) > 0 ) return; f[_y][_x] = 1; for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { if (x == 0 && y == 0) continue; int x2 = _x + x, y2 = _y + y; open(x2, y2); } } } void Data_set() { for (int y = 0; y < ONE; y++) { for (int x = 0; x < ONE; x++) { if (cells[y][x] == 0) { if (f[y][x] == 0) { CELL[y][x] = 0; continue; } else if (f[y][x] == 10) { CELL[y][x] = 10; continue; } else if (f[y][x] == 1) { CELL[y][x] = 1; continue; } } int num = cells[y][x]; if (num >= 2 && num <= 9) { if (f[y][x] == 0) { CELL[y][x] = 0; continue; } else if (f[y][x] == 1) { CELL[y][x] = num; continue; } } if (cells[y][x] == 11) { if (f[y][x] == 0) { CELL[y][x] = 0; continue; } } } } } void bomb_set() { int n = 0; SRand((unsigned int)time(NULL)); do { int x = GetRand(ONE), y = GetRand(ONE); if (cells[y][x] != 11) { cells[y][x] = 11; Drawnum(y, x); n++; } } while (n < BOMB); } void mine_set() { for (int y = 0; y < ONE; y++) for (int x = 0; x < ONE; x++) f[y][x] = 0; } int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { SetOutApplicationLogValidFlag(false); SetWindowText("マインスイーパー"); ChangeWindowMode(true); DxLib_Init(); LoadDivGraph("madia\\a.png", 11, 4, 3, 96, 96, T, false); bomb_set(); mine_set(); bool exp = false; bool clear = false; while (1) { Data_set(); ClearDrawScreen(); Paint(); if (exp) { WaitKey(); break; } if (clear) { WaitKey(); break; } while (1) { if ((GetMouseInput() & MOUSE_INPUT_LEFT) != 0) { GetMousePoint(&cx, &cy); if (f[cy / PX][cx / PX] != 10) { f[cy / PX][cx / PX] = 1; if (cells[cy / PX][cx / PX] == 12) { exp = true; break; } { clear = true; for (int y = 0; y < ONE; y++) { for (int x = 0; x < ONE; x++) { if (cells[y][x] != 11 && f[y][x] == 0) { clear = false; } } } } for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { if (x == 0 && y == 0) continue; int x2 = cx / PX + x, y2 = cy / PX + y; open(x2, y2); } } } } if ((GetMouseInput() & MOUSE_INPUT_RIGHT) != 0) { GetMousePoint(&cx, &cy); } if ((GetMouseInput() & MOUSE_INPUT_RIGHT) != 0 && (GetMouseInput() & MOUSE_INPUT_LEFT) != 0) { GetMousePoint(&cx, &cy); if (cells[cy / PX][cx / PX] == 12) { exp = true; break; } int flagcount; if (f[cy / PX][cx / PX] >= 2 && f[cy / PX][cx / PX] <= 9) { switch (f[cy / PX][cx / PX]) { case 2: flagcount = 1; break; case 3: flagcount = 2; break; case 4: flagcount = 3; break; case 5: flagcount = 4; break; case 6: flagcount = 5; break; case 7: flagcount = 6; break; case 8: flagcount = 7; break; case 9: flagcount = 8; break; } int num = 0; for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { if (x == 0 && y == 0) { continue; } int x2 = cx + x, y2 = cy + y; if (f[y2 / PX][x2 / PX] == 10) { num++; } } } } clear = true; for (int y = 0; y < ONE; y++) { for (int x = 0; x < ONE; x++) { if (cells[y][x] != 11 && f[y][x] == 0) { clear = false; } } } for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { if (x == 0 && y == 0) continue; int x2 = cx / PX + x, y2 = cy / PX + y; open(x2, y2); } } } } if (ProcessMessage() == -1) break; if (CheckHitKey(KEY_INPUT_ESCAPE) == 1) break; } DxLib_End(); return 0; } このコードだと何も反応してくれません。 何か悪いところはあるでしょうか? 補足 12.の前に 「もし旗の数と数値の数が同じで、数値に右クリックと左クリックを押すと 他の開かれてないセルをまとめて開く」 を忘れていました。すみませんでした。
メンテ

Page: 1 | 2 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存