算法|C语言版扫雷(递归实现自动展开)

先贴一张效果图
算法|C语言版扫雷(递归实现自动展开)
文章图片

扫雷的基本思路 1.首先对棋盘初始化,并印出棋盘。
2.对棋盘进行埋雷。
3.输入坐标进行排雷。
4.编写函数统计当前位置周围的雷数,当周围8个位置都没有雷时进行递归展开。
5.统计棋盘中未展开的坐标数是否与雷数相等来判断输赢。
棋盘 首先对棋盘具体分析,应该创建两个棋盘,在一个棋盘中记录雷的位置,另一个棋盘打印出来给用户查看。
因为后面要统计当前位置周围的雷数,当位置在边角时,统计位置时会造成溢出,所以我们可以考虑把棋盘大上一圈,比如99的棋盘我们可以创建成1111的。
算法|C语言版扫雷(递归实现自动展开)
文章图片

如图所示,黑色框为打印给用户看到的棋盘,红色框里面的实际创建的大小,(上下左右均比棋盘大一个)这样就可以避免在统计图中红色部分是造成越界访问了。
初始化 对雷盘和棋盘进行初始化

void InitBoard(char board[ROWS][COLS], int row, int col, char val) { int i = 0; for (int i = 0; i < row; i++) { int j = 0; for (int j = 0; j < col; j++) { board[i][j] = val; } } }

生成随机雷 在对棋盘初始化完成后,我们应该通过生成随机数来步骤雷,代码如下:
void CreateMine(char board[ROWS][COLS], int row, int col, int size) { int count = size; while (count) { int x = rand() % row + 1; int y = rand() % col + 1; if (x >= 1 && x <= row && y >= 1 && y <= col) { if (board[x][y] != '1') { board[x][y] = '1'; count--; } } } }

打印棋盘 完成布置雷后,接下来我们就可以打印出棋盘来了
void PrinBoard(char board[ROWS][COLS], int row, int col) { int i = 0; printf("_________________________________\n"); for (i = 0; i <= row; i++) printf(" %d", i); printf("\n"); for (i = 1; i <= row; i++) { int j = 1; printf("%2d ", i); for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("\n"); } printf("_________________________________\n"); }

开始扫雷 通过对用户输入的坐标进行判断当前位置是否有雷,没有雷的话就要统计当前位置周围8个格子的雷数,如果周围8个位置没有雷,就要对周围8个格子进行递归展开。反之则被炸死,游戏结束。当每次统计完 判断当前状态是否胜利。
判断输赢
通过统计棋盘中未排查的坐标个数与雷数是否相等来判断是否输赢,当与雷数相同是,排雷成功游戏结束。
void PlayerMove(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col) { int x, y; PrinBoard(show, ROW, COL); while (1) { printf("输入需要排查的坐标>"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col && show[x][y] == '*') { if (mine[x][y] == '1') { printf("您被炸死了\n"); show[x][y] = '1'; PrinBoard(show, ROW, COL); break; } else { Open(show, mine, x, y); PrinBoard(show, ROW, COL); } } else { printf("您当前输入的坐标不合法,请重新输入\n"); } int i = 0, flag = 0; for (i = 1; i <= ROW; i++) { int j = 0; for (j = 1; j <= COL; j++) { if (show[i][j] == '*') flag++; } } if (flag == MINES) { printf("玩家获胜\n"); break; } } }

展开函数
void Open(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col) { if (row > 0 && row <= ROW && col > 0 && col <= COL) { int count = Get_Mine_Count(mine, row, col); if (count != 0) show[row][col] = '0' + count; else if (show[row][col] != ' ') { show[row][col] = ' '; int i = 0; for (int i = row - 1; i <= row + 1; i++) { int j = 0; for (j = col - 1; j <= col + 1; j++) { Open(show, mine, i, j); } } } else { //show[row][col]!=' '递归停止 return ; } } }

统计周围雷数
int Get_Mine_Count(char board[ROWS][COLS], int row, int col) { int i = 0, count = 0; for (i = row - 1; i <= row + 1; i++) { int j = 0; for (j = col-1; j <= col + 1; j++) { if (board[i][j] == '1') count++; } } return count; }

完整代码如下 text.c
#include"game.h"void menu() { printf("******************************\n"); printf("********1.play*********\n"); printf("********0.EXIT*********\n"); printf("******************************\n"); }void game() { int size = MINES; char mine[ROWS][COLS]; char show[ROWS][COLS]; //初始化棋盘 InitBoard(mine, ROWS, COLS, '0'); InitBoard(show, ROWS, COLS, '*'); //布置雷 CreateMine(mine, ROW, COL, size); PlayerMove(show, mine, ROW, COL); }int main() { srand((unsigned int)time(NULL)); 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.c
#include"game.h"void InitBoard(char board[ROWS][COLS], int row, int col, char val) { int i = 0; for (int i = 0; i < row; i++) { int j = 0; for (int j = 0; j < col; j++) { board[i][j] = val; } } }void PrinBoard(char board[ROWS][COLS], int row, int col) { int i = 0; printf("_________________________________\n"); for (i = 0; i <= row; i++) printf(" %d", i); printf("\n"); for (i = 1; i <= row; i++) { int j = 1; printf("%2d ", i); for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("\n"); } printf("_________________________________\n"); }void CreateMine(char board[ROWS][COLS], int row, int col, int size) { int count = size; while (count) { int x = rand() % row + 1; int y = rand() % col + 1; if (x >= 1 && x <= row && y >= 1 && y <= col) { if (board[x][y] != '1') { board[x][y] = '1'; count--; } } } }int Get_Mine_Count(char board[ROWS][COLS], int row, int col) { int i = 0, count = 0; for (i = row - 1; i <= row + 1; i++) { int j = 0; for (j = col-1; j <= col + 1; j++) { if (board[i][j] == '1') count++; } } return count; } void Open(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col) { if (row > 0 && row <= ROW && col > 0 && col <= COL) { int count = Get_Mine_Count(mine, row, col); if (count != 0) show[row][col] = '0' + count; else if (show[row][col] != ' ') { show[row][col] = ' '; int i = 0; for (int i = row - 1; i <= row + 1; i++) { int j = 0; for (j = col - 1; j <= col + 1; j++) { Open(show, mine, i, j); } } } else { //show[row][col]!=' '递归停止 return ; } } }void PlayerMove(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col) { int x, y; PrinBoard(show, ROW, COL); while (1) { printf("输入需要排查的坐标>"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col && show[x][y] == '*') { if (mine[x][y] == '1') { printf("您被炸死了\n"); show[x][y] = '1'; PrinBoard(show, ROW, COL); break; } else { Open(show, mine, x, y); PrinBoard(show, ROW, COL); } } else { printf("您当前输入的坐标不合法,请重新输入\n"); } int i = 0, flag = 0; for (i = 1; i <= ROW; i++) { int j = 0; for (j = 1; j <= COL; j++) { if (show[i][j] == '*') flag++; } } if (flag == MINES) { printf("玩家获胜\n"); break; } } }

【算法|C语言版扫雷(递归实现自动展开)】game.h
#pragma once#define_CRT_SECURE_NO_WARNINGS #include #include #include enum { ROW = 10, COL = 10, ROWS = ROW + 2, COLS = COL + 2, MINES = 5 //雷数 }; void InitBoard(char board[ROWS][COLS], int row, int col, char val); void PrinBoard(char board[ROWS][COLS], int row, int col); void CreateMine(char board[ROWS][COLS], int row, int col, int size); void PlayerMove(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col); int Get_Mine_Count(char board[ROWS][COLS], int row, int col); void Open(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col);

    推荐阅读