トップページ > 記事閲覧
マインスイーパーについて
名前: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.10 )
名前:Tatu 日時:2020/04/23 18:50

>このコードだと何も反応してくれません。 ESCキーを押したらウィンドウを閉じるコードからやり直してみてはどうでしょうか。
メンテ
Re: マインスイーパーについて ( No.11 )
名前:管理人 日時:2020/04/23 23:34

> このコードだと何も反応してくれません。 > 何か悪いところはあるでしょうか? はい、あります お使いの開発環境は何でしょうか? もし Visual Studio をお使いでしたら、F10キーを押して1行づつ実行して、 意図した通りにプログラムが実行されているか確認してみてください
メンテ
Re: マインスイーパーについて ( No.12 )
名前:FFGX 日時:2020/04/24 06:30

>お使いの開発環境は何でしょうか? Visual Studio 2019 dxライブラリv3.21です >ESCキーを押したらウィンドウを閉じるコードからやり直してみてはどうでしょうか。 つまりこういうことでしょうか。 CheckHitKey(KEY_INPUT_ESCAPE) != 0
メンテ
Re: マインスイーパーについて ( No.13 )
名前:FFGX 日時:2020/04/24 11:42

このサイトで頑張ってみます ttps://ipx.hatenablog.com/entry/2015/11/26/073858
メンテ
Re: マインスイーパーについて ( No.14 )
名前:FFGX 日時:2020/04/25 07:16

上記のサイトで自分なりにやってみました。 しかし、数値を配置する処理ができません。 #include<DxLib.h> #include<time.h> #define ONE 16 #define PX 96 #define BOMB 40 int cells[ONE][ONE]; int bomb[ONE][ONE]; int T[12]; int mx, my; int s = PX / 3; void data_set() { for (int y = 0; y < ONE; y++) { for (int x = 0; x < ONE; x++) { cells[y][x] = bomb[y][x]; } } } int bomb_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 (bomb[y2][x2] == 11) n++; } } return n; } void bomb_set() { int count = 0; SRand((unsigned int)time(NULL)); do { int x = GetRand(ONE); int y = GetRand(ONE); if (bomb[y][x] != 11) { bomb[y][x] = 11; count++; } } while (count < BOMB); } void Paint() { 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]], false); } } } void num_set() { } int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { SetOutApplicationLogValidFlag(false); SetWindowText("マインスイーパー"); ChangeWindowMode(true); DxLib_Init(); bool exp = false; bool clear = false; LoadDivGraph("madia\\a.png", 12, 4, 3, 96, 96, T, false); bomb_set(); while (1) { if (exp) { data_set(); Paint(); DrawString(480, 0, "ゲームオーバー", GetColor(255, 255, 255)); WaitKey(); break; } if (clear) { Paint(); DrawString(480, 0, "クリア", GetColor(255, 255, 255)); WaitKey(); break; } ClearDrawScreen(); Paint(); if ((GetMouseInput() & MOUSE_INPUT_LEFT) != 0) { GetMousePoint(&mx, &my); if (cells[my / s][mx / s] != 10) if (bomb[my / s][mx / s] == 12) { exp = true; continue; } { clear = true; for (int y = 0; y < ONE; y++) for (int x = 0; x < ONE; x++) if (cells[y][x] != 11 && cells[y][x] == 0) clear = false; } WaitTimer(150); } if ((GetMouseInput() & MOUSE_INPUT_RIGHT) != 0) { GetMousePoint(&mx, &my); if (cells[my / s][mx / s] == 0) cells[my / s][mx / s] = 10; else cells[my / s][mx / s] = 0; WaitTimer(150); } if (ProcessMessage() == -1) { break; } if (CheckHitKey(KEY_INPUT_ESCAPE) != 0) { break; } } DxLib_End(); return 0; } num_set が数値を配置する関数です。 助けてください。
メンテ
Re: マインスイーパーについて ( No.15 )
名前:Tatu 日時:2020/04/25 14:10

> num_set が数値を配置する関数です。 数値というのはおそらくマスを開いた時に周囲に地雷がいくつあるかを示す数字のことだと思いますが、 num_set()をどこで呼び出すつもりでしょうか? bomb_set(); の後や if (bomb[my / s][mx / s] == 12) { exp = true; continue; } の後が考えられますが。
メンテ
Re: マインスイーパーについて ( No.16 )
名前:FFGX 日時:2020/04/25 17:07

bomb_setの後に呼び出すつもりです。 となるとnum_setを前に呼びます。すみませんでした。 補足 void num_set() {はvoid num_set(int _x, int _y) {でした 1.座標を入力させる 2.もしそこが地雷だったら終了 3.相対座標を求め、bomb_count関数で地雷の数を調べる 4.そこが地雷だったらn[ONE][ONE]というグローバル変数にインクリメントする 5.すべて調べたならn[ONE][ONE]のすべてのデータをインクリメントする という流れです。
メンテ
Re: マインスイーパーについて ( No.17 )
名前:Tatu 日時:2020/04/25 18:18

> bomb_setの後に呼び出すつもりです。 それでは以下のようにしてみてはどうでしょう。 num_set()で行う処理 全てのマスに対して処理を行う。それぞれのマスについて そのマスに地雷がある場合、地雷の数を数えないでn[y][x]を0とする。 そのマスに地雷がない場合、bomb_countで周りにある地雷の数を調べ、n[y][x]をその数にする。 マスをクリックされた時に行う処理 そのマスが地雷である場合、ゲームオーバーとする。 追加: そのマスが地雷でない場合、cell[y][x]の値をn[y][x]に応じた値とする。 クリア条件を満たしているか調べる。
メンテ
Re: マインスイーパーについて ( No.18 )
名前:FFGX 日時:2020/04/25 20:24

なるほど。参考にさせて頂きます。
メンテ
Re: マインスイーパーについて ( No.19 )
名前:FFGX 日時:2020/04/25 20:40

訂正したのが 前略 void num_set() { for (int y = 0; y < ONE; y++) { for (int x = 0; x < ONE; x++) { if (bomb[y][x] != 12) { int count = bomb_count(x, y); n[y][x] = count; } else n[y][x] = 0; } } } 中略 GetMousePoint(&mx, &my); if (cells[my / s][mx / s] != 10) { if (bomb[my / s][mx / s] == 12) { exp = true; continue; } cells[my / s][mx / s] = n[my / s][mx / s]; } { clear = true; for (int y = 0; y < ONE; y++) for (int x = 0; x < ONE; x++) if (cells[y][x] != 11 && cells[y][x] == 0) clear = false; } WaitTimer(150); 後略 これでいいでしょうか
メンテ
Re: マインスイーパーについて ( No.20 )
名前:Tatu 日時:2020/04/25 21:19

> これでいいでしょうか これでいいかどうかを決めるのは私ではなく、あなた自身です。 実行してみましたか? もし、実行して何か問題があればその問題がどういうものか書いてみてください。
メンテ
Re: マインスイーパーについて ( No.21 )
名前:FFGX 日時:2020/04/26 06:16

地雷をクリックしても地雷が表示されないです
メンテ
Re: マインスイーパーについて ( No.22 )
名前:FFGX 日時:2020/04/26 11:19

#include<DxLib.h> #include<time.h> #define ONE 16 #define PX 96 #define BOMB 40 int cells[ONE][ONE]; int T[12]; int mx, my; int s = PX / 3; int bomb_count(int _x, int _y) { int n = 0; for (int y = -1; y < 1; y++) { for (int x = 0; 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() { 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]], false); } } } void bomb_set() { int count = 0; int count2 = 1; SRand((unsigned int)time(NULL)); do { int x1 = GetRand(ONE - 1), y1 = GetRand(ONE - 1); if (cells[y1][x1] != 11) { cells[y1][x1] = 11; count++; for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { if (x == 0 && y == 0) continue; int x2 = x1 + x, y2 = y1 + y; cells[y2][x2] = bomb_count(x2, y2) + 1; } } } } while (count < BOMB); } int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { SetOutApplicationLogValidFlag(false); SetWindowText("マインスイーパー"); ChangeWindowMode(true); DxLib_Init(); bool exp = false; bool clear = false; LoadDivGraph("madia\\a.png", 12, 4, 3, 96, 96, T, false); bomb_set(); while (1) { if (exp) { DrawString(480, 0, "残念", GetColor(255, 255, 255)); break; } if (clear) { DrawString(480, 0, "クリア", GetColor(255, 255, 255)); break; } ClearDrawScreen(); Paint(); if (GetMouseInput() & MOUSE_INPUT_LEFT) { GetMousePoint(&mx, &my); if (cells[my / s][mx / s] == 11) { exp = true; continue; } if (cells[my / s][mx / s] != 10) { } } if (GetMouseInput() & MOUSE_INPUT_RIGHT) { } if (GetMouseInput() & MOUSE_INPUT_LEFT && GetMouseInput() & MOUSE_INPUT_RIGHT) { } if (ProcessMessage() == -1) { break; } if (CheckHitKey(KEY_INPUT_ESCAPE) != 0) { break; } } DxLib_End(); return 0; } これだと地雷しか表示されません どうすればいいでしょうか
メンテ
Re: マインスイーパーについて ( No.23 )
名前:Tatu 日時:2020/04/26 13:47

>>No.21 地雷かどうかの判定が間違っていないか確認してみてください。
メンテ
Re: マインスイーパーについて ( No.24 )
名前:FFGX 日時:2020/04/26 12:22

前略 int vector[8][2] = { {-1,-1}, {0,-1}, {1,-1}, {1,0}, {1,1}, {0,1}, {-1,1}, {-1,0}, }; int s = PX / 3; int bomb_count(int _x, int _y) { int n = 0; for (int i = 0; i < 8; i++) { int x2 = _x + vector[i][0], y2 = _y + vector[i][1]; if (x2 < 0 || x2 >= ONE || y2 < 0 || y2 >= ONE) continue; if (cells[y2][x2] == 11) n++; } return n; } void Paint() { 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]], false); } } } void bomb_set() { int count = 0; int count2 = 1; SRand((unsigned int)time(NULL)); do { int x = GetRand(ONE - 1), y = GetRand(ONE - 1); if (cells[y][x] != 11) { cells[y][x] = 11; count++; for (int i = 0; i < 8; i++) { int x2 = x + vector[i][0], y2 = y + +vector[i][1]; cells[y2][x2] = bomb_count(x2, y2); } } } while (count < BOMB); } 後略 作りかけですが作ってみました。 ですが数値がおかしかったのです。 何が悪いでしょうか?
メンテ
Re: マインスイーパーについて ( No.25 )
名前:Tatu 日時:2020/04/26 13:45

no.19を投稿した時のコードに対して以下を確認してください。 ・地雷の判定は正しいか。 ・num_setの呼び出しの追加を忘れていないか。 ・bomb_countは正しく動いているか。 ・cells[y][x]とn[y][x]の対応は正しいか。 n[0][0]が1の場合、cells[0][0]はいくつにするとよさそうか。
メンテ
Re: マインスイーパーについて ( No.26 )
名前:FFGX 日時:2020/04/28 12:19

わかりました。 返信遅くなりすみません。
メンテ
Re: マインスイーパーについて ( No.27 )
名前:FFGX 日時:2020/05/03 20:23

#include<DxLib.h> #include<time.h> #define ONE 18 #define PX 96 #define BOMB 40 int cells[ONE][ONE]; int CELLS[ONE][ONE]; int T[12]; int mx, my; int s = PX / 4; int vector[8][2] = { {-1,-1}, {0,-1}, {1,-1}, {1,0}, {1,1}, {0,1}, {-1,1}, {-1,0}, }; int bomb_count(int _x, int _y) { int n = 1; for (int v = 0; v < 8; v++) { int x2 = _x + vector[v][0], y2 = _y + vector[v][1]; if (x2 < 0 || x2 >= ONE || y2 < 0 || y2 >= ONE) continue; if (CELLS[y2][x2] == 11) n++; } return n; } void num_set(int _x, int _y) { for (int v = 0; v < 8; v++) { int x2 = _x + vector[v][0], y2 = _y + vector[v][1]; CELLS[y2][x2] = bomb_count(x2, y2); } } void Paint() { 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]], false); } } } void bomb_set() { int count = 0; int count2 = 1; SRand((unsigned int)time(NULL)); do { int x = GetRand(ONE - 1), y = GetRand(ONE - 1); if (CELLS[y][x] != 11) { CELLS[y][x] = 11; count++; num_set(x, y); } } while (count < BOMB); } void Data_set() { for (int y = 0; y < ONE; y++) { for (int x = 0; x < ONE; x++) { CELLS[y][x] = cells[y][x]; } } } int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { SetOutApplicationLogValidFlag(false); SetWindowText("マインスイーパー"); ChangeWindowMode(true); DxLib_Init(); bool exp = false; bool clear = false; LoadDivGraph("madia\\a.png", 12, 4, 3, 96, 96, T, false); while (1) { Data_set(); if (exp) { DrawString(480, 0, "残念", GetColor(255, 255, 255)); break; } if (clear) { DrawString(480, 0, "クリア", GetColor(255, 255, 255)); break; } ClearDrawScreen(); Paint(); if (GetMouseInput() & MOUSE_INPUT_LEFT) { GetMousePoint(&mx, &my); if (cells[my / s][mx / s] == 10) { continue; } cells[my / s][mx / s] = 11; num_set(mx / s, my / s); WaitTimer(150); } if (GetMouseInput() & MOUSE_INPUT_RIGHT) { GetMousePoint(&mx, &my); if (cells[my / s][mx / s] == 10) { cells[my / s][mx / s] = 0; } else if (cells[my / s][mx / s] == 0) { cells[my / s][mx / s] = 10; } WaitTimer(150); } if (GetMouseInput() & MOUSE_INPUT_LEFT && GetMouseInput() & MOUSE_INPUT_RIGHT) { } if (ProcessMessage() == -1) { break; } if (CheckHitKey(KEY_INPUT_ESCAPE) != 0) { break; } } DxLib_End(); return 0; } このコードでnum_set(mx / s, my / s);と入力しました。 ですがyが0の時にしか反応しないのです どうにかなりませんか?
メンテ
Re: マインスイーパーについて ( No.28 )
名前:Tatu 日時:2020/05/04 00:50

私ではどうにもならない気がしてきたので、 No.25の時点ではこういう感じになるんだろうなと思っていたコードを掲載します。 #include<DxLib.h> #include<time.h> #define ONE 15 #define PX 96 #define BOMB 40 int flag_num = 0; int cells[ONE][ONE]; //マスに表示する画像の番号 int bomb[ONE][ONE]; //マスに地雷があるかどうか int n[ONE][ONE]; //マスの周囲にある地雷の数 int T[12]; //イメージハンドル int mx, my; int s = PX / 3; int vector[8][2] = { {-1,-1}, {-1,0}, {-1,1}, {0,-1}, {0,1}, {1,-1}, {1,0}, {1,1} }; void data_set() { for(int y = 0; y < ONE; y++) { for(int x = 0; x < ONE; x++) { cells[y][x] = bomb[y][x]; } } } int bomb_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(bomb[y2][x2] == 11) n++; } } return n; } void bomb_set() { int count = 0; SRand((unsigned int)time(NULL)); do { int x = GetRand(ONE - 1); int y = GetRand(ONE - 1); if(bomb[y][x] != 11) { bomb[y][x] = 11; count++; } } while(count < BOMB); } void Paint() { 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]], false); } } DrawFormatString(480,20, 0xFFFFFF,"旗/爆弾: %d/%d", flag_num, BOMB); } void num_set() { for(int y = 0; y < ONE; y++) { for(int x = 0; x < ONE; x++) { if(bomb[y][x] != 11) { int count = bomb_count(x, y); n[y][x] = count; } else n[y][x] = 0; } } } //クリアかどうかをチェックする。クリアなら1、クリアでないなら0を返す。 int clear_check() { int clear = 1; for(int y = 0; y < ONE; y++) { for(int x = 0; x < ONE; x++) { if(bomb[y][x] != 11 && (cells[y][x] == 0 || cells[y][x] == 10) ) { clear = 0; } } } return clear; } //指定された場所が盤内なら1を返し、そうでないなら0を返す。 int in_board(int x, int y) { if(x >= 0 && x < ONE && y >= 0 && y < ONE) return 1; return 0; } //指定されたマスを開く。地雷のマスを開いた場合は1を返す。 int open(int x, int y) { if(cells[y][x] == 0) { if(bomb[y][x] == 11) { return 1; } cells[y][x] = n[y][x] + 1; if(n[y][x] == 0) { for(int i = 0; i < 8; ++i) { int x2 = x + vector[i][0]; int y2 = y + vector[i][1]; if(in_board(x2, y2) == 0) continue; open(x2, y2); } } } return 0; } //指定された場所の数字のマスの周囲を開く。地雷のマスを開いた場合は1を返す。 int around_num_open(int x, int y) { int num = n[y][x]; int flag = 0; int exp = 0; int x2, y2; //マスの周囲の旗の数がマスの数字と一致しているか調べる。 for(int i = 0; i < 8; ++i) { x2 = x + vector[i][0]; y2 = y + vector[i][1]; if(in_board(x2, y2) == 0) continue; if(cells[y2][x2] == 10) ++flag; } //マスの周囲の旗の数がマスの数字と一致している時のみ開く。 if(num == flag) { for(int i = 0; i < 8; ++i) { x2 = x + vector[i][0]; y2 = y + vector[i][1]; if(in_board(x2, y2) == 0) continue; if(open(x2, y2) == 1) { exp = 1; } } } return exp; } int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { SetOutApplicationLogValidFlag(false); SetWindowText("マインスイーパー"); ChangeWindowMode(true); DxLib_Init(); bool exp = false; bool clear = false; LoadDivGraph("madia\\a.png", 12, 4, 3, 96, 96, T, false); bomb_set(); num_set(); while(1) { if(exp) { data_set(); Paint(); DrawString(480, 0, "ゲームオーバー", GetColor(255, 255, 255)); WaitKey(); break; } if(clear) { Paint(); DrawString(480, 0, "クリア", GetColor(255, 255, 255)); WaitKey(); break; } ClearDrawScreen(); Paint(); if((GetMouseInput() & MOUSE_INPUT_LEFT) != 0) { GetMousePoint(&mx, &my); exp = open( mx / s, my / s); if(exp) continue; clear = clear_check(); WaitTimer(150); } if((GetMouseInput() & MOUSE_INPUT_RIGHT) != 0) { GetMousePoint(&mx, &my); if(cells[my / s][mx / s] == 0) { cells[my / s][mx / s] = 10; ++flag_num; } else if(cells[my / s][mx / s] == 10) { cells[my / s][mx / s] = 0; --flag_num; } WaitTimer(150); } if((GetMouseInput() & MOUSE_INPUT_LEFT) != 0 && (GetMouseInput() & MOUSE_INPUT_RIGHT) != 0) { if(cells[my / s][mx / s] >= 2 && cells[my / s][mx / s] <= 9) { exp = around_num_open(mx / s, my / s); clear = clear_check(); } } if(ProcessMessage() == -1) { break; } if(CheckHitKey(KEY_INPUT_ESCAPE) != 0) { break; } } DxLib_End(); return 0; }
メンテ
Re: マインスイーパーについて ( No.29 )
名前:FFGX (解決) 日時:2020/05/04 06:22

ありがとうございます。 マインスイーパーをつくるにはまだまだでした。
メンテ

Page: 1 | 2 |

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

   クッキー保存