【C语言】扫雷游戏(可展开)——超细教学
🚩纸上得来终觉浅, 绝知此事要躬行。
🌟主页:June-Frost
🚀专栏:C语言
🔥该篇将运用数组来实现 扫雷游戏。
目录:
- 🌟思路框架
- 测试
- 游戏
- 🌟测试部分函数实现
- 🌟 游戏部分函数实现
- 🌟完整的代码
- ❤️ 结语
🌟思路框架
测试
通过迭代保证每次玩完游戏后可以再来一局或者退出。
游戏
说明:
1 . 实现扫雷,首先需要布置雷,通过一个二维数组就可以很容易的将雷的信息存储下来。只需要将二维数组的元素赋予两个不同的值,例如,’1’ ——雷,’0‘ ——无雷,或者 ‘#’ ——雷,’ * ’ ——无雷,只不过这两种在后续排查雷中操作不同(通过一个循环前者可以加起来计算出周围有几个雷,后者可以通过比较来判定有多少雷)。
如上图,对于 排查雷(周围有多少雷),如果只有一个数组,那么在周围如果只有一个雷的情况下(’1‘——表示雷,’0‘——表示无雷),该位置的数组元素就会被赋值为1,在最后展示棋盘的时候,这个1就会造成歧义,就会不知道这个’1‘究竟是雷,还是周围雷的个数。
所以,通过建立另一个数组,来记录周围雷的数量。
如图:
3.
但是我们可以将其逻辑统一:
- 为了简便操作,我们将两个数组规定为同类型,同大小(两个都扩充一圈)。
- 优点1:可以方便数组操作,下标一样,不需要重新计算对应数组元素的下标。
- 优点2:同类型意味着可以使用同一个函数,不需要一个功能写两次。
每个部分都是单独的函数体,下面将会单独对每个函数体进行实现。
🌟测试部分函数实现
- 选择是否玩游戏
与三子棋一样,该板块的循环部分将会使用do while 循环来实现(保证一开始可以选择,运行完游戏部分后还可以继续选择)。
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"int main()
{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()函数中。
前提:
#define ROW 9
#define COL 9#define ROWS ROW+2
#define COLS COL+2
定义两种,可以在后续分别用于不同的函数。
- 游戏逻辑
void game()
{char mine[ROWS][COLS] = { 0 };//存放雷char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息//初始化InitBoard(mine, ROWS, COLS, '0');//都先初始化为无雷InitBoard(show, ROWS, COLS, '*');//布置雷SetMine(mine, ROW, COL);//打印第二个棋盘DisplayBoard(show, ROW, COL);//排查雷FineMine(mine, show, ROW, COL);
}
- 初始化
由于想使用一个函数就可以将两个棋盘初始化,所以在参数上需要增加一个变量用于接收初始化的值。
void InitBoard(char board[ROWS][COLS], int row, int col, char set)
{int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){board[i][j] = set;}}
}
- 布置雷
前提:#define Set_Mine 10;//需要布置雷的数量
布置雷是随机的,所以我们采用伪随机数,将下标在合法范围内随机,如果该坐标下是无雷的,就赋值‘1’,定为有雷。
void SetMine(char board[ROWS][COLS], int row, int col)
{int count = Set_Mine;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] == '0'){board[x][y] = '1';count--;//布置成功,雷数减少1}}}
}
- 打印棋盘
为了方便玩家定位坐标,在打印棋盘的时候,可以将行和列打印出来。并且展示出来的,是中间的区域(不展示扩容区域)
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{printf("--------扫雷游戏-------\n");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 ", board[i][j]);}printf("\n");}
}
- 排查雷
计数:
int GetMineCount(char board[ROWS][COLS], int x, int y)
{int i = x - 1;int j = y - 1;int ret = 0;for (i = x - 1; i <= x + 1; i++){for (j = y - 1; j <= y + 1; j++){ret += board[i][j];}}return ret - 9 * '0';
}
排雷:
void FineMine(char mine[ROWS][COLS], char show[ROWS][COLS],int row,int col)
{int win = 0;//如果要赢 需要的有检查的次数,例如:9*9棋盘,有10个雷,检查出71个地区不是雷,就意味着获胜。while (win<ROW*COL-Set_Mine){int x = 0;int y = 0;printf("请输入坐标,中间用空格:> ");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col)//判断坐标合法{//踩到雷if (mine[x][y] == '1'){printf("很遗憾,已踩到雷\n");DisplayBoard(mine, ROW, COL);break;}//没猜到雷else{Unfold(mine,show, ROW, COL, x, y,&win);//递归展开DisplayBoard(show, ROW, COL);//展示棋盘}}else{printf("输入非法,需要重新输入\n");}}if (win == ROW * COL - Set_Mine){printf("游戏获胜\n");DisplayBoard(mine, ROW, COL);}
}
展开:
如何实现上面的展开效果呢?
当我们点击一个坐标后,看是否满足3个条件:
1.这个坐标不是雷(如果按照博主的排雷逻辑,这个条件不需要判断,因为坐标下不是雷的时候才会调用展开函数)
2.周围没有雷
3.没有被递归过(防止死递归)
这时被点击的地方就可以被赋值为空,并对周围的8个区块看是否符合这样的条件,8个区块也按照这个逻辑,如果满足三个条件,被赋空并且遍历周围,如果不满足就显示周围有多少雷,或者不做任何反应,按照这样的逻辑一直延续下去。这种情况我们可以使用递归去解决。
void Unfold(char mine[ROWS][COLS], char show[ROWS][COLS],int row,int col,int x,int y, int* count_w)
{if (x >= 1 && x <= row && y >= 1 && y <= col)//判断合法{if (!GetMineCount(mine, x, y) && show[x][y] != ' ')//周围没有雷并且该位置没有被递归过{show[x][y] = ' ';int i = 0;int j =0;int ret = 0;//直接遍历9个,至于中间的那个坐标,最后一个else if 会处理for (i = x - 1; i <= x + 1; i++){for (j = y - 1; j <= y + 1; j++){Unfold(mine, show, row,col,i, j, count_w);(* count_w)++;}}}else if (GetMineCount(mine, x, y))//周围有雷{int count = GetMineCount(mine, x, y);show[x][y] = count + '0';(* count_w)++;}else if (show[x][y] == ' ')//被递归过{;//不需要操作}}//不合法的函数不需要任何处理
}
这里需要判断合法性,因为扩容出去的那一圈的元素不可以递归,而且也不可以计算 (不然按照GetMineCount的逻辑会越界访问,而且就会可以计算出,也不会打印这个区域,所以可以直接不用管,递归这些地方的时候,函数会什么都不处理)。
🌟完整的代码
game .h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>#define ROW 9
#define COL 9#define ROWS ROW+2
#define COLS COL+2#define Set_Mine 10//需要布置雷的数量
//游戏逻辑
void game();
//初始化
void InitBoard(char board[ROWS][COLS], int row, int col, char set);
//埋雷
void SetMine(char board[ROWS][COLS], int row, int col);
//展示棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//排雷
void FineMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game .c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//菜单
void menu()
{printf("***********************\n");printf("***** 1. play *****\n");printf("***** 0. exit *****\n");printf("***********************\n");
}//初始化
void InitBoard(char board[ROWS][COLS], int row, int col, char set)
{int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){board[i][j] = set;}}
}
//布置雷
void SetMine(char board[ROWS][COLS], int row, int col)
{int count = Set_Mine;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] == '0'){board[x][y] = '1';count--;//布置成功,雷数减少1}}}
}
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{printf("--------扫雷游戏-------\n");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 ", board[i][j]);}printf("\n");}
}
//计数
int GetMineCount(char board[ROWS][COLS], int x, int y)
{int i = x - 1;int j = y - 1;int ret = 0;for (i = x - 1; i <= x + 1; i++){for (j = y - 1; j <= y + 1; j++){ret += board[i][j];}}return ret - 9 * '0';
}//展开
void Unfold(char mine[ROWS][COLS], char show[ROWS][COLS],int row,int col,int x,int y, int* count_w)
{if (x >= 1 && x <= row && y >= 1 && y <= col){if (!GetMineCount(mine, x, y) && show[x][y] != ' ')//周围没有雷并且该位置没有被递归过{show[x][y] = ' ';int i = 0;int j =0;int ret = 0;for (i = x - 1; i <= x + 1; i++){for (j = y - 1; j <= y + 1; j++){Unfold(mine, show, row,col,i, j, count_w);(* count_w)++;}}}else if (GetMineCount(mine, x, y))//周围有雷{int count = GetMineCount(mine, x, y);show[x][y] = count + '0';(* count_w)++;}else if (show[x][y] == ' ')//被递归过{;}}
}
//排雷
void FineMine(char mine[ROWS][COLS], char show[ROWS][COLS],int row,int col)
{int win = 0;while (win<ROW*COL-Set_Mine){int x = 0;int y = 0;printf("请输入坐标,中间用空格:> ");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){//踩到雷if (mine[x][y] == '1'){printf("很遗憾,已踩到雷\n");DisplayBoard(mine, ROW, COL);break;}//没猜到雷else{Unfold(mine,show, ROW, COL, x, y,&win);//递归展开DisplayBoard(show, ROW, COL);//展示棋盘}}else{printf("输入非法,需要重新输入\n");}}if (win == ROW * COL - Set_Mine){printf("游戏获胜\n");DisplayBoard(mine, ROW, COL);}
}//游戏逻辑
void game()
{char mine[ROWS][COLS] = { 0 };//存放雷char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息//初始化InitBoard(mine, ROWS, COLS, '0');//都先初始化为无雷InitBoard(show, ROWS, COLS, '*');//布置雷SetMine(mine, ROW, COL);//打印第二个棋盘DisplayBoard(show, ROW, COL);DisplayBoard(mine, ROW, COL);//排查雷FineMine(mine, show, ROW, COL);
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"int main()
{int input = 0;srand((unsigned)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;
}
❤️ 结语
文章到这里就结束了,如果对你有帮助,你的点赞将会是我的最大动力,如果大家有什么问题或者不同的见解,欢迎大家的留言~
相关文章:
【C语言】扫雷游戏(可展开)——超细教学
🚩纸上得来终觉浅, 绝知此事要躬行。 🌟主页:June-Frost 🚀专栏:C语言 🔥该篇将运用数组来实现 扫雷游戏。 目录: 🌟思路框架测试游戏 🌟测试部分函数实现&am…...
数据的深海潜行:数据湖、数据仓库与数据湖库之间的微妙关系
导言:数据的重要性与存储挑战 在这个信息爆炸的时代,数据已经成为企业的核心资产,而如何高效、安全、便捷地存储这些数据,更是每个组织面临的重大挑战。 数据作为组织的核心资产 数据在过去的几十年里从一个辅助工具演变成企业的…...
Docker 安装 Redis集群
1. 面试题 1.1 1~2亿条数据需要缓存,请问如何设计这个存储案例 单机单台不可能实现,肯定是用分布式存储,用redis如何落地? 1.2 上述问题工程案例场景设计类题目,解决方案 1.2.1 哈希取余分区 2亿条记录就是2亿个k,v&…...
数据结构入门 — 链表详解_单链表
前言 数据结构入门 — 单链表详解* 博客主页链接:https://blog.csdn.net/m0_74014525 关注博主,后期持续更新系列文章 文章末尾有源码 *****感谢观看,希望对你有所帮助***** 系列文章 第一篇:数据结构入门 — 链表详解_单链表 第…...
从零学算法151
151.给你一个字符串 s ,请你反转字符串中 单词 的顺序。 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。 返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。 注意:输入字符串 s中可能会存在前导空格、尾随…...
【Vue】动态设置元素类以及样式
Vue2 动态设置元素类以及样式 1.动态设置类 class 1.1 字符串语法 通过v-bind绑定元素的class属性,为其指定一个字符串: <div v-bind:class"className">class动态绑定</div> <script> export default {data() {return {…...
node和前端项目宝塔部署
首先需要一台服务器 购买渠道:阿里云、腾讯云、百度云、华为云 一、以阿里云为例 购买esc 可临时购买测试服务器 二、安装宝塔 复制公网ip地址 通过Xshell 进行账号密码的连接 连接后访问宝塔官网 宝塔面板下载,免费全能的服务器运维软件 找到自己…...
【Python原创毕设|课设】基于Python Flask的上海美食信息与可视化宣传网站项目-文末附下载方式以及往届优秀论文,原创项目其他均为抄袭
基于Python Flask的上海美食信息与可视化宣传网站(获取方式访问文末官网) 一、项目简介二、开发环境三、项目技术四、功能结构五、运行截图六、功能实现七、数据库设计八、源码获取 一、项目简介 随着大数据和人工智能技术的迅速发展,我们设…...
【HTML】HTML面试知识梳理
目录 DOCTYPE(文章类型)head标签浏览器乱码的原因及解决常用的meta标签与SEOscript标签中defer和async的区别src&href区别HTML5有哪些更新语义化标签媒体标签表单进度条、度量器DOM查询Web存储Canvas和SVG拖放 (HTML5 drag API࿰…...
Java进阶篇--IO流的第二篇《多样的流》
目录 Java缓冲流 BufferedReader和BufferedWriter类 Java随机流 Java数组流 字节数组流 ByteArrayInputStream流的构造方法: ByteArrayOutputStream流的构造方法: 字符数组流 Java数据流 Java对象流 Java序列化与对象克隆 扩展小知识&#x…...
iPhone 14 Pro 动态岛的功能和使用方法详解
当iPhone 14 Pro机型发布时,苹果公司将软件功能与屏幕顶部的药丸状切口创新集成,称之为“灵动岛”,这让许多人感到惊讶。这篇文章解释了它的功能、工作原理,以及你如何与它互动以执行动作。 一、什么是灵动岛?它是如何工作的 在谣言周期的早期iPhone 14 Pro 在宣布时…...
掌握这20条你将超过90%的测试员
1、不断学习 不管是“软技能”,比如公开演讲, 或者编程语言,亦或新的测试技术,成功的软件测试工程师总是会从繁忙中抽出时间来坚持学习。 2、管理你的时间 我们的时间很容易被大块的工作和不断的会议所占据,导致我们…...
LightDB create table时列约束支持enable/disable关键字
功能介绍 为了方便用户从Oracle数据库迁移到LightDB数据库,LightDB从23.3版本开始支持 create table时列约束支持enable/disable关键字。这个功能仅是语法糖。 使用说明 执行create table时,列约束后面可以选择性添加enable/disable关键字。 create …...
使用BeeWare实现iOS调用Python
1、准备工作 1.1、安装Python 1.2、设置虚拟环境 我们现在将创建一个虚拟环境——一个“沙盒”,如果我们将软件包安装到虚拟环境中,我们计算机上的任何其他Python项目将不会受到影响。如果我们把虚拟环境搞得一团糟,我们将能够简单地删除它…...
无公网IP内网穿透使用vscode配置SSH远程ubuntu随时随地开发写代码
文章目录 前言1、安装OpenSSH2、vscode配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网地址远程 前言 远程…...
二叉树、红黑树、B树、B+树
二叉树 一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成。 二叉树的特点: 每个结点最多有两棵子树,即二叉树不存在度大于2的结点。二叉树的子树有左右之分…...
12,【设计模式】工厂
设计模式工厂 通过工程来构建任意参数对象&&std::forwardstd::move 在C中,“工厂”(Factory)是一种设计模式,它提供了一种创建对象的方式,将对象的创建和使用代码分离开来,提高了代码的可扩展性和可…...
mysql 8.0 窗口函数 之 分布函数 与 sql server (2017以后支持) 分布函数 一样
mysql 分布函数 percent_rank() :等级值 百分比cume_dist() :累积分布值 percent_rank() 计算方式 (rank-1)/(rows-1), 其中 rank 的值为使用RANK()函数产生的序号,rows 的值为当前…...
Python Opencv实践 - 图像直方图自适应均衡化
import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/cat.jpg", cv.IMREAD_GRAYSCALE) print(img.shape)#整幅图像做普通的直方图均衡化 img_hist_equalized cv.equalizeHist(img)#图像直方图自适应均衡化 #1. 创…...
Linux编程:在程序中异步的调用其他程序
Linux编程:execv在程序中同步调用其他程序_风静如云的博客-CSDN博客 介绍了同步的调用其他程序的方法。 有的时候我们需要异步的调用其他程序,也就是不用等待其他程序的执行结果,尤其是如果其他程序是作为守护进程运行的,也无法等待其运行的结果。 //ssss程序 #include …...
04有监督算法——支持向量机
1.支持向量机 1.1 定义 支持向量机( Support Vector Machine )要解决的问题 什么样的法策边界才是最好的呢? 特征数据本身如果就很难分,怎么办呢? 计算复杂度怎么样?能实际应用吗? 支持向量机( Support Vector Machine , SVM)是一类按监督学习( s…...
macos 使用vscode 开发python 爬虫(安装一)
使用VS Code进行Python爬虫开发是一种常见的选择,下面是一些步骤和建议: 安装VS Code:首先,确保你已经在你的macOS上安装了VS Code。你可以从官方网站(https://code.visualstudio.com/)下载并安装最新版本…...
专有网络VPC私网/公网类产品选择
私网类产品选择 VPC互连:云企业网,对等连接 VPC与本地IDC互连:VPN网关,高速通道,云企业网,智能接入网关 VPC与多站点连接:VPN网关,智能接入网关,VPN网关高速通道 远程接…...
Connect-The-Dots靶场
靶场下载 https://www.vulnhub.com/entry/connect-the-dots-1,384/ 一、信息收集 探测存活主机 netdiscover -r 192.168.16.161/24nmap -sP 192.168.16.161/24端口操作系统扫描 nmap -sV -sC -A -p 1-65535 192.168.16.159扫描发现开放端口有 21 ftp 80 http 20…...
Linux解决RocketMQ中NameServer启动问题
启动步骤可以查看官网,https://github.com/apache/rocketmq 一下说明遇到的问题。 1:ROCKETMQ_HOME问题 根据官网提示进入mq/bin目录下,可以使用./mqnamesrv进行NameServer启动,但是会遇到第一个问题,首次下载Rocket…...
js逆向实战之某书protobuf反序列化
什么是Protobuf? \qquad Protobuf(Protocol Buffer)是 Google 开发的一套数据存储传输协议,作用就是将数据进行序列化后再传输,Protobuf 编码是二进制的,它不是可读的,也不容易手动修改…...
cpolar+JuiceSSH实现手机端远程连接Linux服务器
文章目录 1. Linux安装cpolar2. 创建公网SSH连接地址3. JuiceSSH公网远程连接4. 固定连接SSH公网地址5. SSH固定地址连接测试 处于内网的虚拟机如何被外网访问呢?如何手机就能访问虚拟机呢? cpolarJuiceSSH 实现手机端远程连接Linux虚拟机(内网穿透,手机端连接Linux虚拟机) …...
[MyBatis系列②]Dao层开发的两种方式
目录 1、传统开发 1.1、代码 1.2、存在的问题 2、代理开发 2.1、开发规范 2.2、代码 ⭐mybatis系列①:增删改查 1、传统开发 传统的mybatis开发中,是在数据访问层实现相应的接口,在实现类中用"命名空间.id"的形式找到对应的映…...
言语理解-中心理解之主题词及行文脉络
例题 例题 例题 例题 例题 例题...
LeetCode 面试题 01.05. 一次编辑
文章目录 一、题目二、C# 题解法一:从第一个不同位置处判断后续相同子串法二:前后序遍历判断第一个不同字符的位置关系 优化法一法二 一、题目 字符串有三种编辑操作:插入一个英文字符、删除一个英文字符或者替换一个英文字符。 给定两个字符串ÿ…...
wordpress千万级访问/石家庄最新疫情
1、在windows下安装3-windows-installer.exe软件,默认安装。手动指定安装位置。比如:d:/crm2、访问一下看看是否好用。3、进入d:/crm,拷贝D:\crm\htdocs文件夹,到linux服务器下的网站默认文件夹下:/usr/local/apache2/htdocs,改名…...
wordpress媒体库制作文件夹/网络培训学校
随着近几年IT信息化技术应用变化快速发展,全国各高校的信息化系统也日趋完善,各种学习平台、教学、办公、管理平台都运行在数据中心,一旦数据中心发生故障,将影响到全校信息化系统的正常运转,近年来报道的个别企业已经…...
珠海企业网站建站/一句吸引人的广告语
最小生成树Kruskal裸题 康复训练ing 值得一提地是 用getchar() 一直在RE 最后换成了cin 才A掉 #include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std;#define MAX_V (30) #d…...
推荐几个高端大气上档次网站/怎么做市场营销和推广
项目框架的JS库集成了jQuery,Layout页面(模板页面,类似ASP.NET的母版页)中引用了这些JS,后来使用图表插件(图表插件是基于jQuery的)的时候,项目框架中的JS和图表插件有冲突ÿ…...
网页和网站的联系/学seo哪个培训好
Toy Posted in Apps, IDECobras 是次要专注于行使 Qt 的集成开辟环境(IDE),它宣布在 GNU GPL 允许和谈之下,仅需求 gcc 和 gdb 作为内部东西,程序功用厚实,且运转不乱而疾速。行使 Qt 从事软件开辟的冤家没…...
如何做收费视频互动网站/怎么快速推广自己的产品
任何平台都有一套规则,抖音也不例外,那么想玩好抖音,那么利用规则去做就是最好的办法。那么佛山抖音老师教几个实用技巧吧! 技巧一、调整发布时间 有统计显示,有62%的用户,会在饭前和睡前刷抖音,…...