掃雷 (防止第一次被炸死和展開)
阿新 • • 發佈:2019-01-27
寫了一個掃雷10*10格子,實現
1.第一次不會被炸死 。
2.選擇座標後,實現周圍沒有雷格子的展開。
注:下文中提到 “ 區域 ” 均可理解為 “ 座標 ”
Mine Clearance.h(標頭檔案)
#ifndef __Mine_Clearance__ #define __Mine_Clearance__ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <time.h> #define M 9 //定義炸彈數量。 #define ROW 11 //定義棋盤大小。 #define COL 11 void init(char mine[ROW][COL], char show[ROW][COL]); //宣告game.c中的函式。 void displayboard(char show[ROW][COL]); void displaymine(char mine[ROW][COL]); void Set_Mine(char mine[ROW][COL], int m); void sweep_Mine(char mine[ROW][COL], int x, int y); int if_success(char mine[ROW][COL], char show[ROW][COL], int m ); void prevent_first_death(char mine[ROW][COL], int x, int y); int Num_boms(char mine[ROW][COL], int x, int y); void spread(char mine[ROW][COL], char show[ROW][COL], int x, int y); #endif
game.c(函式檔案)
#include "Mine Clearance.h" //printf("%3d\n", ' '); 32 //printf("%3d\n", '!'); 33 //printf("%3d\n", '*'); 42 //printf("%3d\n", '0'); 48 //printf("%3d\n", '1'); 49 // void init(char mine[ROW][COL], char show[ROW][COL]) //初始化雷盤和展示盤陣列,大小設定為11*11. { int i, j; for (i = 0; i < ROW-1 ; i++) { for (j = 0; j < COL-1; j++) //ROW-1只設置10*10的雷盤,陣列未被初始化的部分會自動設為'0', { mine[i][j] = ' '; //方便之後對 邊界區域的展開函式 和 雷數統函式 的呼叫。
show[i][j] = '*';
} } } void displayboard(char show[ROW][COL]) //向用戶展示盤。 { int i, j; printf(" |"); for (i = 1; i <= 10; i++) { printf("%d ", i); } printf("\n--|--------------------\n"); for (i = 0; i < ROW-1; i++) { printf("%2d|", i + 1); for (j = 0; j < COL-1; j++) { printf("%c ",show[i][j]); } printf("\n"); } } void displaymine(char mine[ROW][COL]) //展示雷盤,測試時使用。 (正常遊戲時在test.c中註釋掉即可)。
{
int i, j;
printf(" |");
for (i = 1; i <= 10; i++)
{
printf("%d ", i);
}
printf("\n--|--------------------\n");
for (i = 0; i < ROW-1; i++)
{
printf("%2d|", i + 1);
for (j = 0; j < COL-1; j++)
{
printf("%c ", mine[i][j]);
}
printf("\n");
}
}
void Set_Mine(char mine[ROW][COL], int m) //隨機放置雷,可以通過在標頭檔案中修改 M 的定義值從而修改 m的大小,即改變佈置的雷數。
{
int x, y;
while (m)
{
x = rand() % 10 + 0;
y = rand() % 10 + 0;
if (mine[x][y] == ' ')
{
mine[x][y] = '!';
m--;
}
}
m = M;
}
int Num_boms(char mine[ROW][COL], int x, int y) //統計周邊的雷數。
{
int count = 0;
if (mine[x - 1][y - 1] == '!')
{
count++;
}
if (mine[x - 1][y] == '!')
{
count++;
}
if (mine[x - 1][y + 1] == '!')
{
count++;
}
if (mine[x][y + 1] == '!')
{
count++;
}
if (mine[x + 1][y + 1] == '!')
{
count++;
}
if (mine[x + 1][y] == '!')
{
count++;
}
if (mine[x + 1][y - 1] == '!')
{
count++;
}
if (mine[x][y - 1] == '!')
{
count++;
}
return count;
}
void spread(char mine[ROW][COL], char show[ROW][COL], const x, const y) //擴充套件函式,向(x,y)周邊的八個區域進行擴充套件。
{
int ret, i, j;
int a, b;
a = x;
b = y;
if ((x >=0) //x,y值得大小應在陣列座標內,不做限定的話會造成死迴圈,使系統崩潰。
&& (x <= 9)
&& (y >=0)
&& (y <=9))
{
if (mine[x - 1][y - 1] == ' ') //如果該區域不是雷。
{
a = x - 1;
b = y - 1;
ret = Num_boms(mine, a, b); //返回以該區域為中心雷的數量。
if (ret == 0) //若在這八個區域中哪個區域的返回炸彈數值為0,即ret==0,
{
show[a][b] = ' '; //如果周圍沒有雷就向玩家展示‘ ’空格。
mine[a][b] = '0'; //將雷盤中的區域改為 ‘0’可方便測試用。
spread(mine, show, a, b); //則將這個區域的座標賦值個x和y,再次進行展開。
}
else
{
show[a][b] = '0' + ret;
mine[a][b] = '0';
}
}
if (mine[x][y - 1] == ' ') //以下的另外七個區域均相同。
{
a = x;
b = y - 1;
ret = Num_boms(mine, a, b);
if (ret == 0)
{
show[a][b] = ' ';
mine[a][b] = '0';
spread(mine, show, a, b);
}
else
{
show[a][b] = '0' + ret;
mine[a][b] = '0';
}
}
if (mine[x - 1][y] == ' ')
{
a = x - 1;
b = y;
ret = Num_boms(mine, a, b);
if (ret == 0)
{
show[a][b] = ' ';
mine[a][b] = '0';
spread(mine, show, a, b);
}
else
{
show[a][b] = '0' + ret;
mine[a][b] = '0';
}
}
if (mine[x + 1][y - 1] == ' ')
{
a = x + 1;
b = y - 1;
ret = Num_boms(mine, a, b);
if (ret == 0)
{
show[a][b] = ' ';
mine[a][b] = '0';
spread(mine, show, a, b);
}
else
{
show[a][b] = '0' + ret;
mine[a][b] = '0';
}
}
if (mine[x + 1][y] == ' ')
{
a = x + 1;
b = y;
ret = Num_boms(mine, a, b);
if (ret == 0)
{
show[x + 1][y] = ' ';
mine[a][b] = '0';
spread(mine, show, a, b);
}
else
{
show[x + 1][y] = '0' + ret;
mine[a][b] = '0';
}
}
if (mine[x + 1][y + 1] == ' ')
{
a = x + 1;
b = y + 1;
ret = Num_boms(mine, a, b);
if (ret == 0)
{
show[x + 1][y + 1] = ' ';
mine[a][b] = '0';
spread(mine, show, a, b);
}
else
{
show[x + 1][y + 1] = '0' + ret;
mine[a][b] = '0';
}
}
if (mine[x][y + 1] == ' ')
{
a = x;
b = y + 1;
ret = Num_boms(mine, a, b);
if (ret == 0)
{
show[x][y + 1] = ' ';
mine[a][b] = '0';
spread(mine, show, a, b);
}
else
{
show[x][y + 1] = '0' + ret;
mine[a][b] = '0';
}
}
if (mine[x - 1][y + 1] == ' ')
{
a = x - 1;
b = y + 1;
ret = Num_boms(mine, a, b);
if (ret == 0)
{
show[x - 1][y + 1] = ' ';
mine[a][b] = '0';
spread(mine, show, a, b);
}
else
{
show[x - 1][y + 1] = '0' + ret;
mine[a][b] = '0';
}
}
}
}
void sweep_Mine(char mine[ROW][COL], char show[ROW][COL], int x, int y) //該函式為掃雷函式:
{
int ret = 0;
if ( mine[x][y] == ' ') //玩家沒有踩到雷,即展示該區域周邊的雷數,如果雷數為0就顯示‘ ’空格。
{
ret=Num_boms(mine, x, y);
if (ret == 0)
{
show[x][y] = ' ';
}
else
{
show[x][y] = '0' + ret; //如果有炸彈就顯示炸彈的數量。
}
spread(mine, show, x, y); // 並在此呼叫展開函式,對周邊區域進行展開。
}
else if(mine[x][y] == '!')
{
show[x][y] = mine[x][y]; //如果玩家踩到炸彈就顯示感嘆號。
}
}
void prevent_first_death(char mine[ROW][COL],int x,int y) //防止玩家第一次被炸死。
{
int m, n;
if(mine[x][y] == '!')
{
do
{
m = rand() % 11 + 0;
n = rand() % 11 + 0; //如果玩家踩到雷,就重新隨機一個沒有雷的地方,將炸彈移動到那裡。
if (mine[m][n] == ' ')
{
mine[x][y] = ' '; //將該區域設定為空格。
mine[m][n] = '!';
break;
}
} while (1);
}
}
int if_success(char mine[ROW][COL], char show[ROW][COL], int m ) //判斷是否輸贏的函式。
{
int i, j,num;
num = M;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL;j++)
{
if (show[i][j]=='*') //如果在展示棋盤上剩餘 ‘*’的數量和雷數相同,那麼就表示掃雷成功了!
{
num--;
}
else if (show[i][j] == '!') //如果顯示盤上出現了 ‘!’說明玩家踩到了雷。
{
return 1;
}
}
}
if (num == 0)
{
return 0;
}
}
test.c(執行檔案)
#include "Mine Clearance.h"
void mune() //介面。
{
printf(" \n *******************************************************************\n");
printf(" ********** Do you want to play the Mine_Clearance Game? **********\n");
printf(" *********** **************\n");
printf(" ************* 1.play 2.exit ***************\n");
printf(" *******************************************************************\n");
}
game() //玩遊戲的函式。
{
char mine[ROW][COL];
char show[ROW][COL] ;
char spread[ROW][COL];
int x, y,m;
int row, col;
int count=0;
int ret;
row = ROW;
col = COL;
m = M; //將定義中的M賦值給 m
init(mine, show, spread);
Set_Mine(mine, m);
displaymine(mine); //在測試中使用,遊戲中可註釋掉。
do
{
displayboard(show);
count++;
printf("Please enter coordinates(x,y):");
scanf("%d %d", &x, &y);
getchar();
x = x - 1;
y= y - 1;
if (count == 1)
{
prevent_first_death(mine, x, y);
}
sweep_Mine(mine, show, x, y);
ret=if_success(mine,show,x,y);
if (ret == 1)
{
displayboard(show);
printf("\n Sorry, you were killed by mine.\n");
break;
}
else if (ret == 0)
{
displayboard(show);
printf("\n Congratulations! Mineclearance success.\n ");
break;
}
} while (1);
}
int main() //主函式 ,選單的選擇與遊戲的呼叫。
{
int n;
do
{
mune();
scanf("%d",&n);
getchar();
if (n == 1)
{
game();
}
else if (n==2)
{
break;
}
else
{
;
}
} while (1);
return 0;
}
就這樣了 不足之處望大家指出。