マインスイーパについて
Posted: 2018年2月24日(土) 23:00
現在マインスイーパをCで作っていて、以下の点について困っています。
・82~141行目:最初のマスの指定で周囲8マスを開けた状態にする。
・143~162行目:最初に指定したマス+その周囲8マス以外に地雷を配置
・164~179行目:周りの地雷の数を示す数字(1~8)の代入
・236~246行目:地雷の入っていないマスを全て開けたかどうかの判定
このマインスイーパの仕様
・最初にクリックしたマスの周囲8マスのみ開く。
・広範囲にわたって0が連なっていても一気に解放されない。一つずつ開放。
・マスの開き方は、「(縦座標),(横座標),p」という形式。
・旗→!、?→?のチェックはマスを開くのと同様に行える。
・マスのチェックはOを用いて外せる。
・マスが解放されたかどうかはcell[][]に、地雷の有無、周りの地雷の数はcell_imformation[][]に、p,!,?,Oの状態をcell_state[][]に保存。(cell_state[][]は多分いらない)
…つまり、自分で大まかに作ったが、雑にソースを書いた為に混乱してしまっている状態です。最初から書き直しても同じことを繰り返してしまう気がするのでここをこうすればいいのでは?ということがあれば教えて頂きたいです。
・以下ソースコード
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
int main(){
int m,n,num,q,i,j,k,l,x,y,count,end,a,b,c,sum,temporary,total;
char start[5];
char decision;
time_t time1,time2;
int cell[30][24] = {0}; //開いている 1, 開いていない 0
int cell_imformation[30][24] = {0}; //地雷 9, なし 0~8
int cell_state[30][24] = {0}; //なし 0, ! 1, ? 2, O 3
int mine[720];
do{
printf(
"----- マインスイーパ -----\n\n"
"マスの数と地雷の数を「(縦,横),地雷の数」と入力してください。\n"
"縦:9~30、横:9~24、地雷の数:10~667\n"
"(指標・初級:(9,9),10、中級:(16,16),40、上級:(30,16),99)\n\n"
"> "
);
do{
scanf("(%d,%d),%d", &m, &n, &num);
if(m < 9 || m > 30 || n < 9 || n > 24 || num < 10 || num > m * n * 0.9264){
printf("マスが規格外又は地雷の数が不適切です。");
}
} while(m < 9 || m > 30 || n < 9 || n > 24 || num < 10 || num > m * n * 0.9264);
printf(
"\n----- ルール -----\n\n"
"・マスの座標とpを入力するとマスを開きます。例:2,3,p\n"
"・開いたマスの数字は周囲8マスの地雷の数です。\n"
"・マスに地雷が入っていた場合、即時終了です。\n"
"・マスの座標と!又は?を入力した場合、そのマスにチェックを入れられます。\n"
"・マスのチェックがついているときは開くことができません。\n"
"・チェックのついているマスの座標とOを入力するとチェックを外せます。\n"
"・地雷の入っていないマスを全て開くとゲームクリアです。\n"
"・できるだけ早いクリアタイムを目指しましょう!\n\n"
"・マスの意味:\n"
"0~9:開いたマス、周りの地雷の数を示す\n"
"O:未開封のマス、地雷か数かも分からない\n"
"!,?:チェックボックスを入れたマス、開くことはできない\n"
"*:地雷、開いたら即終了\n\n"
"スタートする場合は改行してください。 > "
);
q = getchar();
printf("\n");
time(&time1);
srand((unsigned int)time(NULL));
count = 0;
end = 0;
for(i = 1; i <= 720; i++){
mine = i;
}
for(i = 0; i < m; i++){
for(j = 0; j < n; j++){
printf(" O ");
}
printf("\n\n");
}
do{
printf("> ");
do{
scanf("%d,%d,%c", &x, &y, &decision);
if(x < 0 && x > m && y < 0 && y > n && decision != 'p' && decision != '!' && decision != '?' && decision != 'O'){
printf("\n不正な入力です。\n\n> ");
}
} while(x < 0 && x > m && y < 0 && y > n && decision != 'p' && decision != '!' && decision != '?' && decision != 'O');
printf("\n");
x = x - 1;
y = y - 1;
if(decision == 'p'){
cell[x][y] == 1;
if(count == 0){
if(x > 0 && x < m && y > 0 && y < n){
for(i = x - 1; i < x + 2; i++){
for(j = y - 1; j < y + 2; j++){
cell[j] = 1;
}
}
} else if(x == 0){
if(y == 0){
for(i = x; i < x + 2; i++){
for(j = y; j < y + 2; j++){
cell[j] = 1;
}
}
} else if(y == n){
for(i = x; i < x + 2; i++){
for(j = y - 1; j < y + 1; j++){
cell[j] = 1;
}
}
} else {
for(i = x; i < x + 2; i++){
for(j = y - 1; j < y + 2; j++){
cell[j];
}
}
}
} else if(x == m){
if(y == 0){
for(i = x - 1; i < x + 1; i++){
for(j = y; j < y + 2; j++){
cell[j] = 1;
}
}
} else if(y == n){
for(i = x - 1; i < x + 1; i++){
for(j = y - 1; j < y + 1; j++){
cell[j] = 1;
}
}
} else {
for(i = x - 1; i < x + 1; i++){
for(j = y - 1; j < y + 2; j++){
cell[j] = 1;
}
}
}
} else if(y == 0){
for(i = x - 1; i < x + 2; i++){
for(j = y; j < y + 2; j++){
cell[j] = 1;
}
}
} else if(y == n){
for(i = x - 1; i < x + 2; i++){
for(j = y - 1; j < y + 1; j++){
cell[j] = 1;
}
}
}
for(i = 0; i < m * n; i++){
a = rand() % m * n;
b = rand() % m * n;
c = mine[a];
mine[a] = mine;
mine = c;
}
i = 0;
j = 0;
do{
if(mine[i] / n <= x - 1 && mine[i] / n >= x + 1 && mine[i] % n <= y - 1 && mine[i] % n >= y + 1){
temporary = mine[i];
cell_imformation[temporary / n][temporary % n] = 9;
i++;
j++;
} else {
i++;
}
} while(j < num);
for(i = 0; i < m; i++){
sum = 0;
for(j = 0; j < n; j++){
for(k = m - 1; k < m + 2; k++){
for(l = n - 1; l < n + 2; l++){
if(k != m && l != n && cell_imformation[k][l] == 9){
sum++;
}
}
}
cell_imformation[i][j] = sum;
}
}
count++;
} else {
if(cell_imformation[x][y] == 9){
printf("!!!地雷を開けてしまいました!!!\n");
end++;
}
}
} else if(decision == '!'){
cell_state[x][y] = 1;
} else if(decision == '?'){
cell_state[x][y] = 2;
} else if(decision == 'O'){
cell_state[x][y] = 3;
}
for(i = 0; i < m; i++){
for(j = 0; j < n; j++){
printf(" ");
if(cell_state[i][m] == 0){
if(cell[i][j] == 0){
printf("O");
} else {
switch(cell_imformation[i][j]){
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
printf("%d", cell_imformation[i][j]);
break;
case 9:
printf("*");
break;
default:
printf("エラー\n");
break;
}
}
} else if(cell_state[i][j]){
printf("!");
} else if(cell_state[i][j]){
printf("?");
} else if(cell_state[i][j]){
printf("O");
}
printf(" ");
}
printf("\n\n");
}
total == 0;
for(i = 0; i < m; i++){
for(j = 0; j < n; j++){
if(cell_imformation[i][j] != 9){
if(cell[i][j] == 0){
total++;
}
}
}
}
if(total == 0){
end = 2;
}
} while(end != 1 && end != 2);
time(&time2);
if(end == 1){
printf("貴方の負けです。お疲れさまでした。\n");
} else {
printf("おめでとうございます!貴方の勝ちです!\n");
}
printf("今回の経過時間は %.1f秒 でした。\n\n", difftime(time2,time1));
printf("終了する場合は0を入力してください。 > ");
scanf("%d", &q);
} while(q != 0);
return 0;
}
・82~141行目:最初のマスの指定で周囲8マスを開けた状態にする。
・143~162行目:最初に指定したマス+その周囲8マス以外に地雷を配置
・164~179行目:周りの地雷の数を示す数字(1~8)の代入
・236~246行目:地雷の入っていないマスを全て開けたかどうかの判定
このマインスイーパの仕様
・最初にクリックしたマスの周囲8マスのみ開く。
・広範囲にわたって0が連なっていても一気に解放されない。一つずつ開放。
・マスの開き方は、「(縦座標),(横座標),p」という形式。
・旗→!、?→?のチェックはマスを開くのと同様に行える。
・マスのチェックはOを用いて外せる。
・マスが解放されたかどうかはcell[][]に、地雷の有無、周りの地雷の数はcell_imformation[][]に、p,!,?,Oの状態をcell_state[][]に保存。(cell_state[][]は多分いらない)
…つまり、自分で大まかに作ったが、雑にソースを書いた為に混乱してしまっている状態です。最初から書き直しても同じことを繰り返してしまう気がするのでここをこうすればいいのでは?ということがあれば教えて頂きたいです。
・以下ソースコード
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
int main(){
int m,n,num,q,i,j,k,l,x,y,count,end,a,b,c,sum,temporary,total;
char start[5];
char decision;
time_t time1,time2;
int cell[30][24] = {0}; //開いている 1, 開いていない 0
int cell_imformation[30][24] = {0}; //地雷 9, なし 0~8
int cell_state[30][24] = {0}; //なし 0, ! 1, ? 2, O 3
int mine[720];
do{
printf(
"----- マインスイーパ -----\n\n"
"マスの数と地雷の数を「(縦,横),地雷の数」と入力してください。\n"
"縦:9~30、横:9~24、地雷の数:10~667\n"
"(指標・初級:(9,9),10、中級:(16,16),40、上級:(30,16),99)\n\n"
"> "
);
do{
scanf("(%d,%d),%d", &m, &n, &num);
if(m < 9 || m > 30 || n < 9 || n > 24 || num < 10 || num > m * n * 0.9264){
printf("マスが規格外又は地雷の数が不適切です。");
}
} while(m < 9 || m > 30 || n < 9 || n > 24 || num < 10 || num > m * n * 0.9264);
printf(
"\n----- ルール -----\n\n"
"・マスの座標とpを入力するとマスを開きます。例:2,3,p\n"
"・開いたマスの数字は周囲8マスの地雷の数です。\n"
"・マスに地雷が入っていた場合、即時終了です。\n"
"・マスの座標と!又は?を入力した場合、そのマスにチェックを入れられます。\n"
"・マスのチェックがついているときは開くことができません。\n"
"・チェックのついているマスの座標とOを入力するとチェックを外せます。\n"
"・地雷の入っていないマスを全て開くとゲームクリアです。\n"
"・できるだけ早いクリアタイムを目指しましょう!\n\n"
"・マスの意味:\n"
"0~9:開いたマス、周りの地雷の数を示す\n"
"O:未開封のマス、地雷か数かも分からない\n"
"!,?:チェックボックスを入れたマス、開くことはできない\n"
"*:地雷、開いたら即終了\n\n"
"スタートする場合は改行してください。 > "
);
q = getchar();
printf("\n");
time(&time1);
srand((unsigned int)time(NULL));
count = 0;
end = 0;
for(i = 1; i <= 720; i++){
mine = i;
}
for(i = 0; i < m; i++){
for(j = 0; j < n; j++){
printf(" O ");
}
printf("\n\n");
}
do{
printf("> ");
do{
scanf("%d,%d,%c", &x, &y, &decision);
if(x < 0 && x > m && y < 0 && y > n && decision != 'p' && decision != '!' && decision != '?' && decision != 'O'){
printf("\n不正な入力です。\n\n> ");
}
} while(x < 0 && x > m && y < 0 && y > n && decision != 'p' && decision != '!' && decision != '?' && decision != 'O');
printf("\n");
x = x - 1;
y = y - 1;
if(decision == 'p'){
cell[x][y] == 1;
if(count == 0){
if(x > 0 && x < m && y > 0 && y < n){
for(i = x - 1; i < x + 2; i++){
for(j = y - 1; j < y + 2; j++){
cell[j] = 1;
}
}
} else if(x == 0){
if(y == 0){
for(i = x; i < x + 2; i++){
for(j = y; j < y + 2; j++){
cell[j] = 1;
}
}
} else if(y == n){
for(i = x; i < x + 2; i++){
for(j = y - 1; j < y + 1; j++){
cell[j] = 1;
}
}
} else {
for(i = x; i < x + 2; i++){
for(j = y - 1; j < y + 2; j++){
cell[j];
}
}
}
} else if(x == m){
if(y == 0){
for(i = x - 1; i < x + 1; i++){
for(j = y; j < y + 2; j++){
cell[j] = 1;
}
}
} else if(y == n){
for(i = x - 1; i < x + 1; i++){
for(j = y - 1; j < y + 1; j++){
cell[j] = 1;
}
}
} else {
for(i = x - 1; i < x + 1; i++){
for(j = y - 1; j < y + 2; j++){
cell[j] = 1;
}
}
}
} else if(y == 0){
for(i = x - 1; i < x + 2; i++){
for(j = y; j < y + 2; j++){
cell[j] = 1;
}
}
} else if(y == n){
for(i = x - 1; i < x + 2; i++){
for(j = y - 1; j < y + 1; j++){
cell[j] = 1;
}
}
}
for(i = 0; i < m * n; i++){
a = rand() % m * n;
b = rand() % m * n;
c = mine[a];
mine[a] = mine;
mine = c;
}
i = 0;
j = 0;
do{
if(mine[i] / n <= x - 1 && mine[i] / n >= x + 1 && mine[i] % n <= y - 1 && mine[i] % n >= y + 1){
temporary = mine[i];
cell_imformation[temporary / n][temporary % n] = 9;
i++;
j++;
} else {
i++;
}
} while(j < num);
for(i = 0; i < m; i++){
sum = 0;
for(j = 0; j < n; j++){
for(k = m - 1; k < m + 2; k++){
for(l = n - 1; l < n + 2; l++){
if(k != m && l != n && cell_imformation[k][l] == 9){
sum++;
}
}
}
cell_imformation[i][j] = sum;
}
}
count++;
} else {
if(cell_imformation[x][y] == 9){
printf("!!!地雷を開けてしまいました!!!\n");
end++;
}
}
} else if(decision == '!'){
cell_state[x][y] = 1;
} else if(decision == '?'){
cell_state[x][y] = 2;
} else if(decision == 'O'){
cell_state[x][y] = 3;
}
for(i = 0; i < m; i++){
for(j = 0; j < n; j++){
printf(" ");
if(cell_state[i][m] == 0){
if(cell[i][j] == 0){
printf("O");
} else {
switch(cell_imformation[i][j]){
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
printf("%d", cell_imformation[i][j]);
break;
case 9:
printf("*");
break;
default:
printf("エラー\n");
break;
}
}
} else if(cell_state[i][j]){
printf("!");
} else if(cell_state[i][j]){
printf("?");
} else if(cell_state[i][j]){
printf("O");
}
printf(" ");
}
printf("\n\n");
}
total == 0;
for(i = 0; i < m; i++){
for(j = 0; j < n; j++){
if(cell_imformation[i][j] != 9){
if(cell[i][j] == 0){
total++;
}
}
}
}
if(total == 0){
end = 2;
}
} while(end != 1 && end != 2);
time(&time2);
if(end == 1){
printf("貴方の負けです。お疲れさまでした。\n");
} else {
printf("おめでとうございます!貴方の勝ちです!\n");
}
printf("今回の経過時間は %.1f秒 でした。\n\n", difftime(time2,time1));
printf("終了する場合は0を入力してください。 > ");
scanf("%d", &q);
} while(q != 0);
return 0;
}