用C语言实现扫雷

本篇适用于C语言初学者,主要涉及对于函数,数组,分支循环的运用。

目录

设计思想:

总代码(改进后):

运行结果展示:

分布介绍:

声明:

代码主体部分:

功能模块实现:

初始化模块:

打印模块:

埋雷模块:

判断模块:

总结:


设计思想:

首先要有一个游戏菜单,输入1表示开始,0表示结束,其它数字则提示输入错误,请重新输入;其次要有雷盘,雷盘用二维数组表示,开始时要有初始化模块对二维数组初始化,要有埋雷模块放置雷,要有判断输赢及返回结果模块,要有打印模块向玩家展示雷盘,为了更容易实现这些模块,我们选择两个二维数组表示雷盘,其中一个埋雷,其中一个向玩家展示。为了方便计算周围雷的个数,空用 '0' 表示,;雷用 '1'表示。

总代码(改进后):

#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_Mine 10void InitBorad(char borad[ROWS][COLS], int rows, int cols, char ch);
void DisplayBorad(char borad[ROWS][COLS], int row, int col);
void SetMine(char borad[ROWS][COLS], int row, int col);
void FindMine(char mine_borad[ROWS][COLS], char show_board[ROWS][COLS], int row, int col);//初始化
void InitBorad(char borad[ROWS][COLS], int rows, int cols, char ch)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){borad[i][j] = ch;}}
}//打印拓展
void DisplayBorad(char borad[ROWS][COLS], int row, int col)
{int i = 0;//列标for (i = 0; i <= col; i++){printf(" %d |", i);}printf("\n");for (i = 0; i <= col; i++){printf("---|", i);}printf("\n");for (i = 1; i <= row; i++){//行标printf(" %d |", i);int j = 0;for (j = 1; j <= col; j++){printf(" %c |",borad[i][j]);}printf("\n");for (j = 0; j <= col; j++){printf("---|", i);}printf("\n");}printf("\n");
}//放置雷
void SetMine(char borad[ROWS][COLS], int row, int col)
{int count = Easy_Mine;while (count){int x = rand() % row + 1;int y = rand() % col + 1;if (borad[x][y] == '0'){borad[x][y] = '1';count--;}}}//改进判断法//递归实现扫雷的展开一片
void GetMineCount(char mine_borad[ROWS][COLS], char show_borad[ROWS][COLS], int x, int y, int* count)
{if (x >= 1 && x <= ROW && y >= 1 && y <= COL && show_borad[x][y] == '*'){int i = x - 1;int j = y - 1;int sum = 0;//计算周围有几个雷for (i = x - 1; i <= x + 1; i++){for (j = y - 1; j <= y + 1; j++){sum = sum +(mine_borad[i][j] - '0');}}//如果周围没有雷,将此坐标置为空格,递归查找周围的周围是否有雷...if (sum == 0){show_borad[x][y] = ' ';for (i = x - 1; i <= x + 1; i++){for (j = y - 1; j <= y + 1; j++){//更正循环次数(*count)--;GetMineCount(mine_borad, show_borad, i, j, count);}}}//如果周围有雷,将此坐标字符该为对应雷的个数的字符else{//更正循环次数(*count)--;show_borad[x][y] = sum + '0';}}
}void FindMine(char mine_borad[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;int count = row * col - Easy_Mine;//实现主体while (count){printf("请输入坐标:>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (mine_borad[x][y] == '1'){printf("嘭!你被炸死了!\n");DisplayBorad(mine_borad, ROW, COL);break;}else if (mine_borad[x][y] == '0' && show_board[x][y] == '*');{GetMineCount(mine_borad, show_board, x, y, &count);//count = count_number(show_board, row, col);//DisplayBorad(mine_borad, ROW, COL);DisplayBorad(show_board, ROW, COL);}}else{printf("输入坐标非法,请重新输入!\n");}}if (count == 0){printf("恭喜你,你赢了!\n");DisplayBorad(mine_borad, row, col);}
}void menu()
{printf("******************************\n");printf("********   1.paly   **********\n");printf("********   0.exit   **********\n");printf("******************************\n");
}void game()
{//此二维数组用来放置雷char mine[ROWS][COLS] = { 0 };//此二维数组用于像玩家展示char show[ROWS][COLS] = { 0 };//初始化两个二维数组InitBorad(mine, ROWS, COLS, '0');//DisplayBorad(mine, ROW, COL);InitBorad(show, ROWS, COLS, '*');//放置雷SetMine(mine, ROW, COL);//打印棋盘DisplayBorad(show, ROW, COL);//DisplayBorad(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;
}

运行结果展示:

 

 

 

分布介绍:

声明:

如果想要更改雷盘大小,放置雷个数,只需对ROW , COL , Easy_Mine作相应的修改即可。 

#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_Mine 10
//主要函数声明
void InitBorad(char borad[ROWS][COLS], int rows, int cols, char ch);
void DisplayBorad(char borad[ROWS][COLS], int row, int col);
void SetMine(char borad[ROWS][COLS], int row, int col);
void FindMine(char mine_borad[ROWS][COLS], char show_board[ROWS][COLS], int row, int col);

代码主体部分:

关于作为9 * 9的雷盘为什么要选择11 * 11的二维数组表示,是为了防止越界访问,以及更容易地实现扫雷后的判断和返回结果。用字符0将要放置雷的二维数组初始化,用字符*将向玩家展示的二维数组初始化,用字符1表示雷。

//游戏菜单
void menu()
{printf("******************************\n");printf("********   1.paly   **********\n");printf("********   0.exit   **********\n");printf("******************************\n");
}
//实现主体
void game()
{//此二维数组用来放置雷char mine[ROWS][COLS] = { 0 };//此二维数组用于像玩家展示char show[ROWS][COLS] = { 0 };//初始化两个二维数组InitBorad(mine, ROWS, COLS, '0');//DisplayBorad(mine, ROW, COL);InitBorad(show, ROWS, COLS, '*');//放置雷SetMine(mine, ROW, COL);//打印棋盘DisplayBorad(show, ROW, COL);//DisplayBorad(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;
}

功能模块实现:

初始化模块:

通过嵌套for循环用传过来的字符将传过来的数组初始化。

//初始化
void InitBorad(char borad[ROWS][COLS], int rows, int cols, char ch)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){borad[i][j] = ch;}}
}

打印模块:

原始打印模块:

先利用for循环打印列标,再利用嵌套for循环打印行标及二维数组。代码及雷盘展示如下:

//打印
void DisplayBorad(char borad[ROWS][COLS], int row, int col)
{int i = 0;//列标for (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 ", borad[i][j]);}printf("\n");}printf("\n");
}

雷盘:

改进打印模块:

原理如上,加以修饰,代码及雷盘展示如下:

//打印拓展
void DisplayBorad(char borad[ROWS][COLS], int row, int col)
{int i = 0;//列标for (i = 0; i <= col; i++){printf(" %d |", i);}printf("\n");for (i = 0; i <= col; i++){printf("---|", i);}printf("\n");for (i = 1; i <= row; i++){//行标printf(" %d |", i);int j = 0;for (j = 1; j <= col; j++){printf(" %c |",borad[i][j]);}printf("\n");for (j = 0; j <= col; j++){printf("---|", i);}printf("\n");}printf("\n");
}

 雷盘:

埋雷模块:

要实现在雷盘上随机放置雷,需要srand()和time()库函数来确定随机数生成期起点,rand()库函数来生成随机数,将获得的随机数大小控制在1~9之间(雷盘逻辑大小),获得要放置雷的坐标后,找到与之对应的二维数组元素,将其置为字符1。(字符0表示不是雷,字符1表示雷)模块代码及放置雷的二维数组展示:

//放置雷
void SetMine(char borad[ROWS][COLS], int row, int col)
{//要放置的雷的个数int count = Easy_Mine;while (count){//获得要放置雷的坐标int x = rand() % row + 1;int y = rand() % col + 1;//如果此坐标未放置雷,则放置雷,否则重新获得坐标if (borad[x][y] == '0'){borad[x][y] = '1';count--;}}
}

放置雷的二维数组:

判断模块:

原始判断模块;

此模块需要将真雷盘和假雷盘二维数组都传过去。玩家输入要扫雷的坐标,如果坐标不合法,提示输入错误,重新输入。如果坐标合法,与放置雷的二维数组的相应坐标对照,如果此坐标是雷,则输出玩家扫雷失败,并将埋雷的二维数组向玩家展示,游戏结束,如果此坐标不是雷,则判断此坐标周围一圈有无雷,如果无雷,返回0,有雷的话,返回雷的个数,并将向玩家展示的二维数组的对应的坐标更改为雷的个数,更正循环控制条件,继续游戏。当循环控制条件不再满足(及已将所有不是雷的坐标扫出)则获得游戏胜利,游戏结束。

//原始判断法//返回此坐标周围雷的个数
int GetMineCount(char borad[ROWS][COLS], int x, int y)
{//字符1~9减去一个字符0就可以得到整型数1~9,这也是选择用字符0和1表示是否有雷的原因return (borad[x - 1][y] + borad[x - 1][y - 1] + borad[x][y - 1] + borad[x + 1][y - 1]+ borad[x + 1][y] + borad[x + 1][y + 1] + borad[x][y + 1] + borad[x - 1][y + 1] - 8 * '0');
}//判断输赢
void FindMine(char mine_borad[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;//循环控制条件int count = row * col - Easy_Mine;while (count){printf("请输入坐标:>");scanf("%d %d", &x, &y);//判断输入坐标是否合法if (x >= 1 && x <= row && y >= 1 && y <= col){//此坐标是雷if (mine_borad[x][y] == '1'){printf("嘭!你被炸死了!\n");//打印放置雷的二维数组DisplayBorad(mine_borad, ROW, COL);break;}//此坐标不是雷else if (mine_borad[x][y] == '0' && show_board[x][y] != ' ');{//函数调用返回雷的个数int ret = GetMineCount(mine_borad, x, y);//将向玩家展示的二维数组的对应坐标更改为雷的个数(将整型数1~9加一个字符0就可转换成字符1~9)show_board[x][y] = ret + '0';//打印DisplayBorad(show_board, ROW, COL);//更正循环控制条件count--;}}else{printf("输入坐标非法,请重新输入!\n");}}//游戏胜利判定if (count == 0){printf("恭喜你,你赢了!\n");DisplayBorad(mine_borad, row, col);}
}

运行展示:

改进判断模块: 

上述判断模块跟扫雷游戏还是有些实质差异,在扫雷游戏中,当一个坐标周围一圈都没有雷时,就会为空,再对他周围的坐标的周围进行判断......因此需要对其进行改进,总体思想不变,仅需对判断坐标周围一圈雷数的子模块以及循环控制条件进行修改即可。当输入坐标周围一圈都没有雷时,将向玩家展示的二维数组的对应坐标置为空格,更改循环控制条件,并判断它周围坐标的周围是否有雷.....依此类推。这里通过循环和递归思想实现此功能。

//改进判断法//递归实现扫雷的展开一片
void GetMineCount(char mine_borad[ROWS][COLS], char show_borad[ROWS][COLS], int x, int y, int* count)
{//递归限制条件 if (x >= 1 && x <= ROW && y >= 1 && y <= COL && show_borad[x][y] == '*'){int i = x - 1;int j = y - 1;//此变量表示雷的个数 int sum = 0;//计算周围有几个雷for (i = x - 1; i <= x + 1; i++){for (j = y - 1; j <= y + 1; j++){sum = sum +(mine_borad[i][j] - '0');}}//如果周围没有雷,将此坐标置为空格,递归查找周围的周围是否有雷...if (sum == 0){show_borad[x][y] = ' ';for (i = x - 1; i <= x + 1; i++){for (j = y - 1; j <= y + 1; j++){//更正循环次数(*count)--;//递归 GetMineCount(mine_borad, show_borad, i, j, count);}}}//如果周围有雷,将此坐标字符改为对应雷的个数的字符else{//更正循环次数(*count)--;show_borad[x][y] = sum + '0';}}
}void FindMine(char mine_borad[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;int count = row * col - Easy_Mine;//实现主体while (count){printf("请输入坐标:>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (mine_borad[x][y] == '1'){printf("嘭!你被炸死了!\n");DisplayBorad(mine_borad, ROW, COL);break;}else if (mine_borad[x][y] == '0' && show_board[x][y] == '*');{GetMineCount(mine_borad, show_board, x, y, &count);//count = count_number(show_board, row, col);//DisplayBorad(mine_borad, ROW, COL);DisplayBorad(show_board, ROW, COL);}}else{printf("输入坐标非法,请重新输入!\n");}}if (count == 0){printf("恭喜你,你赢了!\n");DisplayBorad(mine_borad, row, col);}
}

运行展示:

 

 

总结:

关于扫雷游戏的基本模块已经实现,可以开始游戏啦!当然,这个简易扫雷游戏还是可以继续优化的,比如增加标记功能等,这些模块的实现就需要大家自行去探索了,我就不过多阐述了。本期内容就到这里,如果帮到你的话,还请给个一键三连吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/17901.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3学习使用axios和qs进行POST请求和响应处理

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、前言1.准备工作2.发送POST请求3.处理响应数据4.总结 一、前言 在前端开发中&#xff0c;经常需要与后端进行数据交互&#xff0c;其中包括发送POST请求并处理响…

HarmonyOS 鸿蒙应用开发 - 创建自定义组件

开发者定义的称为自定义组件。在进行 UI 界面开发时&#xff0c;通常不是简单的将系统组件进行组合使用&#xff0c;而是需要考虑代码可复用性、业务逻辑与UI分离&#xff0c;后续版本演进等因素。因此&#xff0c;将UI和部分业务逻辑封装成自定义组件是不可或缺的能力。 1、创…

快团团帮卖团长怎么对供货大团长进行评分?

都说帮卖“躺赚”&#xff1f; 一旦遇团不淑&#xff0c;惨遭不靠谱团长挖坑&#xff0c;售后拖延、发货慢、产品瑕疵…… 加上顾客夺命连环催&#xff0c;双面夹击&#xff0c;夹缝生存。供货团长靠不靠谱太重要了&#xff01; 快团团供货团长评分系统上线&#xff01; 帮卖团…

ECOLOGY9解决明细表数据按需显示或隐藏

ECOLOGY9:由于领导需要查看完整的明细表数据&#xff0c;没有启用分页功能&#xff0c;导致大领导查看时又出现几百行的数据&#xff0c;影响使用体验。需求&#xff1a;只看正常表单数据&#xff0c;明细表数据&#xff0c;默认不显示&#xff0c;需要查看时再打开。 实现&am…

【RK3288 Android10 T8pro usb hid-multitouch idc配置】

【RK3288 Android10 T8pro usb hid-multitouch idc配置】 文章目录 【RK3288 Android10 T8pro usb hid-multitouch idc配置】背景代码分析1. 读取配置文件2. 标志内外置屏幕3. 设置输入设备4. findviewport()5. 根据对应的viewport来计算相应的mapping的参数 结论 背景 T8pro …

二十三篇:未来数据库革新:AI与云原生的融合之旅

未来数据库革新&#xff1a;AI与云原生的融合之旅 1. 智能数据库管理&#xff1a;AI的魔法 在数字化时代&#xff0c;数据库技术作为信息管理的核心&#xff0c;正经历着前所未有的变革。AI&#xff08;人工智能&#xff09;和云原生技术的融合&#xff0c;正在重新定义数据库…

关于k8s集群的污点和容忍,以及k8s集群的故障排查思路

一 污点(Taint) 和 容忍(Tolerations) &#xff08;一&#xff09;污点 在Kubernetes&#xff08;K8s&#xff09;中&#xff0c;污点&#xff08;Taints&#xff09;是一个重要的概念&#xff0c;用于实现Pod的调度控制。以下是关于污点的详细解释&#xff1a;1.污点定义 污点…

元宇宙vr科普馆场景制作引领行业潮流

在这个数字化高速发展的时代&#xff0c;北京3D元宇宙场景在线制作以其独特的优势&#xff0c;成为了行业内的创新引领者。它能够快速完成空间设计&#xff0c;根据您的个性化需求&#xff0c;轻松设置布局、灯光、音效以及互动元素等&#xff0c;为您打造出一个更加真实、丰富…

【算法】位运算算法——判断字符是否唯一

题解&#xff1a;判断字符是否唯一(位运算算法) 目录 1.题目2.题解3.位图参考代码4.细节5.总结 1.题目 题目链接&#xff1a;LINK 2.题解 题解有两种方法&#xff0c; 一是做一个哈希数组&#xff0c;去查重&#xff1b; 二是直接用一个变量每一位来对应表示是否有这个字母…

Android - failed to set system property

记录一次疏忽&#xff0c;起因是我需要在自定义的 receiver 中保存 property 方便&#xff0c;方便在三方 app 中使用&#xff0c;结果直接崩溃了&#xff0c;虽然结果保存成功了&#xff0c;但是这种情况也是无法接收的&#xff0c;错误日志如下&#xff1a; M006082 05-25 1…

场景题11111

关单操作&#xff1f; 优先考虑定时任务、Redissonredis、RocketMQ延迟消息实现&#xff08;订单量特别大的时候&#xff0c;不建议使用MQ&#xff09; 每个订单都有一个消息会增加资源消耗可靠性问题&#xff08;丢失&#xff09;大量的无效消息不是所有消息队列都支持一般通…

PID控制中的积分到底是什么,为什么它可以将矩形线转换为曲线?simulink搭建PID控制,积分模块1/s

PID控制中的积分到底是什么&#xff0c;为什么它可以将矩形线转换为曲线&#xff0c; 这个问题呢其实道理很简单&#xff0c;用到的是初中的知识 我们做几个测试案例 如下面matlab搭建了积分1/s 那显示如下&#xff08;红色曲线相当于加速度、蓝色曲线相当于速度&#xff09;&a…

5.28_Java语法_运算符,接收键盘数据

1、运算符 具体应用同我C语言操作符详解博客相同,另有补充会直接写 1.1、基本的算术运算符、符号做连接符 CSDN 具体应用同我C语言操作符详解博客相同 符号做连接符&#xff1a; ""符号与字符串运算连用的时候是用作连接符的&#xff0c;其结果依然是一个字符串…

前端响应式期末作品

网页设计成品_前端响应式 主题&#xff1a;租房网站&#xff0c;共6个html页面&#xff0c;包含首页&#xff0c;登录注册&#xff0c;租房新闻&#xff0c;租房精选&#xff0c;租房详情&#xff0c;数据可视化页面&#xff08;可以修改内容&#xff09; 采用技术&#xff1a;…

启动ChatGPT 的快捷键,探索全新 ChatGPT MacOS 应用程序!

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

深度解析Java 11核心新特性

码到三十五 &#xff1a; 个人主页 < 免责声明 > 避免对文章进行过度解读&#xff0c;因为每个人的知识结构和认知背景都不同&#xff0c;没有一种通用的解决方案。对于文章观点&#xff0c;不必急于评判。融入其中&#xff0c;审视自我&#xff0c;尝试从旁观者角度认清…

软考结束。有什么要说的

1. 竟然是机试&#xff0c;出乎我意料。是 考试机构觉得笔试成本高了么。这次的考试是机试&#xff0c;相比以往有所不一样。感言是不是以后都会在固定地点考试也说不准。 2. 遇到年轻人。 这次旁边的一个女同学第一次参加&#xff0c;还像我询问了一些关于软考的事。我是有…

关于学习Go语言的并发编程

开始之前&#xff0c;介绍一下​最近很火的开源技术&#xff0c;低代码。 作为一种软件开发技术逐渐进入了人们的视角里&#xff0c;它利用自身独特的优势占领市场一角——让使用者可以通过可视化的方式&#xff0c;以更少的编码&#xff0c;更快速地构建和交付应用软件&#…

【数据结构】直接选择排序详解!

文章目录 1.直接选择排序 1.直接选择排序 &#x1f427; begin 有可能就是 maxi &#xff0c;所以交换的时候&#xff0c;要及时更新 maxi &#x1f34e; 直接选择排序是不稳定的&#xff0c;例如&#xff1a; 9 [9] 5 [5]&#xff0c;排序后&#xff0c;因为直接选择排序是会…

Debug-012-el-popover 使用 doClose() 关闭窗口不生效的处理方案

前言&#xff1a; 今天上午碰见一个非常奇怪的情况&#xff1a;一样的方法实现的功能&#xff0c;效果却不一样。 两个页面都是使用的doClose()去关闭的el-popover&#xff0c;其中有一个就是不生效&#xff0c;找不同找了半天&#xff0c;始终不得其解。请看效果吧&#xff1…