C语言 数组的应用————扫雷

news2024/11/16 10:37:05

前言

在上一篇博客中我们实现了简单的三子棋小游戏,初步运用了二维数组,今天还是用二维数组来实现另一个小游戏——扫雷的基础版本,写这两个小游戏的目的主要是理解并运用数组,同时巩固前面学习的知识比如循环和函数等等,将其结合具体情况解决我们的需要。

代码实现

在这一部分我们会用代码实现扫雷,并理清游戏与代码的逻辑。扫雷的游戏界面如图826d29cd0dde433691552932e5eb815e.png

这是在网上找到的扫雷过程,从图中我们可以知道,扫雷的游戏界面可以用数组来打印、每选择一个点要查询周围八个点是否有雷,当附近有雷时我们要打印数字来提示玩家周围的雷的数量,当所有非雷的元素都被找出来游戏就结束。

游戏菜单

游戏菜单的打印和主函数的逻辑我们可以做成与三子棋一样,我们的主要精力还是要放在游戏的实现上,所以我们直接按照上次的代码写就行。

#include"game.h"

void Menu()
{
	printf("*****************************\n");
	printf("********   1.play     *******\n");
	printf("********   0.exit     *******\n");
	printf("*****************************\n");
	
}


int main()
{
	int input = 0;
	do
	{
		Menu();
		printf("请选择->\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			//game();
			printf("开始游戏\n");
			break;
		case 0:
			printf("退出\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}

	} while (input);

	return 0;
}

数组创建与初始化

在这个程序里,我们如果要实现一个9*9的扫雷棋盘,我们需要创建两个数组,一个用来打印提示信息显示给玩家看,另一个用来存放雷的位置。而考虑到后面我们需要判断一个点周围是否有雷的情况,如果时9*9的数组,我们就要用很多个if语句来分情况遍历周围的点,为了后续排雷功能更好实现,我们直接在每一条边都再加上一行元素,这一行元素我们不显示,同时他们也不会是雷,这样我们所需要创建的数组就需要比游戏棋盘的行和列都加二。游戏界面的行和列和数组的行和列后序我们经常会用到的变量我们都在game。h中用define来定义。

6a815165cf684d5ab93efb597d398df9.png

然后我们在game函数里要创建两个数组。关于数组的类型,由于我们给玩家展示的棋盘我们要将没有被排到过的点显示为 ‘ * ’ ,所以我们这个showboard数组的类型必须是char类型,而存储雷的位置的数组mineboard我们也可以用char类型,这样我们只用写一个数组初始化函数就行了。

关于数组初始化,由于两个数组的类型都是char类型,在mineboard中我们用 ‘1 ’来表示雷,用

‘ 0 ’来表示没有雷。在showboard中,我们用‘ * ’来表示未被排查,用数字字符来表示周围雷的数量,如果周围没有雷,我们用空格来表示。于是我们就需要将mineboard数组初始化为 ‘ 0 ’,将showboard数组初始化成 ‘ * ’。这时候我们除了数组名,行和列以外,还要多加一个参数来指定初始化的内容。

0dde6dc144a849f5abff9a39e3ce839f.png

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

在初始化这个函数中,我们传的参数是ROWS和COLS,这是因为我们要将整个数组全部初始化,如果不初始化后续会影响我们排雷。

打印游戏棋盘

在打印游戏棋盘的函数中,我们要传的是ROW 和 COL,而不是ROWS和COLS,因为数组里面有用的部分就是中间的9*9,外围的四排我们不用打印,这时候要注意下标的范围,行标和列标都是1~9。在我们打印的时候,由于行数和列数有点多,我们可以在上面一行和左边一列把行和列打印出来,更方便玩家选点。列的信息可以在循环中打印,行的信息可以在进去循环之前打印,我们还可以在棋盘的上下打印分隔线来划分每一次排雷的范围。ccba148d331d46e1ab5b71adc4731019.png

    void Displayboard(char board[ROWS][COLS], int row, int col)
{
	printf("-----------------------------\n");
	int i = 0;
	int j = 0;
	for (i = 0; i <= col; i++)
	{
		printf("%d ", i);

	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("-----------------------------\n");

}

数组放雷

放雷这个功能我们还是用到随机数来实现,生成的随机数对9取模再加一,我们就能得到1~9的随机数,得到坐标后,我们要判断这个坐标是否已经放过雷。在这之前,我们要在game。h中用define定义雷的数量。同时,放雷的函数我们传的参数也是ROW和COL这个游戏界面的范围,也就是行列坐标都是0~9.

fd607d0fd28f4a81a6b1ada5f1ff34ea.png

void GenerateMine(char mineboard[ROWS][COLS], int rows, int cols,int mine_count)//往棋盘中放雷
{
	int x = 0;
	int y = 0;
	while (mine_count)
	{
		x = rand() % 9 + 1;
		y = rand() % 9 + 1;
		if (mineboard[x][y] == '0')
		{
			mineboard[x][y] = '1';
			mine_count--;
		}

玩家排雷

我们可以在game函数中用一个while循环来接受玩家的输入信息,在接收到输入信息时,首先要判断坐标的合法性,坐标合法时再进入下一步,然后判断这个点是否已经被排查过了(是否为空格),如果没有被排查过再次判断这个点是否为雷,如果是雷,游戏结束,如果不是雷,则进入函数checkmine用于这个点的周围八个点的排查,checkmine函数要传刚刚输入的两个坐标和两个数组,ROW和COL,我们还要传一个用来记录已经排查的坐标的个数的参数,find_count,由于我们要在函数里对其进行修改,所以要传它的指针。

ed362187be05404c8c3b2fd072aa9dd6.png

当我们要进到checkmine,首先,这个点已经确定是空格了,所以我们直接让count_find(当count_find==ROW*COL-MINE_COUNT时,游戏结束,所有非雷的坐标都被找了出来,玩家赢了)的值加1;先将其赋值为空格(如果周围有雷后面会改成雷的数量),然后我们要定义一个minecount来记录周围八个点的雷的数量,然后用两层循环遍历周围八个点。当minecount不为0时,也就是周围八个点存在雷,那么这次函数就只用将周围八个点中不是雷的点变成空格,每次变成空格是count_find+1。当minecount为0时,意味着周围八个点都不是雷,此时需要展开这个点,用两层循环将八个点遍历一遍,如果坐标合法,且不为空格和数字字符(是空格则说明已经被排查过了,不要再check),就将该点坐标传进check函数,这是地推的过程。每一个点当他周围有雷时就不再继续往周围递推了,这时候就会回归上一级函数,递归也就返回了。

递推或者说checkmine函数最需要注意的一点是mine_find的值,当showboard中每有一个值被改为空格(被排查),他就要加一,而且被改为空格后就不要再改会 ‘ * ’。我们只有在两个地方会将数组元素改为空格,一是该点进入check函数时,先将其改成空格,如果周围有雷再改成数字字符,二是当周围有雷时,我们要将周围八个点中不是雷的数组元素改为空格,因为他们要将被排查了,但是他们不用显示雷的数量。

void check(int x, int y, int* count_find, char mineboard[ROWS][COLS], char showboard[ROWS][COLS], int row, int col)
{
	*count_find=*count_find+1;
	showboard[x][y] = ' ';
	int minecount = 0;
	int i = 0;
	int j = 0;
	//if (*count_find == row * col - MINE_COUNT)//这一行不用写,有没有不影响结果
	//	return;
	for (i = -1; i <= 1; i++)
	{
		for (j = -1; j <= 1; j++)
		{
			if (x + i >= 1 && x + i <= 9 && y + j >= 1 && y + j <= 9)
			{
				if (mineboard[x + i][y + j] == '1')
				{
					minecount++;
				}
				else
				{
					if (i != 0 || j != 0)
					{
						showboard[x + i][y + j] = ' ';
						*count_find = *count_find + 1;
					}
				}
			}
		}
	}
	if (minecount == 0)
	{
		for (i = -1; i <= -1; i++)
		{
			for (j = -1; j <= 1; j++)
			{
				if(x+i>=1&&x+i<=row&&y+j>=1&&y+j<=col)
				check(x + i, y + j, count_find, mineboard, showboard, row, col);
			}
		}
	}
	else
	{
		showboard[x][y] = minecount+'0';
	}
}

运行截图

在测试时我们可以打印count_find来测试我们的count_find是否记录正确

被炸死

成功通关

测试的是75个雷,也就是只要排除7个点,我们先把雷的数组打印出来来测试能否检测赢得游戏

展开测试

将雷的数量设少一点来测试递归。

这时候图上还有十一个' * ',说明count_find的统计也没有问题。

结语  求点赞!

扫雷这个游戏的checkmine函数真的卡了很久,制作不易,感谢各位的观看,如果感觉对你有帮助,可以点上一个免费的赞,这对作者的创作来说是一个很大的鼓励,感谢各位的阅读。

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

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

相关文章

分享一个不错的three.js开源项目

项目将three.js相关内容封装为相应库 很值得学习&#xff0c;可以模仿项目学习three.js vue-vite-three.js threejs-park: 基于vue3&#xff0c;threeJS智慧园区 threejs-park

YOLOv9改进策略:注意力机制 | 用于微小目标检测的上下文增强和特征细化网络ContextAggregation,助力小目标检测,暴力涨点

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文改进内容&#xff1a;用于微小目标检测的上下文增强和特征细化网络ContextAggregation&#xff0c;助力小目标检测 yolov9-c-ContextAggregation summary: 971 layers, 51002153 parameters, 51002121 gradients, 238.9 GFLOPs 改…

ChatGPT登陆提示:“Please unblock challenges.cloudflare.com to proceed…”

ChatGPT登陆时提示&#xff1a;“Please unblock challenges.cloudflare.com to proceed”&#xff0c; 说明&#xff1a;请解除对challenges.cloudflare.com的屏蔽以继续 原因及解决方法&#xff1a; 1、出现这个问题&#xff0c;一般都是网络和本地环境问题&#xff0c;可以…

使用Nginx配置实现请求的限流操作

概述 限流&#xff08;Rate Limitting&#xff09;是服务降级的一种方式&#xff0c;通过限制系统的输入和输出流量以达到保护系统的目的。 比如我们的网站暴露在公网环境中&#xff0c;除了用户的正常访问&#xff0c;网络爬虫、恶意攻击或者大促等突发流量都可能都会对系统造…

Kotlin进阶之协程从上车到起飞

公众号「稀有猿诉」 原文链接 Kotlin进阶之协程从上车到起飞 通过前面的一篇文章我们理解了协程的基本概念&#xff0c;学会协程的基本使用方法&#xff0c;算是正式入门了&#xff0c;接下来就是要深入的学习技术细节和高级使用方法&#xff0c;以期完全掌握Kotlin协程…

【推荐系统】NCF神经协同过滤

NCF框架 NCF框架是本文要实现的3个模型的主体结构。 首先是输入层&#xff0c;分别包含两个特征向量 v u v_u vu​和 v i v_i vi​&#xff0c;描述了用户u和物品i。输入仅由一个用户向量和一个物品向量构成&#xff0c;它们分别是以one-hot编码的二值化稀疏向量。 接着是Em…

若依 ruoyi-cloud [网关异常处理]请求路径:/system/user/getInfo,异常信息:404

这里遇到的情况是因为nacos中的配置文件与项目启动时的编码不一样&#xff0c;若配置文件中有中文注释&#xff0c;那么用idea启动项目的时候&#xff0c;在参数中加上 -Dfile.encodingutf-8 &#xff0c;保持编码一致&#xff0c;&#xff08;用中文注释的配置文件&#xff0c…

SCI一区 | Matlab实现RIME-TCN-BiGRU-Attention霜冰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测

SCI一区 | Matlab实现RIME-TCN-BiGRU-Attention霜冰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测 目录 SCI一区 | Matlab实现RIME-TCN-BiGRU-Attention霜冰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测预测效果基本介绍模型描述程…

备战蓝桥杯Day31 - 真题-管道

题目描述 解题思路 这个问题可以视为一个水波在管道中传播的问题&#xff0c;其中水波以单位速度传播。阀门在 S 时刻打开&#xff0c;水流以单位速度流向管道的右侧&#xff0c;每个传感器位于每段管道的中心。对于位于 Li 的阀门&#xff0c;在 Ti 时刻打开时&#xff0c;水…

Stripe Android 购买集成

图片丢了来这里看&#xff1a;https://juejin.cn/post/7347220605610541091 1. 准备事项 Stripe 账号域名以及配套的网站Stripe 账号付款信息公钥和私钥配置产品以及价格 这些步骤可以看这篇&#xff1a;Stripe Web 购买集成 3. 分析一下流程 客户端集成和 Web 端集成有挺…

使用Python进行数据库连接与操作SQLite和MySQL【第144篇—SQLite和MySQL】

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 使用Python进行数据库连接与操作&#xff1a;SQLite和MySQL 在现代应用程序开发中&#xf…

8年测试总结,自动化测试必要注意点+自动化测试框架(汇总)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、开始自动化测试…

win修改图标自定义QQ桌面图标

当安装了TIM后&#xff0c;想把图标改成QQ 图标见顶部&#xff0c;或通过网盘下载 提取码&#xff1a;9Ayc 操作步骤&#xff1a; 1.桌面右键图标&#xff0c;点击属性 2.选择快捷方式-更改图标 3.浏览选择下载的ico图标即可

2024最新阿里云幻兽帕鲁搭建服务器_Palworld联机多人游戏

玩转幻兽帕鲁服务器&#xff0c;阿里云推出新手0基础一键部署幻兽帕鲁服务器教程&#xff0c;傻瓜式一键部署&#xff0c;3分钟即可成功创建一台Palworld专属服务器&#xff0c;成本仅需26元&#xff0c;阿里云服务器网aliyunfuwuqi.com分享2024年新版基于阿里云搭建幻兽帕鲁服…

Python装饰器:如何访问和设置私有属性?

大家好&#xff0c;今天我和大家聊一聊如何使用装饰器来访问和设置私有属性。 你有没有遇到过这样的场景&#xff1a;你有一个对象&#xff0c;它的属性是私有的&#xff0c;你想要在不影响原有代码的情况下&#xff0c;对这些私有属性进行操作。这时候&#xff0c;装饰器就派…

【JAVA】Servlet开发

目录 HttpServlet HttpServletRequest HttpServletResponse 错误页面 设置网页自动刷新时间 构造重定向相应 js发起http请求 服务器端对js发起的http请求进行处理 前端获取后端数据&#xff0c;添加到当前页面的末尾&#xff0c;代码示例&#xff1a; 前后端交互&…

微信小程序 nodejs+vue+uninapp学生在线选课作业管理系统

基于微信小程序的班级作业管理助手使用的是MySQL数据库&#xff0c;nodejs语言和IDEA以及微信开发者工具作为开发工具&#xff0c;这些技术和工具我在日常的作业中都经常的使用&#xff0c;并且因为对编程感兴趣&#xff0c;在闲暇时间也进行的进行编程的提高&#xff0c;所以在…

Leet code 1658 将x减到0的最小操作数

解题思路&#xff1a;滑动窗口 主要思想&#xff1a;正难逆简 题目需要左找一个数 右找一个数 我们不如直接找中间最长的一连串子数让这串子树和为 数组子树和减去X 找不到就返回 -1 滑动窗口双指针从左端出发&#xff0c;进行 进窗口 判断 出窗口 更新结果四个步骤 代码…

bugreport中查看开发者选项动画时长缩放日志

首先打开开发者选项&#xff0c;抓取一份bugreport解压后找到bugreport-机型-时间点.zip文件&#xff0c;然后再解压此文件 解压后进入该文件&#xff0c;找到bugreport-机型-时间点.txt文件 打开此文件&#xff0c;搜索“animator_duration_scale”关键字&#xff0c;找到图片…

9成省份“鸿蒙化”,它真起来了?

自去年9月华为宣布鸿蒙原生应用全面启动以来&#xff0c;鸿蒙正以不可阻挡之势&#xff0c;快速在全国千行百业的移动应用领域推进。不仅有支付宝、快手、淘宝、京东等超200家头部互联网企业加入鸿蒙生态&#xff1b;2024年以来&#xff0c;上海、浙江、广西等多省市政务民生、…