###简介
扫雷游戏实现的总代码对初学者来说是一个比较大的工程,许多朋友可能会被它的庞大的外观吓住,但是我通过逐步学习,慢慢梳理逻辑,发现它其实并没有看上去那么困难。我是怎样一步一步学会的呢?接下来,我们一起来具体看看。
###整体逻辑
通过试玩网页版小游戏扫雷,我们大致对扫雷游戏的过程有了一个初步认识。在用代码设计扫雷游戏时,我将其整体分为几个过程:
#一是选择游戏进入与否
#二是扫雷游戏各个部分函数的定义以及扫雷游戏的实现,其中细分为扫雷框架的定义,框架内容的初始化,框架如何打印,雷的设置以及最后扫雷游戏的进行
###整个程序要用到的头文件以及宏定义如下,其中的内容需结合下面的解释一起解读。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define row 9
#define col 9
#define rows row+2
#define cols col+2
#define _COUNT 10//雷的个数,宏定义方便改变个数
void InitBoard(char board[][cols], int rs, int cs, char set);//初始化棋盘
void DisplayBoard(char board[][cols], int r, int c);//打印棋盘
void SetBoard(char board[][cols], int r, int c);//设置雷
void Find(char mine[][cols], char show[][cols], int r, int c);开始扫雷
其中需要提前声明的是row、col分别代表的扫雷框架的行列,它们之所以要加上2是因为我们在扫9*9的框架的边缘时,无法统计这个位置周围的的相关信息,所以我们把它扩展,这样方便游戏的进行,当然我们实际上操作的仍是9*9的框架。如有不解,可结合后续的解释来看。
###设计函数选择游戏进入与否
void test()
{
int input = 0;
do
{
srand((unsigned)time(NULL));
menu();
puts("请选择:");
scanf("%d",&input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,重新输入:\n");
}
} while (input);
}
int main()
{
test();
return 0;
}
首先定义主函数,再设计选择进入游戏与否的函数,值得注意的是本段代码中srand的所在行的代码是为后续的工作准备的,再此可以先忽略不看,menu()是自己设计的一个菜单;这段代码主要是选择游戏的进入,用到选择语句switch。选择1进入游戏,于是在后面,我们要开始设计game()函数了。
###game函数定义
void game()
{
char mine[rows][cols] = { 0 };
char show[rows][cols] = { 0 };
//初始化棋盘
InitBoard(mine, rows, cols,'0');
InitBoard(show, rows, cols,'*');
//打印棋盘
//DisplayBoard(mine, row, col);
DisplayBoard(show, row, col);
//设置雷
SetBoard(mine, row, col);
DisplayBoard(mine, row, col);
//扫雷
Find(mine, show, row, col);
}
此段代码中我们定义的game函数,其中内容见代码,接下来我们具体来看这些内容到底是写什么,为什么要写这些代码,这些代码对扫雷游戏起了一些什么作用
#首先是mine和show数组的定义,这两个数组是扫雷的框架的具体化,我们知道的是,当在玩扫雷游戏时,屏幕呈现出来的是一个类似于棋盘的框架,因此我们用二维数组来表示这个框架可以说非常具体化了
#其次是对这两个数组(数组棋盘)的初始化,首先要声明的是,在mine数组里面我们之后是要存放设置雷的,二show数组的棋盘是要呈现给玩家看的,所以我们把mine数组先全部初始化为字符‘0’,之后把雷设置为字符‘1’;把show数组初始化为‘*’,之后我们每扫一次雷,就在show里面把这个位置周围的雷个数算出来并且在show数组上面呈现给玩家看。
#下列是初始化定义的代码以及打印代码的打印以及其运行结果
//初始化
void InitBoard(char board[][cols], int rs, int cs, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rs; i++)
{
for (j = 0; j < cs; j++)
{
board[i][j] = set;
}
}
}
//打印
void DisplayBoard(char board[][cols], int r, int c)
{
int i = 0;
int j = 0;
for(i=0;i<=r;i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= r; i++)
{
printf("%d ", i);
for (j = 1; j <=c; j++)
{
printf("%c ", board[i][j]);
}
putchar('\n');
}
}
这是目前代码的运行结果,其中set的形参设计是因为mine和show两个数组初始化时字符不同,为避免重复,我们直接使用传参的方式用一个函数就解决了。在这张运行结果中第一个棋盘其实时不能打印的,最后呈现给玩家的只能是show棋盘,在这里只是为了方便结合前面的代码来学习。
#接着是设置雷,我们先看代码
void SetBoard(char board[][cols], int r, int c)
{
int count = _COUNT;
while (count)
{
int x = rand() % 9 + 1;
int y = rand() % 9 + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
具体解读:首先定义count是循环设置雷的次数(雷的个数):接着是x、y的随机生成,在这里我们使用到rand相关知识,这个与前面srand对应起来了,因为棋盘是9*9规格的,所以我们生成9*9的随机值用以对应棋盘上的各个坐标:在选择语句if里面我们将是‘0’的坐标赋值为‘1’,如果第一次以后在赋值时刚好选到了是‘1’的坐标那么if就不会进去,循环次数也不会减少,相应的要设置的雷的个数也不会变化,这时再重新循环,只到选到‘0’的坐标并且依次进行赋值10次后循环结束,雷的设置也完成了,为了进一步理解,下面展示设置完雷的棋盘
#接下来便是扫雷游戏的真正实现了
void Find(char mine[][cols], char show[][cols], int r, int c)
{
int win = 0;
win = c * r - _COUNT;
while (win!= 0) {
int x, y;
printf("输入要查找的坐标:");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= r && y >= 1 && y <= c)
{
if (mine[x][y] == '1')
{
printf("你被炸死了\n");
break;
}
if(mine[x][y]=='0')
{
int ret = 0;
ret = mine[x - 1][y - 1] +
mine[x - 1][y] +
mine[x - 1][y + 1] +
mine[x][y - 1] +
mine[x][y + 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] - 8 * '0';
show[x][y] = ret + '0';
DisplayBoard(show, row, col);
win--;
}
}
else
{
printf("坐标输入不合法,请重新输入:\n");
}
}
if (win == 0)
{
printf("恭喜你,扫雷完成\n");
DisplayBoard(mine, row, col);
}
}
具体解读:先从定义x、y那行看起,先输入你要排查的坐标,如果你通过游戏了,那么你要排查的次数是棋盘的总坐标数减去雷占的坐标数,于是我们看到循环的条件以及条件的设置,便可以理解了;接着是分析排查雷时出现的几种情况:首先是输入坐标是否合理,这是最外层的选择语句的设置原理,如果合理那么进入 合理的部分,若排查了一次雷win就减少一次,那么循环次数就减少一次,如果合法就再循环,循环次数也不会减少(排查次数);合理输入坐标后如果刚好排查到雷,那么游戏就结束了,break;跳出循环;如果排查成功,就要呈现给玩家看这个排查到没有雷的坐标周围有几个雷,在这里,我们使用统计大小的方式来反映,因为周围存放的是字符‘0’或‘1’,我们先将周围八个字符加起来再减去8*‘0’得出的结果就是周围雷的个数(参考ASCLL表),然后再把show棋盘上的相应的坐标赋值这个得到的结果加‘0’,最后呈现给玩家看到的就是一个字数,也就是雷的个数。后面的if是一个顺利完成的结束语,最后打印一次棋盘是为了让玩家玩完游戏后看到雷的位置。
以下是总的运行结果
本次分享完毕,如有不对,希望能一起讨论。