哈喽,大家好久不见!不知不觉已来到2023年的最后一天了,小编呢在此提前祝大家新年快乐,希望在新的一年里,我们都越来越好,学习和工作都更上一层楼.OK,言归正传,今天小编为大家准备了一个小游戏----扫雷.相信大家或多或少都玩过这个游戏,那么今天我将从以下几个方面为大家讲解初阶扫雷游戏的实现.
一.游戏分析与设计
二.游戏代码实现
三.写代码时的注意事项
1.游戏分析与设计
- 1 扫雷游戏玩法说明
- 使用控制台实现扫雷游戏
- 通过菜单实现退出游戏或继续游戏
- 用棋盘布置扫雷的格子(根据自己的想法,如可以是9*9,11*11等等,一般不超过内存范围即可,今天小编用9*9格子)
- 随机布置10个雷(你也可以按自己的意愿布置雷的个数)
- 排查雷
- 排查坐标为雷,则游戏结束
- 排查坐标不是雷,则统计此坐标周围雷的个数
- 若成功把全部雷排查出来,游戏也结束
1.2 扫雷游戏的设计
第一步:创建棋盘(9*9格子,即9*9的数组)用来存储扫雷过程中布置雷和排查雷的信息
然后在这个棋盘中有雷的位置就存放1,没有雷的位置就存放0
然而,如果我们只创建这样一个棋盘,那么会产生一个麻烦,比如如果我们排查了棋盘上的某一个位置后,若此坐标位置不是雷,而它的周围有一个雷,此时我们需要将排查出的雷的信息进行存储并打印出来,由于我们只创建了一个棋盘,因此如果我们把排查出的雷的信息存放在这个棋盘上,那么雷的信息和雷的个数信息就会产生混淆(如在我们排查了某一个坐标后,棋盘上显示了1,那么这个1到底是雷的个数还是此处是雷将会分不清楚),并且这样也会产生打印上的困难.
为此,我们可以这样:创建两个同样的棋盘,一个专门用来存储布置的雷的信息,另一个专门用来存储排查出的雷的个数信息,两个棋盘用两个数组来表示,如用mine数组来存储布置雷的信息,用show数组来存储排查的雷个数的信息
为了保持神秘,show数组初始化为'*',而mine数组初始化为'0',布置雷的位置用'1'表示
还有一点需要注意,就是上面这两个初始化后的棋盘为什么要增加一圈?
这是为了防止坐标越界,而什么是坐标越界呢?
2.代码实现
在实现代码时,为了使增加代码可读性以及更加直观,我们可以用多文件的形式进行书写
如用test.c实现扫雷游戏的逻辑
用game.c实现函数的逻辑
用game.h书写函数所需的头文件
下面就是代码
#include "game.h"
void InitBoard(char arr[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++)
{
arr[i][j] = set;
}
}
}
void DisplayBoard(char arr[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 ", arr[i][j]);
}
printf("\n");
}
printf("-------扫雷游戏-------\n");
}
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int x, y;
int count = LEI;
while (count)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
int GetCountMine(char mine[ROWS][COLS], int x, int y)
{
int i = 0;
int j = 0;
int count = 0;
for(i = x - 1; i <= x + 1;i++)
{
for(j = y - 1; j <= y + 1;j++)
{
count += (mine[i][j] - '0');
}
}
return count;
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int end = 0;
while (end < row * col - LEI)
{
printf("请输入要排查的坐标:> ");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("抱歉,你被炸死了\n");
DisplayBoard(mine, row, col);
break;
}
else
{
int count = GetCountMine(mine, x, y);
show[x][y] = count + '0';
DisplayBoard(show, row, col);
end++;
}
}
else
{
printf("该坐标已经排查过了,请重新输入\n");
}
}
else
{
printf("输入坐标不正确,请重新输入\n");
}
}
if (end == row * col - LEI)
{
printf("你太棒了,成功排完所有雷\n");
DisplayBoard(mine, row, col);
}
}
#include "game.h"
void menu()
{
printf("*****************\n");
printf("*****************\n");
printf("**** 1. play ****\n");
printf("**** 0. exit ****\n");
printf("*****************\n");
printf("*****************\n");
}
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);
SetMine(mine, ROW, COL);
FindMine(mine, show, ROW, COL);
}
void test()
{
int n = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:> ");
scanf("%d", &n);
switch (n)
{
case 1:
game();
break;
case 0 :
printf("退出游戏\n");
break;
default :
printf("输入错误,请重新输入\n");
break;
}
} while (n);
}
int main()
{
test();
return 0;
}
3.写代码时的注意事项
1.在写代码时要注意首先理清思路,不然很容易写了就忘
2.要注意在写代码时if和else的位置,即悬空else的问题,要清楚else与哪一个if匹配,小编在初次写时就因为没有注意这个问题而花费了很多时间
3.要注意传参时二维数组可以省略行,但不可以省略列,如
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
void FindMine(char mine[ ][COLS], char show[ ][COLS], int row, int col)
总结
以上是小编对初阶扫雷游戏的初步理解,有什么不对的地方还请大家指正,拜拜!咱们明年再见!