扫雷游戏是一款经典的单人电脑游戏,最初由微软公司开发。玩家需要根据数字提示,在不触雷的情况下揭开所有格子。这是一款考验逻辑思维和运气的游戏,而我们将用C语言来实现它。

该程序有一个头文件和两个源文件构成。在头文件game.h中进行函数的声明,在源文件game.c中进行函数的实现,在test.c中进行程序测试,实现主函数。接下来我将从主函数开始进行代码的逐一讲解,需要源代码可以在勤奋的土豆 (rolltudou) – Gitee.com中的bite_begin路径下进行查找或者在文章结尾会有全部源代码。

一、test.c

1、main

int main(void){test();return 0;}

在mian函数中用test来实现过程,用于启动游戏。

2、test

void test(){int input = 0;do{menu();printf("please choice number to take part in game or give out >");scanf("%d",&input);switch (input){case 1:game();break;case 0:printf("game over\n");break;default:printf("you put nmber is fault,please choice again\n");break;}} while (input);}

在test中进行整体游戏的实现,首先用do while循环进行持续进行,循环中首先进行打印菜单menu(),然后通过menu()中的选项,用switch进行选择,可以进行游戏、结束游戏,在输入的数字有问题的时候会提示输入有误,让用户进行重新输入。

接下来由从上到下,从内到外的顺序进行逐个讲解。

3、menu

void menu(){printf("\n******1.game begin****\n");printf("******0.game over ****\n");}

4、game

void game(){//mine is mine's informationchar mine[ROWS][COLS] = { 0 };//The show array stores the information of the detected mineschar show[ROWS][COLS] = { 0 };//Initialize the board(The show and mine all use one funk)InitBoard(mine, ROWS,COLS,'0');InitBoard(show, ROWS, COLS, '*');//setmine //9*9 10 mineSetMine(mine, ROW, COL);//print boardDisplayBoard(show,ROW,COL);//find mineFindMine(mine, show, ROW, COL);}

在game.h中对ROW,COL,ROWS,COLS进行宏定义,方便对棋盘大小进行更改。

#define ROW 9
#define COL 9

#define ROWS ROW + 2
#define COLS COL + 2

在游戏中需要两个数组,一个是雷的数组,一个用来展示给玩家的看的数组。

用InitBoard函数对mine和show数组进行初始化。

用SetMine进行对雷的放置。

用DisplayBoard进行棋盘的打印。

用FindMine进行雷的查找。

二、game.c

1.InitBoard

void InitBoard(char arr[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){arr[i][j] = set;}}}

为了保证函数的通用性用char set进行形参,来保证可以用不同的字符进行初始化。另外,用ROWS和COLS将棋盘制造出一个空白框,保证在查找的时候对空白地方进行扫描的时候不会影响查找雷。

2、SetMine

void SetMine(char arr[ROWS][COLS], int row, int col){int count = EASY_COUNT;while (count){int x = rand() % 9 + 1;int y = rand() % 9 + 1;//judge arr[x][y] ,when arr[x][y] don't setted mine just do it.if (arr[x][y] == '0'){arr[x][y] = '1';--count;}}}

在game.h中宏定义EASY_COUNT的数量,方便更改游戏难度。

为了做到雷可以在棋盘上随机坐标进行排布,用rand()获取随机坐标进行雷的放置。另外进行if判断,如果这个坐标没有放置过的话才会进行放置‘1’。

3、FindMine

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col){int x = 0;int y = 0;int win = 0;while (win = 1 && x = 1 && y <= col){if (show[x][y] == '*'){//if mine ,you're died; if no,show mine number and open blockif (mine[x][y] == '1'){//cleansystem("cls");printf("you are dead");DisplayBoard(mine, ROW, COL);break;}else{//count mine number//int count = GetMineCount(mine, x, y);//show[x][y] = count + '0';//cleansystem("cls");open(mine, show, x, y);DisplayBoard(show, ROW, COL);++win;}}else{printf("The coordinates have been checked\n");}}else{printf("The coordinates are invalid, please re-enter them\n");}}if (win == row * col - EASY_COUNT){printf("You're such a f**king genius\n");DisplayBoard(mine, ROW, COL);}}

代码逻辑为以下:

  • 使用while循环来持续进行雷区的查找,直到玩家找到所有非雷区的格子。
  • 通过scanf获取玩家输入的坐标,然后进行合法性判断。
  • 根据玩家的输入,判断是否触雷,如果触雷则游戏结束,否则显示周围雷的数量并打开相应的格子。

4、open

void open(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y){if (x >= 1 && x = 1 && y <= COL){int count = GetMineCount(mine, x, y);//rerurn mine number//如果该格子周围雷的个数不为0,我们就把该格子周围雷的个数传到玩家玩的show棋盘对应的格子中,而如果是0,我们传入空格‘ ’ if (count != 0){show[x][y] = count + '0';//由于count返回的是整数,而存入数组中的是字符,我们需要加上‘0’,相当于加上ASCII值48}else if (show[x][y] != ' '){show[x][y] = ' ';int i = 0;for (i = x - 1; i <= x + 1; i++){int j = 0;for (j = y - 1; j <= y + 1; j++){//Function recursion,until around all have mine.open(mine, show, i, j);}}}else{return;}}}

open函数使用递归的方法进行每次查找到空白的时候展开周围不是雷的一片区域。

对于递归地方的说明:如果该位置周围没有地雷且展示数组show的对应位置不是空格,那么将该位置的展示数组show的值设为空格,并遍历该位置周围的8个格子,对每个格子再次调用open函数,实现递归展开空白区域的功能。如果该位置周围没有地雷且展示数组show的对应位置已经是空格,则直接返回,不做任何处理。

5、GetMineCount

static int GetMineCount(char mine[ROWS][COLS], int x, int y){int i = 0;int count = 0;for (i = x - 1; i <= x + 1; i++){int j = 0;for (j = y - 1; j <= y + 1; j++){count += (mine[i][j] - '0');}}return count;}

在扫雷中通过查找选中坐标九宫格内的雷的个数,然后在选中坐标进行显示。

也可以通过以下代码进行查询,效果相同:

int get_mine(char mine[ROWS][COLS], int x, int y){return mine[x][y + 1] + mine[x][y - 1] + mine[x - 1][y] + mine[x + 1][y]+ mine[x + 1][y + 1] + mine[x - 1][y - 1] + mine[x + 1][y - 1] +mine[x - 1][y + 1] - 8 * '0';}

二、源代码

1、键盘输入坐标查找(本篇代码)

①game.h

#pragma once#define _CRT_SECURE_NO_WARNINGS 1#define ROW 9#define COL 9#define ROWS ROW + 2#define COLS COL + 2#define EASY_COUNT 10#include #include//initialize boardvoid InitBoard(char arr[ROWS][COLS], int rows, int cols);//set minevoid SetMine(char arr[ROWS][COLS], int row, int col);//print boardvoid DisplayBoard(char arr[ROWS][COLS], int row, int col);//find minevoid FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//open blockvoid open(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

②test.c

#include"game.h"void game(){//mine is mine's informationchar mine[ROWS][COLS] = { 0 };//The show array stores the information of the detected mineschar show[ROWS][COLS] = { 0 };//Initialize the board(The show and mine all use one funk)InitBoard(mine, ROWS,COLS,'0');InitBoard(show, ROWS, COLS, '*');//setmine //9*9 10 mineSetMine(mine, ROW, COL);//print boardDisplayBoard(show,ROW,COL);//find mineFindMine(mine, show, ROW, COL);}void menu(){printf("\n******1.game begin****\n");printf("******0.game over ****\n");}void test(){int input = 0;do{menu();printf("please choice number to take part in game or give out >");scanf("%d",&input);switch (input){case 1:game();break;case 0:printf("game over\n");break;default:printf("you put nmber is fault,please choice again\n");break;}} while (input);}int main(void){test();return 0;}

③game.c

#include"game.h"void InitBoard(char arr[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){arr[i][j] = set;}}}void SetMine(char arr[ROWS][COLS], int row, int col){int count = EASY_COUNT;while (count){int x = rand() % 9 + 1;int y = rand() % 9 + 1;//judge arr[x][y] ,when arr[x][y] don't setted mine just do it.if (arr[x][y] == '0'){arr[x][y] = '1';--count;}}}void DisplayBoard(char arr[ROWS][COLS], int row, int col){int i = 0;//print the first row nmber showfor (i = 0; i <= col; ++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 ",arr[i][j]);}printf("\n");}}static int GetMineCount(char mine[ROWS][COLS], int x, int y){int i = 0;int count = 0;for (i = x - 1; i <= x + 1; i++){int j = 0;for (j = y - 1; j = 1 && x = 1 && y <= COL){int count = GetMineCount(mine, x, y);//rerurn mine number//如果该格子周围雷的个数不为0,我们就把该格子周围雷的个数传到玩家玩的show棋盘对应的格子中,而如果是0,我们传入空格‘ ’ if (count != 0){show[x][y] = count + '0';//由于count返回的是整数,而存入数组中的是字符,我们需要加上‘0’,相当于加上ASCII值48}else if (show[x][y] != ' '){show[x][y] = ' ';int i = 0;for (i = x - 1; i <= x + 1; i++){int j = 0;for (j = y - 1; j <= y + 1; j++){//Function recursion,until around all have mine.open(mine, show, i, j);}}}else{return;}}}void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col){int x = 0;int y = 0;int win = 0;while (win = 1 && x = 1 && y <= col){if (show[x][y] == '*'){//if mine ,you're died; if no,show mine number and open blockif (mine[x][y] == '1'){//cleansystem("cls");printf("you are dead");DisplayBoard(mine, ROW, COL);break;}else{//count mine number//int count = GetMineCount(mine, x, y);//show[x][y] = count + '0';//cleansystem("cls");open(mine, show, x, y);DisplayBoard(show, ROW, COL);++win;}}else{printf("The coordinates have been checked\n");}}else{printf("The coordinates are invalid, please re-enter them\n");}}if (win == row * col - EASY_COUNT){printf("You're such a f**king genius\n");DisplayBoard(mine, ROW, COL);}}

2、鼠标操作(可选择难度)

该程序将在之后的博客进行讲解。

欢迎关注。

①game.h

#pragma once#define _CRT_SECURE_NO_WARNINGS#include #include  // time 函数需要的头文件#include  // rand、 srand、malloc 函数需要的头文件#include #include void initBoard(char** arr, int rows, int cols, char set);int display(char** arr, int row, int col, int y, int x, int* time);void setMine(char** mine, int row, int col, int y, int x);void findMine(char** mine, char** show, int row, int col);void spread(char** mine, char** show, int y, int x, int* win, int row, int col);void numberSpread(char** mine, char** show, int y, int x, int num, int* win, int row, int col);// 动态扫雷实现char** apply(int* rows, int* cols);void release(char** arr, int rows, int cols);int getMine();void myApply(int* rows, int* cols);int myGetMine();// 伪图形扫雷实现void game();void gotoxy(int a, int b);void HideCursor();int option(int* rows, int* cols);// 鼠标操作void getPower();void mouseOperateGame(char** mine, char** show, int mouseOperate, int y, int x, int row, int col, int first, int* win);//GetAsyncKeyState(VK_RBUTTON); // 右键//GetAsyncKeyState(VK_LBUTTON); // 左键//右键//mouseRecord.Event.MouseEvent.dwButtonState == RIGHTMOST_BUTTON_PRESSED//左键//if (mouseRecord.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)

②test.c

#include "game.h"int getMineCount = 0;//定义句柄变量HANDLE get1;//权限准备DWORD get2 = ENABLE_EXTENDED_FLAGS | ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT;//定义输入事件结构体INPUT_RECORD mouseRecord;//用于存储读取记录DWORD res;void getPower() // 获取权限{if (!SetConsoleMode(get1, get2))fprintf(stderr, "%s\n", "SetConsoleMode");}void adjustScreen(){system("cls");printf("Ctrl + 滑动鼠标滑轮调整大小\n");printf("注意:若实际游戏画面大于程序窗口会出现刷屏哦\n");printf("按任意键返回:>\n");char ch = _getch();system("cls");}void menu1(){getPower();char a = 0;int y = 0;int x = 0;int exitgame = 0;int judge = 1;while (1){gotoxy(0, 0);//读取输入事件ReadConsoleInput(get1, &mouseRecord, 1, &res);//获取鼠标当前位置y = mouseRecord.Event.MouseEvent.dwMousePosition.Y;x = mouseRecord.Event.MouseEvent.dwMousePosition.X;char arr[3][13] = { "开始游戏", "调整画面", "退出游戏" }; printf("*************************\n");if ((y == 1) && (4 <= x && x <= 21)){printf("****\033[41m %-10s\033[0m****\n", &arr[0][0]);}elseprintf("**** %-12s****\n", &arr[0][0]);if ((y == 2) && (4 <= x && x <= 21)){printf("****\033[41m %-10s\033[0m****\n", &arr[1][0]);}elseprintf("**** %-12s****\n", &arr[1][0]);if ((y == 3) && (4 <= x && x <= 21)){printf("****\033[41m %-10s\033[0m****\n", &arr[2][0]);}elseprintf("**** %-12s****\n", &arr[2][0]);printf("*************************\n");printf("若点一下无反应可重新点一下\n");int mouseOperate = 0;if (judge)mouseOperate = mouseRecord.Event.MouseEvent.dwButtonState;else if (GetAsyncKeyState(VK_LBUTTON))judge = 1;elsemouseOperate = 0;if (mouseRecord.EventType == MOUSE_EVENT){switch (mouseOperate){case FROM_LEFT_1ST_BUTTON_PRESSED:if ((y == 1) && (4 <= x && x <= 21)){system("cls"); // 先清屏game();getPower();}if ((y == 2) && (4 <= x && x <= 21)){adjustScreen();judge = 0;getPower();}if ((y == 3) && (4 <= x && x <= 21)){system("cls");// 先清屏printf("%s\n", "退出游戏");exitgame = 1;}break;}}GetAsyncKeyState(VK_LBUTTON);Sleep(50);if (exitgame)break;}}int option(int* rows, int* cols){GetAsyncKeyState(VK_LBUTTON);getPower();char a = 0;int y = 0;int x = 0;while (1){gotoxy(0, 0); // 固定画面//读取输入事件ReadConsoleInput(get1, &mouseRecord, 1, &res);//获取鼠标当前位置y = mouseRecord.Event.MouseEvent.dwMousePosition.Y;x = mouseRecord.Event.MouseEvent.dwMousePosition.X;char arr[4][20] = { "1.初级(9×9)", "2.中级(16×16)", "3.高级(16×30)", "返回" };printf("*************************\n");if ((y == 1) && (4 <= x && x <= 22))printf("****\033[41m %-15s\033[0m****\n", &arr[0][0]);elseprintf("**** %-15s****\n", &arr[0][0]);if ((y == 2) && (4 <= x && x <= 22))printf("****\033[41m %-15s\033[0m****\n", &arr[1][0]);elseprintf("**** %-15s****\n", &arr[1][0]);if ((y == 3) && (4 <= x && x <= 22))printf("****\033[41m %-15s\033[0m****\n", &arr[2][0]);elseprintf("**** %-15s****\n", &arr[2][0]);if ((y == 4) && (4 <= x && x <= 22))printf("****\033[41m %-14s\033[0m****\n", &arr[3][0]);elseprintf("**** %-14s****\n", &arr[3][0]);printf("*************************\n");int mouseOperate = mouseRecord.Event.MouseEvent.dwButtonState;if (mouseRecord.EventType == MOUSE_EVENT){switch (mouseOperate){case FROM_LEFT_1ST_BUTTON_PRESSED:if ((y == 1) && (4 <= x && x <= 22)){*rows = 11;*cols = 11;return 1;}if ((y == 2) && (4 <= x && x <= 22)){*rows = 18;*cols = 18;return 2;}if ((y == 3) && (4 <= x && x <= 22)){*rows = 18;*cols = 32;return 3;}if ((y == 4) && (4 <= x && x <= 22)){return -1;}break;}}Sleep(50);}return 1;}void game(){int rows = 0;int cols = 0;int num = option(&rows, &cols);system("cls");if (num < 0)return;char** mine = apply(&rows, &cols);char** show = apply(&rows, &cols);getMineCount = getMine(num);int row = rows - 2;int col = cols - 2;initBoard(mine, rows, cols, '0');initBoard(show, rows, cols, '*');findMine(mine, show, row, col);release(mine, rows, cols);release(show, rows, cols);}void test(){get1 = GetStdHandle(STD_INPUT_HANDLE);HideCursor();srand((unsigned int)time(NULL)); // 使rand函数产生伪随机数menu1();CloseHandle(get1);}int main(){test();return 0;}

③game.c

#include "game.h"extern int getMineCount;extern HANDLE get1;extern DWORD get2;extern INPUT_RECORD mouseRecord;extern DWORD res;void gotoxy(int a, int b){HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);COORD pos;pos.X = a;pos.Y = b;SetConsoleCursorPosition(handle, pos);}void HideCursor(){CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);}void initBoard(char** arr, int rows, int cols, char set){for (int i = 0; i < rows; i++)for (int j = 0; j < cols; j++)arr[i][j] = set;}int display(char** arr, char** mine, char** show, int row, int col, int y, int x, int time1, int* first, int* win, int mouseOperate){int FCount = 0;static int time2 = 0;if (win != NULL){//游戏进行时间 为 当前时间减去 进入游戏的时间time2 = (int)time(NULL) - time1;}int i, j;for (i = 0; i <= col / 2 - 2; i++)printf("--");printf("time:%-3d", time2);for (i = 0; i <= col / 2 - 3; i++)printf("--");printf("\n");for (i = 1; i <= row; i++)for (j = 1; j  getMineCount) // 防止雷数量成为负数FCount = getMineCount;for (i = 1; i <= row; i++){printf("|");for (j = 1; j <= col; j++) // 打印扫雷内容{if (i == y && j * 2 == x + 1){printf("\033[42m%c\033[0m ", arr[i][j]);if (mouseRecord.EventType == MOUSE_EVENT){mouseOperateGame(mine, show, mouseOperate, i, j, row, col, first, win, FCount);}}else{if (arr[i][j] == '*')printf("%c ", arr[i][j]);if (arr[i][j] == '0')printf("\033[30m%c\033[0m ", arr[i][j]); // 黑色if (arr[i][j] == '1')printf("\033[36m%c\033[0m ", arr[i][j]); // 浅蓝色if (arr[i][j] == '2')printf("\033[34m%c\033[0m ", arr[i][j]); // 蓝色if (arr[i][j] == '3')printf("\033[33m%c\033[0m ", arr[i][j]); // 黄色if (arr[i][j] == '4')printf("\033[31m%c\033[0m ", arr[i][j]); // 红色if (arr[i][j] == '5')printf("\033[35m%c\033[0m ", arr[i][j]); // 紫色if (arr[i][j] == '6')printf("%c ", arr[i][j]);if (arr[i][j] == '7')printf("%c ", arr[i][j]);if (arr[i][j] == 'F')printf("\033[32m%c\033[0m ", arr[i][j]); // 绿色}}printf("\n"); // 换行}for (i = 0; i <= col / 2 - 2; i++)printf("--");printf("雷:\033[31m%d\033[0m", getMineCount - FCount); // 表示当前雷的数量for (i = 0; i <= col / 2 - 2; i++)printf("--");printf("\n");int goBack = 0;}void setMine(char** mine, int row, int col, int y, int x){int count = 0;int i, j;// 记录输入行和旁边的两行int judgeRow[3] = { 0 };for (int k = -1, a = 0; k <= 1; k++, a++)judgeRow[a] = k + y;// 记录输入列和旁边的两列int judgeCol[3] = { 0 };for (int k = -1, a = 0; k <= 1; k++, a++)judgeCol[a] = k + x;while (count < getMineCount) // 布置雷的数量,数量到达时则跳出循环{i = rand() % row + 1; // 行// 当输入行且旁边两行与布置行不同时if (i != judgeRow[0] && i != judgeRow[1] && i != judgeRow[2])j = rand() % col + 1; // 列// 当输入行或旁边两行与布置行相同时else{do{j = rand() % col + 1;// 若输入列或旁边两列与布置列相同则进入循环} while (j == judgeCol[0] || j == judgeCol[1] || j == judgeCol[2]);}if (mine[i][j] == '0') // 若为 '0',则放置雷{mine[i][j] = '1';count++;}}}int mineCount(char** mine, int y, int x){int count = 0;for (int i = -1; i <= 1; i++)for (int j = -1; j = '1' && show[y][x] <= '7')numberSpread(mine, show, y, x, show[y][x] - '0', win, row, col);break;caseRIGHTMOST_BUTTON_PRESSED:if (show[y][x] == '*' && FCount < getMineCount)show[y][x] = 'F';break;}}void findMine(char** mine, char** show, int row, int col){getPower();// 注:由于扫雷下标从1开始,在 3.游戏操作 中需要变通一下int x = 1; // 横轴移动int y = 1; // 纵轴移动int time1 = (int)time(NULL); // 获取进入游戏的时间int win = 0;int mouseOperate = 0;int first = 1;int falseTime = 1;int winTime = 1;while (1) {gotoxy(0, 0);ReadConsoleInput(get1, &mouseRecord, 1, &res);//获取鼠标当前位置y = mouseRecord.Event.MouseEvent.dwMousePosition.Y;x = mouseRecord.Event.MouseEvent.dwMousePosition.X;mouseOperate = mouseRecord.Event.MouseEvent.dwButtonState;// 当win为负数意思为被雷炸死if (win = 0)display(show, mine, show, row, col, y, x, time1, &first, &win, mouseOperate);if (win >= row * col - getMineCount){if (winTime){system("cls");getPower();winTime = 0;}display(show, mine, show, row, col, y, x, time1, NULL, NULL, 0);printf("**********************\n");printf("******你赢了******\n");printf("**********************\n");if ((y == row + 5) && (5 <= x && x <= 16)){printf("*****\033[41m%6s\033[0m*****\n", "返回");if (mouseOperate == FROM_LEFT_1ST_BUTTON_PRESSED){system("cls");break;}}elseprintf("*****%6s*****\n", "返回");}if (win < 0){if (falseTime){system("cls");getPower();falseTime = 0;}display(mine, mine, show, row, col, y, x, time1, NULL, NULL, 0);printf("**********************\n");printf("**很遗憾,你被炸死了**\n");printf("**********************\n");if ((y == row + 5) && (5 <= x && x <= 16)){printf("*****\033[41m%6s\033[0m*****\n", "返回");if (mouseOperate == FROM_LEFT_1ST_BUTTON_PRESSED){system("cls");break;}}elseprintf("*****%6s*****\n", "返回");}}}void spread(char** mine, char** show, int y, int x, int* win, int row, int col){if (show[y][x] == '0') // 若周围没有雷才进入{for (int i = -1; i <= 1; i++) // 行{for (int j = -1; j = 1 && y + i = 1 && x + j <= col) // 防止超出9×9的范围{if (show[y + i][x + j] == '*')// 防止反复递归同一个坐标{int count = mineCount(mine, y + i, x + j);show[y + i][x + j] = count + '0'; // 将已经递归过的坐标显示它周围雷的数量,防止反复递归同一个坐标(*win)++; // 增加查找非雷坐标的数量spread(mine, show, y + i, x + j, win, row, col); // 进入下一次递归}}}}}}void numberSpread(char** mine, char** show, int y, int x, int num, int* win, int row, int col){int unknown = 0; // 未知坐标的数量int unknownBlank = 0;// 未知坐标且未插旗的数量int FCount = 0; // 插旗坐标的数量// 记录周围三者的数量for (int i = -1; i <= 1; i++){for (int j = -1; j  num && FCount >= num && unknownBlank != 0) // 周围未知的坐标的数量要大于周围雷的数量{for (int i = -1; i <= 1; i++) // 行{for (int j = -1; j = 1 && y + i = 1 && x + j <= col){// 数字展开时扫到雷if (show[y + i][x + j] == '*' && mine[y + i][x + j] == '1'){(*win) = -9;}// 数字展开扫到非雷else if (show[y + i][x + j] == '*' && mine[y + i][x + j] == '0'){int count = mineCount(mine, y + i, x + j);show[y + i][x + j] = count + '0';(*win)++;spread(mine, show, y + i, x + j, win, row, col);}}}}}}char** apply(int* rows, int* cols){// 申请二级指针(二维数组)行的数量char** arr = (char**)malloc(sizeof(char*) * (*rows));if (NULL == arr){printf("游戏异常,已退出\n");exit(-1);}// 申请每行之中列的数量for (int i = 0; i < *rows; i++){arr[i] = (char*)malloc(sizeof(char) * (*cols));if (NULL == arr[i]){printf("游戏异常,已退出\n");exit(-1);}}// 返回首元素地址return arr;}void release(char** arr, int rows, int cols){// 先释放一级指针空间for (int i = 0; i < rows; i++)free(arr[i]);// 后释放二级指针的空间free(arr);}int getMine(int num){switch (num){case 1:return 10;case 2:return 40;case 3:return 99;}return 0;}

以上即是本篇博客的全部内容,关于扫雷有以下总结:整个程序的实现逻辑是:首先进行游戏初始化,包括初始化游戏板和设置雷的位置;然后进入游戏进行阶段,玩家根据提示逐步打开格子;最后根据玩家的操作进行递归地打开格子或者判断游戏是否结束。游戏菜单和测试函数用于启动游戏和提供交互界面。