(C语言)扫雷 | 您所在的位置:网站首页 › 扫雷是怎么判断雷的位置的 › (C语言)扫雷 |
需求: 1.玩家选择是否进行游戏; 2.要有反复游玩的功能;主函数代码如下: int main() { int input; 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\n"); break; } } while (input); return 0; }生成的游戏菜单 玩家输入1,进入game函数,进行游戏; 玩家输入0,结束游戏; 玩家输入其他字符,提示输入错误,重新输入; 3.game函数设计思路思路:定义界面->初始化->打印->埋雷->找雷 1.游戏界面扫雷游戏的界面是一个方盘 这里不得不提到一点:因为需要统计坐标周围8个位置雷的个数,假如要统计边界坐标周围雷的个数,那么就会造成数组越界,如果单独讨论就十分繁琐。如果我们定义了9* 9的边界,也就要定义11*11的数组元素,最外边一圈元素我们不要打印出来,如下图 既然数组已经定义好了,我们就要初始化这两个二维数组。 我们规定地雷用字符'1'表示,安全区域用字符'0'表示,而玩家的show数组则全部初始化为字符'*'。 初始化函数声明: void Init(char board[ROWS][COLS], int rows, int cols, char sign);————————————————————————— 3.打印函数 Displayboard验证是否初始化成功; 以及每次玩家点击某个坐标后,我们都要将结果打印出来。 打印函数声明: void Displayboard(char board[ROWS][COLS], int row, int col)————————————————————————— 4.设置雷的位置 SetMine首先利用宏定义雷的数量 #define bomb 10然后利用函数rand随机在上述橙色区域中布置地雷。 设置地雷函数声明: void SetMine(char board[ROWS][COLS], int row, int col);————————————————————————— 5.排查雷 FindMine需求: 1.防止第一步踩雷 2.如果踩到雷,提示玩家踩中地雷,该轮游戏结束。 3.如果没有踩雷,则在坐标中标记周围地雷数,如果标记为0,那么展开。 4.找出所有地雷,提示玩家排雷成功,该轮游戏结束。 排查雷函数声明: void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col); 4.函数定义 源码分析初始化,打印和设置地雷函数都比较简单,直接上源码。扫雷的核心在于排查地雷。 4.1 初始化函数 Init void Init(char board[ROWS][COLS], int rows, int cols, char sign) { int i, j; for (i = 0; i board[i][j] = sign; } } } 4.2 打印函数 Displayboard void Displayboard(char board[ROWS][COLS], int row, int col) { int i, j; printf("------------------------------------------\n"); for (i = 0; i printf("%d ", i); for (j = 1; j int i=bomb; while(i) { int x = rand() % row + 1; int y = rand() % col + 1; if (board[x][y] != '1') { board[x][y] = '1'; i--; } } } 4.4 排查地雷函数FindMine排查雷一定是一个循环的过程,直到出结果才能终止循环。我们可以声明变量win为安全地区的数量,当win==ROW*COL-bomb时,则排完所有地雷。 而且要求输入的坐标必须在上述的橙色区域内,否则要求玩家重新输入。 那我们就有了一个基本的框架: void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x, y; int win=0;//win为排雷数 while (1) { printf("输入坐标:>"); scanf("%d%d", &x, &y); if (x >= 1 && x = 1 && y printf("越界 重新输入\n"); } } } 4.4.1 防止第一步踩雷好的,现在我们假设输入的坐标正确,终于能玩游戏了,但是有些时候很倒霉,一上来就踩中了地雷,那我们如何避免呢? 这里就要先设计一个函数,避免你的霉运——Prevent_jinx 将你第一步脚下的地雷挪到没雷的位置去。 //防止第一步就踩中地雷 void Prevent_jinx(char mine[ROWS][COLS],int x,int y) { int m, n; while (1) { m = rand() % ROW + 1; n = rand() % COL + 1; if (mine[m][n] != '1') { mine[m][n] = '1'; mine[x][y] = '0'; break; } } }那我们怎么触发这个函数呢? 一定是在第一步的时候——即此刻排查出的安全区的数量win==0,而且你选择的坐标正好下面埋着一颗雷——mine[x][y] == '1' 于是我们的框架得到了更新: void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x, y; int win = 0;//win为安全数 如果win=总数-地雷数 则成功 while (1) { printf("输入坐标:>"); scanf("%d%d", &x, &y); if (x >= 1 && x = 1 && y Prevent_jinx(mine, x, y); } //正式进入排雷....... } else { printf("越界 重新输入\n"); } } }趟过了第一步便正式进入了排雷,下面我们将判断之后的每一步是否踩中了地雷。 假设踩中了地雷,那么我们就需要提示玩家踩中地雷,而且需要打印实际地雷位置信息,好让玩家‘死’个明白,然后退出概该轮游戏。 于是我们的框架得到了更新: void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x, y; int win = 0;//win为安全地区数 如果win=总数-地雷数 则成功 while (1) { printf("输入坐标:>"); scanf("%d%d", &x, &y); if (x >= 1 && x = 1 && y Prevent_jinx(mine, x, y); } if (mine[x][y] == '1' ) //踩中雷 { printf("踩到雷啦!\n"); Displayboard(mine, ROW, COL); break; } else //未踩中雷 { ..... } } else { printf("越界 重新输入\n"); } } } 4.4.2 展开如果没有踩中地雷,那么我们需要在show[x][y] 处标记周围八个方向的地雷个数,如果个数为0则需要展开。 展开:如果(x,y)处为0,则周围8个点依次向外找雷,如果周围找到了地雷则标记个数,否则继续向外找雷。 实现定义找周围的雷数函数——Getbombcount: int Getbombcount(char mine[ROWS][COLS], int x, int y) { int i, j,count=0; for (i = x - 1; i if (mine[i][j] == '1') count++; } } return count; }我们定义递归函数OpenMine来执行**展开**操作: void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) { if (x >= 1 && x = 1 && y show[x][y] = '0'; int i, j; //依次遍历周围八个点 for (i = x - 1; i if (show[i][j] != '*') continue; //如果已被标记过则不用进入递归,避免重复查找 OpenMine(mine, show, i, j); } } } else //count不为0 停止扩展找雷 { show[x][y] = count + '0'; } } else return; }这样的依次展开就可以排查掉许多安全区域 现在我们需要一个函数Countshow来统计以下安全区域的数量 int Countshow(char board[ROWS][COLS], int row, int col, char sign) { int count = 0,i,j; for (i = 1; i if (board[i][j] == sign) count++; } } return count; }于是我们的FindMine函数就完全写出来了: void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x, y; int win = 0;//win为排雷数 如果win=总数-地雷数 则成功 while (1) { printf("输入坐标:>"); scanf("%d%d", &x, &y); if (x >= 1 && x = 1 && y Prevent_jinx(mine, x, y); } if (mine[x][y] == '1' ) { printf("踩到雷啦!\n"); Displayboard(mine, ROW, COL); break; } else //未踩中雷 { OpenMine(mine, show, x, y); win = ROW*COL-Countshow(show, ROW, COL, '*'); if (Countshow(show, ROW, COL, '*')== bomb) { Displayboard(show, ROW, COL); printf("排雷成功\n"); break; } Displayboard(show, ROW, COL); } } else { printf("越界 重新输入\n"); } } } 5.函数声明 game.h 源码 #include #include #include //定义宏 #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define bomb 3 //初始化 void Init(char board[ROWS][COLS], int rows, int cols, char sign); //打印游戏界面 void Displayboard(char board[ROWS][COLS], int row, int col); //布置地雷 void SetMine(char board[ROWS][COLS], int row, int col); //排查雷 void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col); 6.main函数 test.h 源码 #include "game.h" void menu() { printf("*******************\n"); printf("***0.exit 1.play***\n"); printf("*******************\n"); } void game() { //定义存放地雷的数组 和 玩家游玩的数组 char mine[ROWS][COLS],show[ROWS][COLS]; //初始化数组 Init(mine,ROWS,COLS,'0'); Init(show, ROWS, COLS, '*'); //打印 //Displayboard(mine,ROW,COL); //Displayboard(show, ROW, COL); //布置地雷 SetMine(mine,ROW,COL); Displayboard(mine, ROW, COL); Displayboard(show, ROW, COL); //排查雷 FindMine(mine,show,ROW,COL); } int main() { int input; 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\n"); break; } } while (input); return 0; } 7 函数定义 game.c 源码 #include "game.h" //初始化 void Init(char board[ROWS][COLS], int rows, int cols, char sign) { int i, j; for (i = 0; i board[i][j] = sign; } } } //打印游戏界面 void Displayboard(char board[ROWS][COLS], int row, int col) { int i, j; printf("------------------------------------------\n"); for (i = 0; i printf("%d ", i); for (j = 1; j int i=bomb; while(i) { int x = rand() % row + 1; int y = rand() % col + 1; if (board[x][y] != '1') { board[x][y] = '1'; i--; } } } //获取坐标周围地雷数目 int Getbombcount(char mine[ROWS][COLS], int x, int y) { int i, j,count=0; for (i = x - 1; i if (mine[i][j] == '1') count++; } } return count; } //防止第一步就踩中地雷 void Prevent_jinx(char mine[ROWS][COLS],int x,int y) { int m, n; while (1) { m = rand() % ROW + 1; n = rand() % COL + 1; if (mine[m][n] != '1') { mine[m][n] = '1'; mine[x][y] = '0'; break; } } } void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) { if (x >= 1 && x = 1 && y show[x][y] = '0'; int i, j; for (i = x - 1; i if (show[i][j] != '*') continue; //如果已被排雷过则不用递归 OpenMine(mine, show, i, j); } } } else //count不为0 停止扩展 { show[x][y] = count + '0'; } } else return; } int Countshow(char board[ROWS][COLS], int row, int col, char sign) { int count = 0,i,j; for (i = 1; i if (board[i][j] == sign) count++; } } return count; } //排查雷 void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x, y; int win = 0;//win为排雷数 如果win=总数-地雷数 则成功 while (1) { printf("输入坐标:>"); scanf("%d%d", &x, &y); if (x >= 1 && x = 1 && y Prevent_jinx(mine, x, y); } if (mine[x][y] == '1' ) { printf("踩到雷啦!\n"); Displayboard(mine, ROW, COL); break; } else //未踩中雷 { OpenMine(mine, show, x, y); win = ROW*COL-Countshow(show, ROW, COL, '*'); if (Countshow(show, ROW, COL, '*')== bomb) { Displayboard(show, ROW, COL); printf("排雷成功\n"); break; } Displayboard(show, ROW, COL); } } else { printf("越界 重新输入\n"); } } } 8.实际游玩效果第一把 :设置bomb为2 |
CopyRight 2018-2019 实验室设备网 版权所有 |