扫雷游戏通常是一个由方格组成的区域内进行的,其中随机分布着一定数量的地雷 。玩家的目标是通过点击方格来标记出所有地雷的位置,同时避免自己点到地雷而导致游戏失败。游戏开始时,玩家通常只能看到一部分方格,而其余的方格则需要通过点击来逐渐揭示其内容(目前学的比较低级请见谅)。
下面这个图是网页版扫雷的界面:
现在开始讲解代码:
写一个完整代码首先都是从主函数开始(前面写的游戏可以发现主函数的流程几乎不变),do……while(一上来就先进行菜单选择),主函数包含菜单还有对菜单的输入与选择(这个没什么难度,略写),而且一般游戏都需要菜单,玩家才可以清楚了解和选择。
void menu()
{
printf("**************************************\n");
printf("*********** 1.play ************\n");
printf("*********** 0.exit ************\n");
printf("**************************************\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请输入你的选择:");
scanf("%d", &input);
switch (input)
{
case 1:game();
break;
case 0:printf("退出游戏!!!\n");
break;
default:printf("选择错误,请重新选择!!!\n");
break;
}
} while (input);
return 0;
}
进行选择:这里为了后续的写作当然是要选1的,接着跳到game函数。
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//PrintBoard(mine, ROW, COL);//这个不需要打印,不然就看着答案排雷了
PrintBoard(show, ROW, COL);
SetMine(mine, ROW, COL);
PrintBoard(mine, ROW, COL);
FindMine(show, mine, ROW, COL);
}
扫雷游戏内部需要两个数组一个是屏幕显现出来(show);另一个则是藏在我们背后(mine),这就是这个游戏的巧妙之处。而且这个数组显现出来的是9X9的数组,但是玩游戏需要计算坐标周围一圈,假设想要检验数组四条靠边的坐标,计算坐标一圈数组会越界这时需要数组都加二(即四条边都加一)
#define ROW 9
#define COL 9#define ROWS ROW+2
#define COLS COL+2
一开始要对这两个数组初始化,而且初始化时需要整个数组都初始化而不是只对显现出来的数组初始化,不然后面会影响。show数组初始化没什么要求,然而为了后面计算【至于为什么后面会提到】mine数组初始化为‘0’(即字符0)。这里有一个简便的操作,就是数组设置为board,这样不管是show还是mine只需要改变数组就可以调用初始化的这个函数。
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;
}
}
}
接下来就是打印数组,单纯只打印数组的话数坐标有些困难,所以需要在数组前标数字方便数数,还需要分界线。
void PrintBoard(char board[ROWS][COLS], int row, int col)
{
printf("--------扫雷-------\n");
int i = 0;
int j = 0;
for (i = 0; i <= row; i++)
{
if (i != 0)
{
printf(" %d", i);
}
else
{
printf(" ");
}
}
printf("\n");
for (i = 0; i <= row; i++)
{
printf("--");
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d|", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
for (i = 0; i <= row; i++)
{
printf("--");
}
printf("\n\n");
}
下面就到布置地雷,游戏分初级,中级,高级。我们就先简单一点的设置10个地雷,然后就是随机挑选坐标(当然是没有地雷的坐标中挑选啦),选中一个那对应的地雷数要减少一个,这样才知道地雷是否符合标准。
#define EASY 10
void SetMine(char mine[ROWS][COLS], int row, int col)
{
srand((unsigned int)time(NULL));
int count = EASY;
while (count)
{
int a = rand() % row + 1;
int b = rand() % col + 1;
if (mine[a][b] == '0')
{
mine[a][b] = '1';
count--;
}
}
}
最后就是重难点排查地雷,先要输入你要排查的坐标,讨论输入的坐标是否符合数组范围,然后再看这个坐标是否有地雷,如若有雷游戏结束且需要打印mine数组的地雷位置供玩家参考;相反没有地雷的话需要打印周围一圈地雷的数量,这个就是mine数组初始化为字符0的原因,数字0和字符0之间相差一个字符0,所以计算地雷数量只需将坐标周围的字符分别都减一个字符0再相加起来就是坐标周围一圈的地雷数量,show数组中是字符,所以地雷数量还需加一个字符0,在打印show数组就会出现地雷数。
游戏的胜利是需要把所有的不是地雷的坐标找出来才算胜利,所以需要累计排查的坐标是否满足总的坐标减去地雷数,当然过程中不能有重复排查的坐标,不然满足但还有坐标没有排查,这就不符合游戏规则。
int get_round_mine(char mine[ROWS][COLS], int x, int y)
{
int i = 0;
int j = 0;
int ch = 0;
for (i = x - 1; i <= x + 1; i++)
{
for (j = y - 1; j <= y + 1; j++)
{
ch = ch + (mine[i][j] - '0');
}
}
return ch;
}
void FindMine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while (win < ROW * COL - EASY)
{
printf("请输入你要排查的坐标:");
scanf("%d %d", &x, &y);
if (x > 0 && x <= ROW && y > 0 && y <= COL)
{
if (show[x][y] != '*')
{
printf("该坐标已被排查过\n");
continue;
}
if (mine[x][y] == '1')
{
printf("踩到地雷,游戏结束!!!\n");
PrintBoard(mine, ROW, COL);
break;
}
else
{
int n = get_round_mine(mine, x, y);
show[x][y] = n + '0';
PrintBoard(show, ROW, COL);
win++;
}
}
else
{
printf("输入超过限制,无法检测是否有地雷!\n");
}
}
if (win == ROW * COL - EASY)
{
printf("扫雷成功,你太厉害了吧!\n");
}
}
现在这个代码还不是很好,和网页版的还是有差距的。目前能力有限往后就不太会了,见谅。