文章目录

  • 前言
  • 一、扫雷的游戏规则
  • 二、扫雷设计的大概思路
  • 三、扫雷设计的详细思路和代码
    • 1.首先定义一个菜单menu函数
    • 2.在test函数中调用menu函数
    • 3.在main函数中在调用test函数
    • 4.以上均在text.c中进行,然后我们需要在text.c文件中调用game函数,然后在game.c的源文件实现其功能,实现game函数的具体思路和代码如下
      • 1.定义2个棋盘mine,show的二维数组
      • 2.初始化棋盘,其中mine全部初始化为'0',有雷的地方定为'1',用0,1是为了方便统计周围雷的数量。show是用来给玩家来玩的,一开始全部初始化为'*'
      • 3.打印棋盘mine,show,而实际玩的时候不需要打印出mine棋盘,这里我们把两个棋盘打印出来
      • 4.然后就是设置雷,也就是埋雷了,在mine数组中我们用1代表雷,我们在头文件中定义#define EAZY 10代表简单模式下要排的10个雷,这样更方便我们后续更改雷的个数
      • 5.设置完雷后便是排查雷了
      • 6.由于排查雷的时候我们使用了open(mine, show, x, y)来展开一片空白,接下来我们对open函数进行实现
      • 7.由于实现open展开函数的时候用到了统计雷个数函数get_mine,接下来我们需要在这之前实现get_mine(mine, x, y)
      • 8.以上就实现了整个扫雷游戏
    • 5.总的代码如下
  • 四、总结
  • 此外

前言




我们都知道扫雷分给不同等级
一下操作均以最基础的9*9棋盘,10个雷的难度演示

一、扫雷的游戏规则

1.扫雷的基本规则:找出空的方块和雷区。如果确定该方块为空,可以左键点击一下,如果认为是雷可以右键点击一下插上小旗,右击两次代表不确认。

2.左下角代表游戏时间,右下角代表剩余雷的数量。

3.首先开始我们都不知道哪里是雷,就需要任意选择一个,小编一般喜欢从四个角落开始。

4.游戏中的数字代表周围八个方向雷的数量,如下图中的数字1,周围的空格已经全部打开,只剩下一个方格,那么这一个肯定就是雷了。

5.游戏中要注意各个数字间的配合,仔细一点。

6.有时候可能会遇到无法判断具体哪一个是雷的情况,这样需要我们根据周围的数字去判断最有可能的是哪一个。

二、扫雷设计的大概思路

定义2个棋盘mine,show
其中mine全部初始化为’0’,有雷的地方定为’1’,用0,1是为了方便统计周围雷的数量
show是用来给玩家来玩的,一开始全部初始化为’*‘
初始化
打印棋盘
设置雷
排查雷
展开

三、扫雷设计的详细思路和代码

为了确保程序的独立性
我们创造两个源文件game.c和text.c,一个头文件game.h实现程序的模块化进行
其中game.c用来实现整个游戏的具体操作
text.c用来最终调用game.c来实现运行
这就需要创造一个头文件game.h来实现上述的调用

1.首先定义一个菜单menu函数

代码如下(示例):

//游戏菜单:选择是否开始玩儿游戏,1:玩儿,0:退出游戏;
void menu()
{printf("*************************\n");printf("******** 1.play  ********\n");printf("******** 0.exit  ********\n");printf("*************************\n");
}

2.在test函数中调用menu函数

使用函数调用的方式实现

void text()
{int input = 0;do{menu();printf("请选择是否进行游戏\n");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误,请重新选择\n");break;}} while (input);
}

3.在main函数中在调用test函数

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

至此之前的操作和三子棋操作大体相同

4.以上均在text.c中进行,然后我们需要在text.c文件中调用game函数,然后在game.c的源文件实现其功能,实现game函数的具体思路和代码如下

1.定义2个棋盘mine,show的二维数组

虽然我们要打印99的棋盘,但为了后续能更好的统计最外围雷的个数
我们需要在最外围各自在加上一行,相当于以左右上下各加一行,相当于11
11的棋盘
后续在其9*9的棋盘上进行操作即可
所以在头文件game.h中,定义后续操作需要用的ROW,COL,ROWS,COLS

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

然后在text.c文件中我们创出两个11*11的二维数组

void game()
{char mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };}

2.初始化棋盘,其中mine全部初始化为’0’,有雷的地方定为’1’,用0,1是为了方便统计周围雷的数量。show是用来给玩家来玩的,一开始全部初始化为’*’

在text.c文件的game函数中

void game()
{//定义2个棋盘mine,showchar mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };//初始化//其中mine全部初始化为'0',有雷的地方定为'1',用0,1是为了方便统计周围雷的数量//show是用来给玩家来玩的,一开始全部初始化为'*'init_board(mine, ROWS, COLS,'0');init_board(show, ROWS, COLS,'*');
}

其中为使代码更精简,我们用board来接收mine和show,传入的’0‘和’*‘用met接收
因为mine和show的区别只是要初始化的值不同,故这样操作可以一举两得

在头文件game.h中声明两个初始化函数

//初始化棋盘
void init_board(char board[ROWS][COLS], int rows, int cols,int met);

在到game.c文件中具体实现初始化实现nit_board函数

void init_board(char board[ROWS][COLS], int rows, int cols,int met)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){board[i][j] = met;}}
}

3.打印棋盘mine,show,而实际玩的时候不需要打印出mine棋盘,这里我们把两个棋盘打印出来

在text.c文件的game函数中调用print函数,由于我们要打印9*9的棋盘,因此我们传入ROW,COL

void game()
{//定义2个棋盘mine,showchar mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };//初始化//其中mine全部初始化为'0',有雷的地方定为'1',用0,1是为了方便统计周围雷的数量//show是用来给玩家来玩的,一开始全部初始化为'*'init_board(mine, ROWS, COLS,'0');init_board(show, ROWS, COLS,'*');//打印棋盘//display_board(mine, ROW, COL);display_board(show, ROW, COL);}

同样的和初始化一样的思路,为了使代码更加精简,我们用board来接收mine和show,
打印所需的棋盘即可

所以在头文件game.h中定义print函数

//打印棋盘
void display_board(char board[ROWS][COLS], int row, int col);

然后我们到game.c文件中实现print函数

void display_board(char board[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;printf("--------- 扫雷 ---------\n");for (y = 0; y <= col; y++)//打印第一行的行标{printf("%d ", y);}printf("\n");//打印行for (x = 1; x <= row; x++){printf("%d ", x);//打印第一列的列标//打印列for (y = 1; y <= col; y++){printf("%c ", board[x][y]);}printf("\n");}printf("--------- 扫雷 ---------\n");
}

效果如下

4.然后就是设置雷,也就是埋雷了,在mine数组中我们用1代表雷,我们在头文件中定义#define EAZY 10代表简单模式下要排的10个雷,这样更方便我们后续更改雷的个数

在text.c文件的game函数中调用setmine函数

void game()
{//定义2个棋盘mine,showchar mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };//初始化//其中mine全部初始化为'0',有雷的地方定为'1',用0,1是为了方便统计周围雷的数量//show是用来给玩家来玩的,一开始全部初始化为'*'init_board(mine, ROWS, COLS,'0');init_board(show, ROWS, COLS,'*');//打印棋盘//display_board(mine, ROW, COL);display_board(show, ROW, COL);//设置雷setmine(mine, ROW, COL);//display_board(show, ROW, COL)}

在头文件game.h中声明setmine函数,并定义EAZY 10代表雷的个数

//雷的个数
#define EASY 10
//设置雷
void setmine(char mine[ROWS][COLS], int row, int col);

在game.c中我们实现setmine函数

void setmine(char mine[ROWS][COLS], int row, int col)
{int count = EASY;int x = 0;int y = 0;while (count){x = rand() % row + 1;y = rand() % col + 1;if (mine[x][y] == '0'){mine[x][y] = '1';count--;}}
}

我们使用rand函数随机产生雷,而使用rand需要和srand连用才能产生随机数,所以我们需要在text.c文件的main函数中使用srand

int main()
{srand((unsigned int)time(NULL));text();return 0;
}

使用rand和srand,time库函数需要引用头文件
使用在头文件game.h中

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

至此我们雷已经设置完了,我们打印出来mine棋盘效果如下

5.设置完雷后便是排查雷了

我们在text.c的game函数中调用check函数,并传入mine,show两个数组和ROW,COL

void game()
{//定义2个棋盘mine,showchar mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };//初始化//其中mine全部初始化为'0',有雷的地方定为'1',用0,1是为了方便统计周围雷的数量//show是用来给玩家来玩的,一开始全部初始化为'*'init_board(mine, ROWS, COLS,'0');init_board(show, ROWS, COLS,'*');//打印棋盘//display_board(mine, ROW, COL);display_board(show, ROW, COL);//设置雷setmine(mine, ROW, COL);//display_board(mine, ROW, COL);//排查雷check(mine,show, ROW, COL);}

在头文件game.h中声明check

//排查雷
void check(char mine[ROWS][COLS],char show[ROWS][COLS],int row, int col);

在game.c文件中实现

//排查雷
void check(char mine[ROWS][COLS], char show[ROWS][COLS],int row, int col)
{int x = 0;int y = 0;int win = 0;//只要不是雷就+1while(win<row*col-EASY)//当win等于除雷外所有的个数证明已经排完所有雷,跳出循环{ printf("请输入要排查的坐标");scanf("%d%d", &x, &y);if (show[x][y] != '*')//防止坐标重复使win加1{printf("该坐标被查过了");continue;}if (x >= 1 && x <= row && y >= 1 && y <= col)//由于传入的是11*11数组,我们要其中心的9*9数组进行操作,坐标(数组下标)必须在1~9范围上{if (mine[x][y] == '1'){printf("很遗憾,你被炸死了\n");//把雷的位置打出来给玩家看看display_board(mine, ROW, COL);break;}else{open(mine, show, x, y);//展开一片空白,我们在下面进行讲解display_board(show, ROW, COL);//打印玩家要玩的棋盘win++;}}else{printf("坐标非法,请重新输入\n");}}if (win == (row * col - EASY))//当win等于除雷外所有的个数证明已经排完所有雷,代表游戏胜利{printf("游戏获胜\n");//把所有雷的位置打印出来给玩家看display_board(mine, ROW, COL);}
}

6.由于排查雷的时候我们使用了open(mine, show, x, y)来展开一片空白,接下来我们对open函数进行实现

在text.c中的game函数中调用open函数

void game()
{//定义2个棋盘mine,showchar mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };//初始化//其中mine全部初始化为'0',有雷的地方定为'1',用0,1是为了方便统计周围雷的数量//show是用来给玩家来玩的,一开始全部初始化为'*'init_board(mine, ROWS, COLS,'0');init_board(show, ROWS, COLS,'*');//打印棋盘//display_board(mine, ROW, COL);display_board(show, ROW, COL);//设置雷setmine(mine, ROW, COL);//display_board(mine, ROW, COL);//排查雷check(mine,show, ROW, COL);//展开雷open(mine, show, ROW, COL);
}

然后在头文件game.h中我们声明open函数

//展开雷
void open(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

最后在game.c文件中实现open函数

//展开雷
void open(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{if (x >= 1 && x <= ROW && y >= 1 && y <= COL){int count = get_mine(mine, x, y);//统计一个格子周围雷的个数,并返回个数count//如果该格子周围雷的个数不为0,我们就把该格子周围雷的个数传到玩家玩的show棋盘对应的格子中,而如果是0,我们传入空格‘ ’ if (count != 0)show[x][y] = count + '0';//由于count返回的是整数,而存入数组中的是字符,我们需要加上‘0’,相当于加上ASCII值48else 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++){//利用递归反复进行,知道周围都有雷open(mine, show, i, j);}}}else{return ;}}
}

7.由于实现open展开函数的时候用到了统计雷个数函数get_mine,接下来我们需要在这之前实现get_mine(mine, x, y)

因为get_mine函数在open函数即统一文件中调用,我们不需要在头文件game.c中声明,直接在open函数之前实现即可

而实现get_mine函数又有两种方法如下

方法一

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';
}

方法二

int get_mine(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++){if (mine[i][j] == '1')count++;}}return count;}

我个人认为第二种方法更好

8.以上就实现了整个扫雷游戏

游戏效果如下



5.总的代码如下

text.c

#include "game.h"void menu()
{printf("**************************\n");printf("********* 1.play *********\n");printf("********* 0.exit *********\n");printf("**************************\n");
}void game()
{//定义2个棋盘mine,showchar mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };//初始化//其中mine全部初始化为'0',有雷的地方定为'1',用0,1是为了方便统计周围雷的数量//show是用来给玩家来玩的,一开始全部初始化为'*'init_board(mine, ROWS, COLS,'0');init_board(show, ROWS, COLS,'*');//打印棋盘//display_board(mine, ROW, COL);display_board(show, ROW, COL);//设置雷setmine(mine, ROW, COL);//display_board(mine, ROW, COL);//排查雷check(mine,show, ROW, COL);//展开雷open(mine, show, ROW, COL);
}void text()
{int input = 0;do{menu();printf("请选择是否进行游戏\n");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误,请重新选择\n");break;}} while (input);
}int main()
{srand((unsigned int)time(NULL));text();return 0;
}

game.h

#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 10//初始化棋盘
void init_board(char board[ROWS][COLS], int rows, int cols,int met);//打印棋盘
void display_board(char board[ROWS][COLS], int row, int col);//设置雷
void setmine(char mine[ROWS][COLS], int row, int col);//排查雷
void check(char mine[ROWS][COLS],char show[ROWS][COLS],int row, int col);//展开雷
void open(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

game.c

#include "game.h"void init_board(char board[ROWS][COLS], int rows, int cols,int met)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){board[i][j] = met;}}
}void display_board(char board[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;printf("--------- 扫雷 ---------\n");for (y = 0; y <= col; y++){printf("%d ", y);}printf("\n");for (x = 1; x <= row; x++){printf("%d ", x);for (y = 1; y <= col; y++){printf("%c ", board[x][y]);}printf("\n");}printf("--------- 扫雷 ---------\n");
}void setmine(char mine[ROWS][COLS], int row, int col)
{int count = EASY;int x = 0;int y = 0;while (count){x = rand() % row + 1;y = rand() % col + 1;if (mine[x][y] == '0'){mine[x][y] = '1';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';
//}//方法二
int get_mine(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++){if (mine[i][j] == '1')count++;}}return count;}//排查雷
void check(char mine[ROWS][COLS], char show[ROWS][COLS],int row, int col)
{int x = 0;int y = 0;int win = 0;while(win<row*col-EASY){ printf("请输入要排查的坐标");scanf("%d%d", &x, &y);if (show[x][y] != '*'){printf("该坐标被查过了");continue;}if (x >= 1 && x <= row && y >= 1 && y <= col){if (mine[x][y] == '1'){printf("很遗憾,你被炸死了\n");//把雷的位置打出来给玩家看看display_board(mine, ROW, COL);break;}else{open(mine, show, x, y);display_board(show, ROW, COL);win++;}}else{printf("坐标非法,请重新输入\n");}}if (win == (row * col - EASY)){printf("游戏获胜\n");display_board(mine, ROW, COL);}
}//展开雷
void open(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{if (x >= 1 && x <= ROW && y >= 1 && y <= COL){int count = get_mine(mine, x, y);if (count != 0)show[x][y] = count + '0';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++){open(mine, show, i, j);}}}else{return ;}}
}

四、总结

提示:这里对文章进行总结:
继三子棋后的扫雷,我会继续坚持的
有不对的请及时指正我!谢谢读者

此外

关于扫雷还可以进行的改进
比如:可以像游戏里的标记雷的位置,创造更难的棋盘等等

扫雷超详解(可展开一片空白)相关推荐

  1. Android vector标签 PathData 画图超详解

    此文章来源于https://www.cnblogs.com/yuhanghzsd/p/5466846.html点击打开链接 Android vector标签 PathData 画图超详解 SVG是一种 ...

  2. Mybatis案例超详解

    Mybatis案例超详解 前言: 本来是想像之前一样继续跟新Mybatis,但由于种种原因,迟迟没有更新,快开学了,学了一个暑假,博客也更新了不少,我觉得我得缓缓,先整合一些案例练练,等我再成熟点理解 ...

  3. python控制手机模拟器_Appium+python自动化之连接模拟器并启动淘宝APP(超详解)...

    简介 上一篇讲解完模拟器的安装.配置好以后,就好比我们手机已经买好,并且系统已经做好了,就差我们用数据线和电脑连接开始实战了,这篇宏哥就带着小伙伴们和童鞋们趁热打铁,讲解和分享一下如何连接模拟器(电脑 ...

  4. js打印三角形超详解

    js打印三角形超详解 j控制星星的总行数,i控制每行星星的打印个数 打印图形如下: (1) (2) //str=""用来存储星星// 理解步骤1:在一行输出6个星星如何操作,在循环 ...

  5. 线性规划之单纯形法【超详解+图解】-转载

    线性规划之单纯形法[超详解+图解] 目录 1.作用 2.线性规划的一般形式 5.1几何意义 5.2如何判断最优 5.3如何选择新的基变量 5.4如何选择被替换的基变量 5.5终止条件 标准型: 转化为 ...

  6. 【平衡小车制作】(七)串级PID调参及平衡成果展示(超详解)

      大家好,我是小政.本篇文章我将针对PID调参进行详细的讲解,让每位小伙伴能够对比例.积分.微分三个参数如何调节有更加清晰的理解. 一.调参步骤 确立机械中值 直立环(内环)--Kp极性.Kp大小. ...

  7. 蓝牙模块XY-MBD07A的介绍及使用方法(超详解)

    蓝牙模块XY-MBD07A的介绍及使用方法(超详解) 蓝牙XY-MBD07A是主从一体的蓝牙串口模块,简单的说,当蓝牙设备与蓝牙设备配对连接成功后,我们可以忽视蓝牙内部的通信协议,直接将将蓝牙当做串口 ...

  8. C/C++实现蛇形矩阵(超详解)【沈七】

    C/C++实现蛇形矩阵(超详解) 题目链接 题目描述 输入样例 题解部分 完整代码 完结散花 悄悄告诉你: 参考文章 萌新报道! 唤我沈七就行嘿嘿. 大一软件工程在读. 菜鸡蒟蒻想在博客中记录一些算法 ...

  9. [C++ 系列] 90. 超详解C++思维导图

    这段时间针对 C++ 的学习到了一个收尾的阶段.目前所涉及到了 C++ 基础语法.大小知识点的学习.当然语言学习绝对离不开实战项目的练手,网络优质资源以及各类经典丛书也是 C++ 学习的巨大宝库.在此 ...

最新文章

  1. vue实现文件上传功能
  2. 【CV】吴恩达机器学习课程笔记 | 第1-2章
  3. 洛谷乐多赛 yyy loves Maths VI (mode)
  4. linux shell概述,Linux学习 -- Shell基础 -- 概述
  5. Python 文件读取与写入操作方法
  6. 自动更新本地 GIT 仓库
  7. 今天女同事说月经不调:加班加的!我们为什么不敢闲?
  8. openStack Packages yum upgrade
  9. 转 .NET中的异步编程(四)- IO完成端口以及FileStream.BeginRead
  10. LS-DYNA基础理论
  11. MongoDB学习总结四(详细记录使用MongoTemplate操作MongoDB数据库)
  12. [归并排序]leetcode327:区间和的个数(hard)
  13. 扬子苦荞啤酒 一杯苦荞啤酒,精彩你的世界
  14. 形象理解线性代数(三)——列空间、零空间(核)、值域、特征值(特征向量)、矩阵与空间变换、矩阵的秩
  15. 低功耗蓝牙芯片发展方向
  16. 基于AltiumDesigner的PCB及原理图项目设计经验分享 [硬件开发设计]
  17. HTML 具体是用来做什么的?
  18. 大话数据结构之树(下)
  19. VScode报错:undefined reference to ‘WinMain’ collect2.exe: error: ld returned 1 exit status
  20. oh-my-zsh配置

热门文章

  1. 解决nrm ls命令没有*(星号)的问题
  2. CreateJS 指南
  3. LiteOS 消息队列
  4. Tita 绩效宝:经理一对一会议简介
  5. Mac系统如何查看更新R版本
  6. 一加手机android auto,一加手机怎么升级安卓5.0系统
  7. pr怎样进行素材嵌套
  8. android 常用框架整理
  9. 不是有效的win32应用程序_什么是模块,各种模块的有效行为(1)
  10. Mars 是什么、能做什么、如何做的——记 Mars 在 PyCon China 2018 上的分享...