扫雷大师:用C语言揭秘自动展开盘面与智能扫雷策略

目录

  • 扫雷
  • 自动展开盘面
  • 智能扫雷
  • 更优策略
  • 完整代码

扫雷

扫雷游戏是一款经典的单人电脑游戏,其主要规则如下:

  1. 游戏目标:游戏的目标是在不触发任何地雷的情况下,找出所有非雷区域。玩家需要根据格子周围的数字来推断哪些格子含有地雷。

  2. 游戏界面:游戏界面是一个由许多封闭的格子组成的方形网格。格子的数量根据游戏难度不同而变化。一些格子下藏有地雷,其余格子则不含地雷。

  3. 操作方式

    • 左键点击一个格子会打开它,如果该格子下藏有地雷,则游戏结束。如果点击的格子周围没有地雷,则会显示一个数字,这个数字表示该格子周围八个格子中有多少个是地雷。
    • 如果点击的格子周围没有地雷,游戏会自动展开与该格子相邻的区域,直到显示出周围有地雷的格子为止。
    • 右键点击一个格子可以标记一个地雷的位置,防止误触。玩家也可以再次右键点击来取消标记或标记为问号。
  4. 胜利条件:玩家揭示所有非雷区域而没有触发任何地雷时,游戏胜利。

  5. 计时和计分:大多数扫雷游戏都会计时,玩家完成游戏所需的时间越短,成绩就越好。有些版本的游戏还会根据不同的标准进行计分。

这些是扫雷游戏的基本规则,游戏的乐趣在于玩家需要运用逻辑和策略来避免地雷,同时尽可能快地清除非雷区域。

举个例子:假设有这么一个盘面。
在这里插入图片描述
注意我标注出来的那个1,这个1周围的8个位置只有1个雷,所以右下角那个位置必然是雷,可以标注出来。
在这里插入图片描述
此时注意右下方那个1。
在这里插入图片描述
由于周围8个位置已经有1个位置确定是雷了,所以其余几个位置一定不是雷,也就是下面标注的位置都不是雷。
在这里插入图片描述
这样就可以接着展开这几个位置了。
在这里插入图片描述
如果使用C语言,我们用2个数组,其中一个数组mine存储雷的位置信息,用1表示雷,0表示非雷;另一个数组show存储展示给玩家的盘面,其中星号表示这个位置没有被排查,空格表示这个位置周围没有雷,数字字符标识周围雷的数量,标记位用感叹号和问号表示。注意为了防止潜在的越界,数组要比实际情况多开一圈,也就是说,如果是9*9的盘面,就应该开11*11的大小。

自动展开盘面

注意到如果周围有一大片非雷位置,有可能会一次性展开一片区域。这可以通过递归实现。

递归的结束条件:

  1. 这个位置已经越界了。
  2. 这个位置已经排查过了。
  3. 这个位置是雷。
  4. 这个位置周围有雷。

如果还没满足递归的结束条件,就递归探索上下左右四个位置。

void ExpandMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	// 越界
	if (x < 1 || x > ROW || y < 1 || y > COL)
		return;

	// 排查过
	if (show[x][y] == ' ' || isdigit(show[x][y]))
		return;

	// 遇到雷
	if (mine[x][y] == '1')
		return;

	// 排查并展开
	int n = GetMineCnt(mine, x, y);
	show[x][y] = n == 0 ? ' ' : '0' + n;
	if (n == 0)
	{
		ExpandMine(mine, show, x - 1, y);
		ExpandMine(mine, show, x + 1, y);
		ExpandMine(mine, show, x, y - 1);
		ExpandMine(mine, show, x, y + 1);
	}
}

智能扫雷

说是智能扫雷,其实只是把一个新手扫雷玩家的简单想法交给电脑完成。那么一个新手是怎么想的呢?

如果一个盘面内,有某几个位置确定是雷了,新手玩家就会把它标记出来。比如:

在这里插入图片描述
注意到2个1周围只有1个位置可能是雷,那这个位置就一定是雷了。换句话说,如果某个数字和周围有可能是雷的位置数相等,那么这几个位置就一定是雷,可以标记。

option为0表示标记(鼠标右键),option为1表示排查(鼠标左键)。GetShowCnt返回(i,j)周围有几个字符在字符串中,GetShowPoint返回满足在字符串中的字符坐标。注意x和y都是int*类型的指针。

// 找到某个数字,恰好等于周围所有未排查的雷
for (int i = 1; i <= ROW; ++i)
{
	for (int j = 1; j <= COL; ++j)
	{
		if (isdigit(show[i][j])
			&& GetShowCnt(show, i, j, "*!") == show[i][j] - '0'
			&& GetShowCnt(show, i, j, "*"))
		{
			*x = i;
			*y = j;
			GetShowPoint(show, x, y, "*");
			*option = 0;
			return;
		}
	}
}

如果已经把确定是雷的位置都找出来了,接下来应该做什么呢?
在这里插入图片描述
注意到框起来的1,周围已经有一个位置确定是雷了,那么圈起来的位置就一定不是雷。换句话说,如果某个数字和周围确定是雷的位置数相等,则其余位置一定不是雷,可以排查。
在这里插入图片描述

// 找到某个数字,与周围已标记为!的位置数相等,其余位置排查
for (int i = 1; i <= ROW; ++i)
{
	for (int j = 1; j <= COL; ++j)
	{
		if (isdigit(show[i][j])
			&& GetShowCnt(show, i, j, "!") == show[i][j] - '0'
			&& GetShowCnt(show, i, j, "*"))
		{
			*x = i;
			*y = j;
			GetShowPoint(show, x, y, "*");
			*option = 1;
			return;
		}
	}
}

当然,如果既找不到确定是雷的位置,也找不到确定不是雷的位置,就只能随机排查了。

// 随机排查某一个位置
while (true)
{
	*x = rand() % ROW + 1;
	*y = rand() % COL + 1;
	if (show[*x][*y] == '*')
	{
		*option = 1;
		return;
	}
}

更优策略

其实,以上并不是最优策略,经过测试,当代码走到“随机排查”的时候,有很大概率会踩到雷。事实上,如果你是个扫雷新手,在遇到无法判断的情况时,乱点一通,是很有可能踩到雷的。

这里抛砖引玉,有没有更优的策略呢?

如果你是扫雷高手,应该会知道些定式。我们可以让计算机识别这些基础模式,从而在某些情况下也能给出最优解:

  1. 直线模式
  • 1-2-1模式:当你在直线上看到1-2-1的排列时,两边的1对应的未揭开的格子都是雷。
  • 1-2-2-1模式:在直线上,如果出现1-2-2-1的排列,最外侧的1旁边的未揭开的格子是雷,而2之间的格子不是雷。
  1. 方块模式
  • 2x2的雷区:在一个2x2的区域内,如果有两个相邻的数字相同,那么他们共同指向的未揭开的格子是雷。
  1. 交叉模式
  • 相交的1:如果两个1在角落相交,那么两个1共同指向的那个格子是雷。
  • 相交的2:如果两个2在角落相交,且它们共有三个未揭开的格子,通常情况下,靠近两个2的两个格子是雷,远离2的那个格子不是雷。

如果还是无法判断呢?那就只能计算某个位置是雷的概率了,这又涉及到更加复杂的算法,本篇博客就不赘述了。

完整代码

已上传至Gitee链接

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MFC(二)集成基础控件

目录 OnCreateCStatic【标签&#xff0c;图片】CEdit【文本框&#xff0c;密码框&#xff0c;数值框&#xff0c;文本区】CButton【按钮&#xff0c;单选按钮&#xff0c;多选按钮】CComboBox【下拉列表&#xff0c;列表】CSliderCtrl【滑动条】CListCtrl【表格】CAnimateCtrl【…

第十二届蓝桥杯JavaB组省赛真题 - ASC

解题思路&#xff1a; 这是目前为止做到过最简单的了 public class Main {public static void main(String[] args) {int res L-A 65;System.out.print(res);} }

东联直播音效助手

东方联盟创始人郭盛华为广大主播免费开发的一款专用的音效场控工具&#xff0c;通过这款软件&#xff0c;主播使用各种精彩的音效&#xff0c;避免直播间过于低沉和尴尬&#xff0c;从而更好的拉近观众的距离。音效有掌声、爆笑声、尖叫声、关注点赞、任务等各种音效. 【东方联…

【win10 win11添加右键】git bash

打开注册表编辑器。 按下Win键 R&#xff0c;然后输入”regedit”并按下回车键来打开注册表编辑器。计算机\HKEY_CLASSES_ROOT\Directory\Background\shell\git_bash\command2. 导航到注册表路径&#xff1a;依次展开”HKEY_CLASSES_ROOT\Directory\Background\shell”。右键…

电商系列之仓储发货

疫情3年&#xff0c;大多数人都将购买需求转移到了线上。同时由于暴涨的订单数量、还在恢复中的物流运输等因素&#xff0c;导致用户的收货时间缓慢甚至是发货时间、收货时间延后。那么笔者就从订单的仓库作业流程入手&#xff0c;分析了用户订单发货延后的原因。 受到最近疫情…

2024年软件测试,“我“从初级到高级进阶,不再走弯路...

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

【git分支管理策略】如何高效的管理好代码版本

目录 1.分支管理策略 2.我用的分支管理策略 3.一些常见问题 1.分支管理策略 分支管理策略就是一些经过实践后总结出来的可靠的分支管理的办法&#xff0c;让分支之间能科学合理、高效的进行协作&#xff0c;帮助我们在整个开发流程中合理的管理好代码版本。 目前有两套Git…

mysql索引失效

什么是索引失效 在MySQL中&#xff0c;索引失效指的是查询语句无法有效地使用索引&#xff0c;而必须进行全表扫描。索引失效可能会导致查询性能下降&#xff0c;特别是在处理大量数据时。 索引失效的原因 1.索引列进行了运算或函数操作 如果对索引列进行了运算或使用了函数…

第十四届蓝桥杯C++A组(A/B/C/D/E/H)

文章目录 A.幸运数B.有奖问答C.平方差D.更小的数E.颜色平衡树H.异或和之和 A.幸运数 /*纯暴力*/ #include <bits/stdc.h>using namespace std;void solve() {int sum 0;for(int i 1; i < 100000000; i ){int n i;int a[11];int j 1;for(; n ! 0; j ){a[j] n % …

基于Python的Climate Indices库计算SPI01:不同站点不同时间尺度的SPI的计算

热闹的尽头是孤寂&#xff0c;在虚浮的欢闹中保持自己&#xff0c;纷繁世间&#xff0c;可报期望者不过二三。 文章目录 前言1. 概述2.1 目的2.2 说明 2. 版本2.1 天津&#xff0c;2024年1月18日&#xff0c;Version1 3. 微信公众号GISRSGeography 一、数据1. 输入数据2. 输出…

日常刷题之77-组合

题目 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案 提示&#xff1a;假设 n5,k3 就是需要组合出来&#xff0c;长度3且内容数据是在[1,n]这个区间内的所有可能得组合 同时一个组合里面内个数字只能出现一次&#…

windows grep 安装及使用

1&#xff09;下载地址&#xff1a; Grep for Windows 2&#xff09;选择这个包下载&#xff1a; 3&#xff09; 将D:\Program Files (x86)\GnuWin32\bin目录 加入系统变量&#xff1a; 4&#xff09;grep "ACE_Lock_Adapter" -i * 执行命令如下&#xff1a;

使用Git仓库进行项目代码同步与打包

1. 引言 最近在用友的开发者中心论坛发现好多小伙伴反馈使用 YonStudio 开发工具进行云端项目导入失败的问题&#xff0c;有感于此问题会影响开发小伙伴的开发效率&#xff0c;特编写此文帮助新手小伙伴去规避这类问题的发生。 一直以来&#xff0c;开发者依循惯性思维去依赖…

不会搭建物联网数据平台的老板参考一下吧

搭建牛奶厂的物联网数据平台 对于现代牛奶厂&#xff0c;在数字化时代中&#xff0c;搭建物联网数据平台至关重要。这样的平台基础是建立IOT数据底座平台&#xff0c;它是支撑物联网应用的数据存储和管理基础设施&#xff0c;通常由分布式存储系统、时序数据库集群和存储管理组…

放弃 Rust 选择 Zig,Xata 团队推出 pgzx —— 计划使用 Zig 开发基于 PG 的分布式数据库

Summary Xata 公司在基于 PostgresSQL 开发自己的分布式数据库&#xff0c;出于 Zig 和 C 语言以及 PostgreSQL 的 API 有更好的互操作性的考虑&#xff0c;他们选择了 Zig 而非当红炸子鸡语言 Rust。他们的博客文章中对 pgzx 进行了介绍。让我们来看下他们对 Zig 和 Rust 语言…

学习网络编程No.15【高级IO之多路转接】

引言&#xff1a; 北京时间&#xff1a;2024/3/19/11:16&#xff0c;若是说记忆有克星的话&#xff0c;那么一定是时间。若是说耐心有克星的话&#xff0c;那么一定是人的心态。连续几天睡眠问题&#xff0c;加上环境影响&#xff0c;上篇博客还有部分知识只能放在该篇博客介绍…

面试总结:C++11新特性

对于C11的特性你了解多少&#xff1f;简单说说 - 在语法层面引入统一初始化&#xff08;即列表初始化&#xff09;&#xff0c;那么C11的初始化就可以分为列表初始化和字面值初始化 列表初始化就是使用{}&#xff08;花括号&#xff09;来进行对象、内置基本类型等的初始化 in…

超全整理,软件测试-性能测试流程汇总,看这一篇就够了...

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

这个插件,提供了1000多个在线底图服务!

本文推荐一下QGIS中的热门插件:QuickMapService。目前在QGIS插件市场下载量排名第一,先看下官网的介绍: Easy to use list of services and search for finding datasets and basemaps. 言简意赅,用来添加QGIS底图的插件。 插件安装 打开QGIS自带的插件管理器。 在搜索框中…

学习要不畏难

我突然发现&#xff0c;畏难心是阻碍我成长的最大敌人。事未难&#xff0c;心先难&#xff0c;心比事都难&#xff0c;是我最大的毛病。然而一念由心生&#xff0c;心不难时&#xff0c;则真难事也不再难。很多那些自认为很难的事&#xff0c;硬着头皮做下来的时候&#xff0c;…