一、扫雷游戏规则
相信小伙伴们都玩过扫雷游戏,了解一定的简单逻辑规则,如果小伙伴忘记了或者不知道的小伙伴我们先了解一下游戏规则吧。
游戏规则:
在一块N*N的网格中,随机会布置N个雷,左键随机点击一个方格,若方格是雷会显示“被炸死”,方格不是雷,方格即被打开并显示出方格中的数字;方格中数字则表示其周围的8个方格隐藏了几颗雷;如果点开的格子为空白格,即其周围有0颗雷,则其周围格子自动打开;如果其周围还有空白格,则会引发连锁反应;在你认为有雷的格子上,点击右键即可标记雷。
网页版扫雷游戏:扫雷游戏网页版 点击网页版扫雷,了解游戏逻辑。
二、代码文件的设计
首先,我们用VS2019编译器在编写小游戏之前,需要创建一个源(.h)文件和两个.c文件。
test.c文件:主要用于整体逻辑的测试
game.c文件:用于编写游戏相关的函数实现
game.h文件:用于编写游戏相关的函数声明及其头文件包含、定义标识符
三、游戏逻辑的设计
预先说明:我们这里实现的简单扫雷游戏,并不能实现点击功能,只能根据坐标输入形式进行排雷。
逻辑分析:我们先需要一个N*N的棋盘,这里我们用9*9的棋盘为例,随机放置10个雷,而棋盘的存储需要一个二维数组,我们考虑用“1”布置雷,“0”则表示非雷。为什么不用像“*”、“#”之类的字符,(因为后面判断统计雷的个数情况较复杂,这里预先考虑“0”或者“1”。)观察以下图片,假设🔴是我们排查的雷的坐标(1,1),🔴的周围有1个“1”,代表我们目前排雷的坐标不是雷,且周围有1个雷,那么我们需要统计周围的雷,雷的个数为1,那么是将🔴的坐标的“0”置换为“1”吗,此时被置换为“1”后,不又布置了1个雷吗,这不就冲突了吗?此时我要的是统计周围雷的个数,所以我们需要创建两个二维数组,一个二维数组用来存储“0”或“1”的数据,另一个用来统计周围有若干个雷的数据。再次观察 🔴周围的三个蓝色坐标部分为有效部分,那么,访问并统计周围其他五个坐标时,不就属于数组越界访问了吗?针对这个问题,我们将数组的行和列分别都加上2,这样在统计时以免越界访问,我们暂且称之为虚拟棋盘的大小,而数据的存放和打印我们仅使用蓝色部分的棋盘,我们暂且称之为实际棋盘的大小。
我们逻辑理清 后,再一步步编写代码。
🔴 表示选中的坐标;绿色数组表示坐标序号;红方框表示的都是“1”,布置的10个雷,以便分析方便观察;
1.设置游戏菜单
我们从test.c文件开始编写,游戏开始前,需要有一个菜单页面,我们编写到menu()函数之中。
我们希望玩一把不过瘾,想接着继续玩,考虑使用do……while循环结构,选择“1”,我们Play游戏(先写个game()函数);当不想玩了,我们选择“0”,退出游戏,跳出循环;输入其他值,显示“输入有误,请重新选择。”让你重新选择。所以考虑循环里面嵌套一个switch语句。
test.c文件
#define _CRT_SECURE_NO_WARNINGS //用于整体逻辑的测试 #include "game.h" void menu() { printf("********************\n"); printf("******扫雷游戏******\n"); printf("******1.Play********\n"); printf("******0.Exit********\n"); printf("********************\n"); } void game() { } 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; }
2.存储棋盘数据及初始化棋盘
首先我们需要先编写一个mine数组,来存放雷的相关信息,数组元素是“0”和“1”。编写另一个数组show数组,用来表示排查出雷的信息,该数组全部遍历为“*”,以保持隐匿,当排查不是雷的时候,周围的雷的个数就会替换“*”,所以两个数组元素类型我们统一用char类型的数组,两个数组的元素个数我们统一用虚拟棋盘大小来算。
1.存储数据:我们定义标识符常量ROW、COL为实际棋盘的大小,ROWS、COLS为虚拟棋盘的大小,EASY_COUNT为放置雷的个数(简单版本)。
2.我们创建一个InitBoard()来初始化棋盘,初始化两个数组,我们分别传进两个数组,虚拟棋盘大小,以及要初始化的元素(“0”和“*”)。
#define _CRT_SECURE_NO_WARNINGS //用于整体逻辑的测试 #include "game.h" void menu() { printf("********************\n"); printf("******扫雷游戏******\n"); printf("******1.Play********\n"); printf("******0.Exit********\n"); printf("********************\n"); } void game() { //存储数据 char mine[ROWS][COLS] = { 0 }; char show[ROWS][COLS] = { 0 }; //初始化棋盘 InitBoard(mine,ROWS,COLS,'0'); InitBoard(show,ROWS,COLS,'*'); } 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; }
game.h文件
#define _CRT_SECURE_NO_WARNINGS //用于游戏相关函数的声明及头文件包含 #include<stdio.h> //实际棋盘大小 #define ROW 9 #define COL 9 //虚拟棋盘大小 #define ROWS ROW + 2 #define COLS COL + 2 //放置雷的个数(简单版本) #define EASY_COUNT 10 //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols,char set);
game.c文件
#define _CRT_SECURE_NO_WARNINGS //用于游戏相关函数的具体实现 #include"game.h" //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols,char set) { int i = 0; for (i = 0; i < rows; i++) { int j = 0; for (j = 0; j < cols; j++) { board[i][j] = set; } } }
2.打印棋盘
紧接着,我们创建写一个DisplayBoard()函数来打印棋盘。我们试着先打印mine数组和show数组,需要打印的是实际棋盘的大小,所以传入ROW和COL就行。
test.c文件
#define _CRT_SECURE_NO_WARNINGS //用于整体逻辑的测试 #include "game.h" void menu() { printf("********************\n"); printf("******扫雷游戏******\n"); printf("******1.Play********\n"); printf("******0.Exit********\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(show, ROW, COL); DisplayBoard(mine, ROW, COL); } 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; } game.h文件
game.h文件
#define _CRT_SECURE_NO_WARNINGS //用于游戏相关函数的声明 及头文件包含 #include<stdio.h> //实际棋盘大小 #define ROW 9 #define COL 9 //虚拟棋盘大小 #define ROWS ROW + 2 #define COLS COL + 2 //放置雷的个数(简单版本) #define EASY_COUNT 10 //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols,char set); //打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col);
game.c文件
#define _CRT_SECURE_NO_WARNINGS //用于游戏相关函数的具体实现 #include"game.h" //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols,char set) { int i = 0; for (i = 0; i < rows; i++) { int j = 0; for (j = 0; j < cols; j++) { board[i][j] = set; } } } //打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col) { printf("*****-- 扫雷 --*****\n"); //作分隔栏,以免观察混淆 int i = 0; for (i = 0; i <= row; i++) { printf("%d ", i); //打印列号 } printf("\n"); for (i = 1; i <= row; i++) { printf("%d ", i); //每打印一行之前打印行号。 int j = 0; for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); //打印初始化元素 } printf("\n"); } }
代码打印如下:
3.放置雷
接下来,我们需要设置随机10个雷的遍布,我们编写一个SetMine()函数,需要传入mine数组,需要用到实际棋盘的大小,传入ROW和COL即可。
test.文件
#define _CRT_SECURE_NO_WARNINGS //用于整体逻辑的测试 #include "game.h" void menu() { printf("********************\n"); printf("******扫雷游戏******\n"); printf("******1.Play********\n"); printf("******0.Exit********\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(show, ROW, COL); //放置雷 SetMine(mine,ROW,COL); } int main() { int input = 0; srand((unsigned int)time(NULL)); 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; }
game.h文件
SetMine()函数需要用到库函数rand()和srand(),因此需要引用头文件<stdlib.h>和<time.h>
#define _CRT_SECURE_NO_WARNINGS //用于游戏相关函数的声明 及头文件包含 #include<stdio.h> #include<stdlib.h> #include<time.h> //实际棋盘大小 #define ROW 9 #define COL 9 //虚拟棋盘大小 #define ROWS ROW + 2 #define COLS COL + 2 //放置雷的个数(简单版本) #define EASY_COUNT 10 //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols,char set); //打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col); //放置雷 void SetMine(char mine[ROWS][COLS], int row, int col);
game.c文件
#define _CRT_SECURE_NO_WARNINGS //用于游戏相关函数的具体实现 #include"game.h" //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols,char set) { int i = 0; for (i = 0; i < rows; i++) { int j = 0; for (j = 0; j < cols; j++) { board[i][j] = set; } } } //打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col) { printf("*****-- 扫雷 --*****\n"); int i = 0; for (i = 0; i <= row; i++) { printf("%d ", i); } printf("\n"); for (i = 1; i <= row; i++) { printf("%d ", i); int j = 0; for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("\n"); } } //放置雷 void SetMine(char mine[ROWS][COLS], int row, int col) { int count = EASY_COUNT; //将雷的个数放进计数变量 while (count) { int x = rand() % row + 1; //余数范围 1 ~ row int y = rand() % col + 1; //余数范围 1 ~ col if (mine[x][y] == '0') //'0'为非雷 { mine[x][y] = '1'; //当坐标为非雷,放置雷 count--; //每放置一次雷,count-- } } }
在写完SetMine()函数,我们再次调用DisplayBoard()函数,发现棋盘随机放置了十个“1”,说明放置雷成功!
4.排查雷
我们随机放置雷成功后,接下来需要写一个FindMine()函数来排查雷,设计到mine数组和show数组,需要按9*9的序号输入坐标,判断坐标的非法性,所以我们传入ROW和COL。
test.c文件
#define _CRT_SECURE_NO_WARNINGS //用于整体逻辑的测试 #include "game.h" void menu() { printf("********************\n"); printf("******扫雷游戏******\n"); printf("******1.Play********\n"); printf("******0.Exit********\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(show, ROW, COL); //放置雷 SetMine(mine,ROW,COL); DisplayBoard(mine, ROW, COL); //排查雷 FindMine(mine, show, ROW, COL); } int main() { int input = 0; srand((unsigned int)time(NULL)); 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; }
game.h文件
#define _CRT_SECURE_NO_WARNINGS //用于游戏相关函数的声明 及头文件包含 #include<stdio.h> #include<stdlib.h> #include<time.h> //实际棋盘大小 #define ROW 9 #define COL 9 //虚拟棋盘大小 #define ROWS ROW + 2 #define COLS COL + 2 //放置雷的个数(简单版本) #define EASY_COUNT 10 //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols,char set); //打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col); //布置雷 void SetMine(char mine[ROWS][COLS], int row, int col); //排查雷 void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
这里我们需要再编写一个GetMineCount()函数,用于统计该位置(该位置不是雷的情况下)旁边8个坐标雷的个数。但是我们发现统计雷的个数时,“1”是char字符类型,而不是整型数字啊,于是我们考虑将每个字符减去一个‘0’,不就转换为整型了吗?(“1” - “0” = 1,字符“1”的ASCII码值为49,‘0’的ASCII码值为48,相减就得到了1)
game.c文件
#define _CRT_SECURE_NO_WARNINGS //用于游戏相关函数的具体实现 #include"game.h" //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols,char set) { int i = 0; for (i = 0; i < rows; i++) { int j = 0; for (j = 0; j < cols; j++) { board[i][j] = set; } } } //打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col) { printf("*****-- 扫雷 --*****\n"); int i = 0; for (i = 0; i <= row; i++) { printf("%d ", i); } printf("\n"); for (i = 1; i <= row; i++) { printf("%d ", i); int j = 0; for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("\n"); } } //布置雷 void SetMine(char mine[ROWS][COLS], int row, int col) { int count = EASY_COUNT; while (count) { int x = rand() % row + 1; int y = rand() % col + 1; if (mine[x][y] == '0') { mine[x][y] = '1'; count--; } } } //获取该位置周围雷的个数 int GetMineCount(char mine[ROW][COLS], int x, int y) { return (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] + mine[x - 1][y] - 8 * '0'); } //排查雷 void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int count = 0; int win = 0; while (win < row*col - EASY_COUNT) //非雷的地方一直排查 { printf("请输入要排查的坐标:>"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) //判断坐标的合法性 { if (show[x][y] == '*') //当show数组为*时,我们进行排雷 { if (mine[x][y] == '1') { printf("很遗憾,你被炸死了\n"); DisplayBoard(mine, ROW, COL); //再次显示棋盘,自己如何被炸死的 break; } else { //该坐标不是雷,就统计周围有几个雷 count = GetMineCount(mine, x, y); show[x][y] = count + '0'; //再次转换为char类型 DisplayBoard(show, ROW, COL); //显示周围雷的信息 win++; //每排查一次成功win++ } } else { printf("该位置已经被排查\n"); //非*时,说明已经被排查过了 } } else { printf("坐标非法,请重新输入\n"); } } //非雷的位置都排查完了 while循环跳出来判断游戏结束 if (win == row * col - EASY_COUNT) { printf("恭喜你,排雷成功!\n"); } }
5.测试代码
这里我们定义10个雷不好作测试,如果一个个去排查,会有一定的难度。所以我们暂且直接将EASY_COUNT改为80个,我们将show和mine数组都用DisplayBoard()打印出来,以方便测试。
test.c文件
#define _CRT_SECURE_NO_WARNINGS //用于整体逻辑的测试 #include "game.h" void menu() { printf("********************\n"); printf("******扫雷游戏******\n"); printf("******1.Play********\n"); printf("******0.Exit********\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(show, ROW, COL); //布置雷 SetMine(mine,ROW,COL); DisplayBoard(mine, ROW, COL); //排查雷 FindMine(mine, show, ROW, COL); } int main() { int input = 0; srand((unsigned int)time(NULL)); 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; }
game.h文件
#define _CRT_SECURE_NO_WARNINGS //用于游戏相关函数的声明 及头文件包含 #include<stdio.h> #include<stdlib.h> #include<time.h> //实际棋盘大小 #define ROW 9 #define COL 9 //虚拟棋盘大小 #define ROWS ROW + 2 #define COLS COL + 2 //放置雷的个数(简单版本) #define EASY_COUNT 80 //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols,char set); //打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col); //放置雷 void SetMine(char mine[ROWS][COLS], int row, int col); //排查雷 void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game.c文件
#define _CRT_SECURE_NO_WARNINGS //用于游戏相关函数的具体实现 #include"game.h" //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols,char set) { int i = 0; for (i = 0; i < rows; i++) { int j = 0; for (j = 0; j < cols; j++) { board[i][j] = set; } } } //打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col) { printf("*****-- 扫雷 --*****\n"); int i = 0; for (i = 0; i <= row; i++) { printf("%d ", i); } printf("\n"); for (i = 1; i <= row; i++) { printf("%d ", i); int j = 0; for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("\n"); } } //布置雷 void SetMine(char mine[ROWS][COLS], int row, int col) { int count = EASY_COUNT; while (count) { int x = rand() % row + 1; int y = rand() % col + 1; if (mine[x][y] == '0') { mine[x][y] = '1'; count--; } } } //获取该位置周围雷的个数 int GetMineCount(char mine[ROW][COLS], int x, int y) { return (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] + mine[x - 1][y] - 8 * '0'); } //排查雷 void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int count = 0; int win = 0; while (win < row*col - EASY_COUNT) //非雷的地方一直排查 { printf("请输入要排查的坐标:>"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) //判断坐标的合法性 { if (show[x][y] == '*') //当show数组为*时,我们进行排雷 { if (mine[x][y] == '1') { printf("很遗憾,你被炸死了\n"); DisplayBoard(mine, ROW, COL); //再次显示棋盘,自己如何被炸死的 break; } else { //该坐标不是雷,就统计周围有几个雷 count = GetMineCount(mine, x, y); show[x][y] = count + '0'; //再次转换为char类型 DisplayBoard(show, ROW, COL); //显示周围雷的信息 win++; //每排查一次成功win++ } } else { printf("该位置已经被排查\n"); //非*时,说明已经被排查过了 } } else { printf("坐标非法,请重新输入\n"); } } //非雷的位置都排查完了 while循环跳出来判断游戏结束 if (win == row * col - EASY_COUNT) { printf("恭喜你,排雷成功!\n"); } }
代码写完后,我们测试代码,排查唯一一个没有雷的地方(2,9),最终显示“恭喜你,排雷成功!” ,代码测试完成。
四、完整代码
棋盘9*9的大小,雷随机放置10个的简易扫雷游戏代码,将三个代码文件的完整代码,放置如下
test.c文件
#define _CRT_SECURE_NO_WARNINGS //用于整体逻辑的测试 #include "game.h" void menu() { printf("********************\n"); printf("******扫雷游戏******\n"); printf("******1.Play********\n"); printf("******0.Exit********\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(show, ROW, COL); //放置雷 SetMine(mine,ROW,COL); //DisplayBoard(mine, ROW, COL); //排查雷 FindMine(mine, show, ROW, COL); } int main() { int input = 0; srand((unsigned int)time(NULL)); 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; }
game.h文件
#define _CRT_SECURE_NO_WARNINGS //用于游戏相关函数的声明 及头文件包含 #include<stdio.h> #include<stdlib.h> #include<time.h> //实际棋盘大小 #define ROW 9 #define COL 9 //虚拟棋盘大小 #define ROWS ROW + 2 #define COLS COL + 2 //放置雷的个数(简单版本) #define EASY_COUNT 10 //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols,char set); //打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col); //放置雷 void SetMine(char mine[ROWS][COLS], int row, int col); //排查雷 void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game.c文件
#define _CRT_SECURE_NO_WARNINGS //用于游戏相关函数的具体实现 #include"game.h" //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols,char set) { int i = 0; for (i = 0; i < rows; i++) { int j = 0; for (j = 0; j < cols; j++) { board[i][j] = set; } } } //打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col) { printf("*****-- 扫雷 --*****\n"); int i = 0; for (i = 0; i <= row; i++) { printf("%d ", i); } printf("\n"); for (i = 1; i <= row; i++) { printf("%d ", i); int j = 0; for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("\n"); } } //布置雷 void SetMine(char mine[ROWS][COLS], int row, int col) { int count = EASY_COUNT; while (count) { int x = rand() % row + 1; int y = rand() % col + 1; if (mine[x][y] == '0') { mine[x][y] = '1'; count--; } } } //获取该位置周围雷的个数 int GetMineCount(char mine[ROW][COLS], int x, int y) { return (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] + mine[x - 1][y] - 8 * '0'); } //排查雷 void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int count = 0; int win = 0; while (win < row*col - EASY_COUNT) //非雷的地方一直排查 { printf("请输入要排查的坐标:>"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) //判断坐标的合法性 { if (show[x][y] == '*') //当show数组为*时,我们进行排雷 { if (mine[x][y] == '1') { printf("很遗憾,你被炸死了\n"); DisplayBoard(mine, ROW, COL); //再次显示棋盘,自己如何被炸死的 break; } else { //该坐标不是雷,就统计周围有几个雷 count = GetMineCount(mine, x, y); show[x][y] = count + '0'; //再次转换为char类型 DisplayBoard(show, ROW, COL); //显示周围雷的信息 win++; //每排查一次成功win++ } } else { printf("该位置已经被排查\n"); //非*时,说明已经被排查过了 } } else { printf("坐标非法,请重新输入\n"); } } //非雷的位置都排查完了 while循环跳出来判断游戏结束 if (win == row * col - EASY_COUNT) { printf("恭喜你,排雷成功!\n"); } }
最后,该代码还有值得被优化的地方,比如,如果点开的格子不是雷,即其周围有0颗雷,则其周围格子自动打开;如果其周围还有‘0’,则会引发连锁反应;在你认为有雷的格子上,点击右键即可标记雷;游戏计时等诸多功能。有兴趣的话,小伙伴们,可以尝试着优化一下噢~