这次是写一个扫雷的小游戏,可实现周围没雷时展开和第一次排雷不被炸死(防止欧皇直接暴毙!)。
首先我们先梳理代码思路:
1、既然要展示和布雷,所以我们需要2个二维数组,一个用来展示给观众,一个显示雷利于我们编程,我们将雷数组初始化为 0 ,将展示的数组初始化为 * ,保持神秘~
2、我们需要将雷布置到雷数组中去,当然是随机布置;
3、我们还需要一个安全函数,就是当第一次排雷的时候不被炸死;(就是如果第一次排的是雷,就将此位置的雷转移)
4、排雷的过程,包括了如何展开,还有表明旁边有几颗雷;
1、初始化数组(mine和show),而且为了边上的坐标也能排雷,所以需要建的数组要比棋盘多两行两列。然后就是初始化数组(mine初始化为字符0,show初始化为 *)
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
2、打印数组,当然要都打印出来以便我们测试(为了排雷方便,我们给数组加上了序号)
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("----------------------------------\n");
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("----------------------------------\n");
}
3、将雷布置到 mine数组中去,这里我们需要用到随机数,我们用的是rand()这个函数来产生随机数,当然范围要控制在数组范围中
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = EASY_COUNT;
while (count)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
4、安全函数,这个函数的作用是保证我们第一次排雷不被炸死…
void SafeMine(char mine[ROWS][COLS],char show[ROWS][COLS],int row, int col)
{
int ret = 1;
int x = 0;
int y = 0;
int count = 0;
printf("请输入你要排查的坐标:");
scanf("%d%d", &x,&y);
if (mine[x][y] == '1')
{
mine[x][y] = '0';
count = GetMine(mine, x, y);
show[x][y] = count + '0';
while (ret)
{
if (mine[x][y] == '1')
{
int m = rand() % 9 + 1;
int n = rand() % 9 + 1;
mine[x][y] = '0';
mine[m][n] = '1';
}
ret--;
}
}
OpenMine(mine, show, row, col,x,y);
DisplayBoard(show, row, col);
}
5、最后就是排雷的过程了,展开函数也在里面(展开函数是用递归来完成的)
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
int count = 0;
while (1)
{
printf("请输入要排查的坐标:");
scanf("%d%d", &x, &y);
if (x >= 0 && x <= row && y >= 0 && y <= col)
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了!\n");
DisplayBoard(mine, row, col);
break;
}
else
{
count = GetMine(mine, x, y);
show[x][y] = count+'0';
OpenMine(mine, show, row, col, x, y);
DisplayBoard(show, row, col);
if (MyWin(show,row,col) == EASY_COUNT)
{
break;
}
}
}
else
{
printf("坐标非法,请重新输入!\n");
}
}
if (MyWin(show, row, col) == EASY_COUNT)
{
printf("恭喜你排雷成功!\n");
DisplayBoard(mine, row, col);
}
}
void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y)
{
int ret = 0;
ret = GetMine(mine, x, y);
if (ret == 0) {
show[x][y] = ' ';
if (x - 1>0 && y>0 && show[x - 1][y] == '*')
OpenMine(mine, show, row, col, x - 1, y);
if (x - 1>0 && y + 1 <= col && show[x - 1][y + 1] == '*')
OpenMine(mine, show, row, col, x - 1, y + 1);
if (x>0 && y + 1 <= col && show[x][y + 1] == '*')
OpenMine(mine, show, row, col, x, y + 1);
if (x + 1 <= row && y + 1 <= col && show[x + 1][y + 1] == '*')
OpenMine(mine, show, row, col, x + 1, y + 1);
if (x + 1 <= row && y>0 && show[x + 1][y] == '*')
OpenMine(mine, show, row, col, x + 1, y);
if (x + 1 <= row && y - 1>0 && show[x + 1][y - 1] == '*')
OpenMine(mine, show, row, col, x + 1, y - 1);
if (x>0 && y - 1>0 && show[x][y - 1] == '*')
OpenMine(mine, show, row, col, x, y - 1);
if (x - 1>0 && y - 1>0 && show[x - 1][y - 1] == '*')
OpenMine(mine, show, row, col, x - 1, y - 1);
}
else
{
show[x][y] = GetMine(mine, x, y) + '0';
}
}
6、其中有一个GetMine函数是用来统计周围有多少雷,这个函数写的很巧妙,这也是我们为什么非要设计0和1作为雷数组
int GetMine(char mine[ROWS][COLS], int x, int y)
{ return mine[x - 1][y] +
mine[x - 1][y - 1] + mine[x][y - 1]
+ mine[x + 1][y - 1] + mine[x + 1][y] +
+ mine[x + 1][y + 1] + mine[x][y + 1] +
+ mine[x - 1][y + 1] - 8 * '0';
}
总结:这个游戏总体来说不是很难,难点就在于展开的那里,是用递归来进行完成的,总体设计和三子棋的界面一样,我们需要注意的就是雷的布置和雷的统计还有雷的展开。