今天来讲解扫雷,首先因为扫雷游戏中各种操作比较复杂,我们可以把扫雷的过程抽象成一个game();函数,然后写出一个游戏框架。我们可以先把程序整体写成一个test();程序。
int main()
{
test();
return 0;
}
在进行测试时,为了明确我们进入程序时得到反馈,我们可以先写一个menu();程序来打印我们的菜单。我们开始测试时候会直接打印菜单供我们选择,并且因为有重复游戏的需要,我们选择do while语句来实现,菜单选择至少会有一个开始游戏与退出游戏的选择,为了得到输入的反馈我们需要一个switch case语句实现。
void test()
{
int i = 0;
do
{
menu();
scanf("%d", &i);
switch (i)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (i);
}
因为调用了menu目录打印,所以还要写一个menu();函数
void menu()
{
printf("**********************************\n");
printf("*****0、退出游戏 1、开始游戏*****\n");
printf("**********************************\n");
}
至此,游戏框架已经搭建完毕,剩下的就是game();程序的实现了。
为了方便测试与维护,我们可以把game();程序分装成一些更加具体的逻辑,首先,我们要实现扫雷,当我们点开一个按钮时候会显示周围八个格子位置中雷的数目的总和,考虑到第一行,最后一行,第一列,最后一列,我们可以定义一个ROW为展示棋盘的行数,COL为展示棋盘的列数,ROWS为ROW+2来表示我们代码实现过程中使用的棋盘的行数,同理COLS为COL+2表示我们代码实现过程中的棋盘列数。我们首先要创建两个棋盘,行列分别是ROWS和COLS,一个用来控制是否有雷,一个用来展示对应位置附近雷的数量。
char mine[ROWS][COLS];
char board[ROWS][COLS];
创建好了棋盘我们现在要做的就是初始化棋盘,我们在mine棋盘里全放字符‘0’,这样方便控制雷的存在与否并且方便后续计算雷的数目,我们在board棋盘里全部初始化为*,这样可以使打印出的棋盘全为*,当我们选择排雷时候才会展示会附近雷的数量。
void initboard(char board[ROWS][COLS], int rows, int cols, char c)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = c;
}
}
}
初始化之后我们要埋雷,我们假如要埋10个雷我们可以生成10个在棋盘内的随机坐标,选定的坐标值改为‘1’就可以了。
void setmine(char board[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = easy;
while (count)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
埋完雷之后首先我们希望可以先把棋盘展示出来,这个比较简单,直接遍历我们board 二维数组就可以了,但是也有细节,我们最好可以在每一行和每一列之前打印出行号和列号。
void display(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 0; i < row; i++)
{
printf("%d ", i+1);
for (j = 0; j < col; j++)
{
printf("%c ", board[i+1][j+1]);
}
printf("\n");
}
}
然后就可以进行排雷过程了,排雷过程我们需要计算周围八个格子雷的数目,没雷的话为‘0’,有雷为‘1’,一共有八个格子所以可以把它们加起来然后减去8*‘0’;这样就计算出了雷的数目,然后再利用上面的display();函数来打印棋盘就完成了一次排雷过程,我们先把排雷过程写一个循环,当判断出被雷炸死时跳出循环,循环要满足我们排雷的次数加上雷的次数小于棋格总次数,循环结束后我们再判断排出的格子数量是否等于总格数减去雷的数目,相等就代表我们赢了。
void finemine(char mine[ROWS][COLS], char board[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while (win < row * col-easy)
{
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '0')
{
board[x][y] = mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x - 1][y] + mine[x + 1][y] + mine[x - 1][y + 1] + mine[x][y + 1] + mine[x + 1][y + 1] - 7 * '0';
display(board, ROW, COL);
win++;
}
else
{
printf("你被炸死了\n");
display(mine, ROW, COL);
break;
}
}
else
printf("输入错误,重新输入\n");
}
if (win == row * col-easy)
printf("恭喜你,排雷成功\n");
}
然后我们在框架里把这些函数逻辑上连起来就完成了
void game()
{
//创建棋盘
char mine[ROWS][COLS];
char board[ROWS][COLS];
//初始化棋盘
initboard(mine, ROWS, COLS, '0');
initboard(board, ROWS, COLS, '*');
//布置雷
setmine(mine, ROW, COL);
//展示棋盘
display(board, ROW, COL);
//排雷
finemine(mine, board, ROW, COL);
}