搜索
有爱,有技术,有你^_^)y
╱人◕‿‿◕人╲订下契约(注册新用户)

合作站点账号登陆

QQ登录

只需一步,快速开始

快捷导航
查看: 798|回复: 13
收起左侧

[谜题巧思] 【原创】自动WINXP扫雷器

[复制链接]

签到天数: 1 天

连续签到: 1 天

[LV.1]初来乍到

9

主题

11

好友

1118

积分

Continue

积分
1118
发表于 2013-8-8 14:52:11 | 显示全部楼层 |阅读模式

╱人◕‿‿◕人╲定下契约

您需要 登录 才可以下载或查看,没有账号?╱人◕‿‿◕人╲订下契约(注册新用户)

x
本帖最后由 踢馆帝 于 2013-8-8 19:18 编辑

序言
本人平时无聊时总会玩玩扫雷游戏,某天一如既往的被炸死后,突然想写一个自动扫雷的程序来玩玩,经过几天的思考和CODING,算是完成了一个初版,下面就来简单介绍一下扫雷的基础和程序的流程。
命名
先规定一下本文中使用的基本名词
(1)扫雷中的方格称为<>
(2)有数字的块称为<数字块>
(3)没有点击也没有做标记的块称为<未知块>
(4)已经确定是雷的称为<>
(5)<>周围相邻的所有块的集合称为<8-邻域>
(6)将<8-邻域>扩大一个单位,并去除四个角落,称为<20-邻域>
file:///C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ksohtml\wps_clip_image-8386.png
<8-邻域><20-邻域>示意图
<8-邻域>:红色区域除去a
<20-邻域>:黄色区域除去a
扫雷基础
在扫雷游戏刚开始,第一步貌似点哪里被炸的几率都一样,但其实并非如此,我们以WINDOWS-XP的扫雷(简称<XP扫雷>)为例,<XP扫雷>的第一步一定不会是雷,有兴趣的童鞋可以用DEBUG工具分析或者查看源代码。<XP扫雷>的运行机制是当用户第一次点击时,生成雷区,如果用户点击的<>正好是雷,则重新生成雷区。因此第一步不用担心。
既然第一步不会被炸,那么随便点哪里都一样吗?其实也不是,因为我们希望第一步能点开一片区域(也就是被点击的<><8-邻域>没有雷),这样我们就可以从区域的边界来推算下一步该如何选择。
好了,那么问题就变成这样了:<XP扫雷>刚开始时,哪些<>在点击后,<8-邻域>一个雷都没有的几率最大?相信大家凭直觉就能知道是雷区的角落和边界,实际上也正是如此,通过计算也能得出角落是最优选择,其次是边界。
判断方法1
假如第一步已经点开了一片区域,那么下面我们就要推算哪些是雷,哪些不是雷了。
先说最简单的判断方法,也就是<数字块><8-邻域>中的<未知块>的数量等于<数字块>的数字,此时,所有的<未知块>都是<>。下面的图就是一个典型例子。
file:///C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ksohtml\wps_clip_image-9538.png
判断方法2
这是一个稍微复杂一点的方法,涉及到的区域是<20-邻域>。看到下图中,黄色方框中的<3><8-邻域>中有2<未知块>,但是只有1<>,因此无法判断。再看红色方框中的<1>,它的<8-邻域>中有3<未知块>1<>,也无法判断。但是将这两个区域结合起来,我们将<1><8-邻域>的所有<未知块>称为<未知集合1>,将<3><8-邻域><未知块>称为<未知集合2>,我们发现<未知集合1>包含了<未知集合2>,因此可以果断得出结论,<未知集合1><未知集合2>的未重叠部分,一定没有<>
将这个方法归纳一下:
<未知集合1>n1<未知块>b1<>
<未知集合2>n2<未知块>b2<>
<未知集合1>包含<未知集合2>,可以得出n1>n2
那么<未知集合1>除去<未知集合2>的剩余部分有n1-n2<未知块>,有b1-b2<>
此时可以考察b1-b2,如果b1-b2 = 0,则说明n1-n2<未知块>全都不是<>,如果        b1-b2 = n1-n2,则说明n1-n2<未知块>全都是<>
其实这个方法还可以继续推广,<未知集合1>包含<未知集合2>~<未知集合n>,并且<未知集合2>~<未知集合n>互相不想交,则也可以适用上面的判断。
file:///C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ksohtml\wps_clip_image-31801.png
更高级的判断方法
本人比较愚笨,只会用这两种方法,穷途末路以后就全拼RP..........
如果各位有什么其它更高级的方法,希望能告诉我。程序实现
程序分为几个部分
(1)雷区的获取
本程序是直接通过分析图像来获得雷区信息的,步骤如下:
l 通过win32函数找到扫雷游戏的窗口坐标和窗口大小
l 对扫雷窗口截图,转换为彩色图和灰度图两个版本
l 通过灰度图分析雷区的方格信息,方法是找到每行每列像素的灰度边界,找出边界之间的距离,并列出距离的直方图,通过直方图找到方格的大小和数量,并可以找到雷区相对于窗口的相对坐标
l 获取每个方格的状态则是采用彩色图,简单的将方格像素直接和预存的常量对比,状态包含<未知><0><1><2><3><4><5><6><7><8><旗帜><><>
(2)雷区判断
l 使用上文提到的两种方法遍历雷区,获取整个雷区的<概率图>,概率是从0~10代表一定不是雷,1代表一定是雷,除了01以外的概率并不是非常准确,因为只是采用了上文提到的两种方法来计算
l 调用win32函数控制鼠标,将所有概率是0的方格点开,概率是1的标记旗帜(也可以不标记,因为标记旗帜对程序来说没有任何作用)
l 重复上述步骤,直到完成扫雷或者无法继续
下图是一次自动解<扫雷高级>的结果,可以看到并没有扫完,程序无法继续了,实际上只通过上面说到的两种方法,只能完成<扫雷初级>和大部分<扫雷中级><扫雷高级>的完成率是很低的,最后只能使用概率来拼RP

file:///C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ksohtml\wps_clip_image-26082.png
屏幕最上面的图表是概率图,概率0是白色,概率1是红色,概率越大颜色越深
屏幕左下角是雷区状态图,用数字表示了每个块的状态


程序下载地址http://115.com/lb/5lbfjwj6#
automine.rar
115网盘礼包码:5lbfjwj6

评分

参与人数 1宅魂 +1 宅币 +1 收起 理由
mt---king + 1 + 1 o(* ̄▽ ̄*)ブ 发糖

查看全部评分

签名被小宅喵吞掉了~~~~(>_<)~~~~
回复

使用道具 举报

该用户从未签到

7

主题

18

好友

4152

积分

序章

积分
4152
发表于 2013-8-8 15:16:05 | 显示全部楼层
要是自定义难度呢……
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

2

主题

23

好友

1808

积分

Continue

积分
1808
发表于 2013-8-8 15:21:43 | 显示全部楼层
还需完善,继续努力!
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

签到天数: 1 天

连续签到: 1 天

[LV.1]初来乍到

19

主题

31

好友

1万

积分

第一章

积分
12213
发表于 2013-8-8 17:37:42 | 显示全部楼层
捧场··
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

397

主题

61

好友

11万

积分

荣誉会员

地下研究所 所长

积分
115586
发表于 2013-8-8 18:04:53 | 显示全部楼层
记得有位大神用XYZZY的秘笈写了一个自动扫雷器,是通过识别XYZZY秘笈在显示器左上角显示的当前鼠标所指方格内是否有雷的状态来实现的。
回复 支持 反对

使用道具 举报

签到天数: 1 天

连续签到: 1 天

[LV.1]初来乍到

9

主题

11

好友

1118

积分

Continue

积分
1118
 楼主| 发表于 2013-8-8 19:06:27 | 显示全部楼层
hcl 发表于 2013-8-8 18:04
记得有位大神用XYZZY的秘笈写了一个自动扫雷器,是通过识别XYZZY秘笈在显示器左上角显示的当前鼠标所指方格 ...

我这个主要目的还是学习扫雷的决策方法,以一种更接近人的方式来扫雷
版主所说的秘籍我貌似有听说过
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

签到天数: 1 天

连续签到: 1 天

[LV.1]初来乍到

9

主题

11

好友

1118

积分

Continue

积分
1118
 楼主| 发表于 2013-8-8 19:19:12 | 显示全部楼层
帖子底部更新了程序的下载地址,大家可以下载来玩,需要.net4.0环境
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

35

主题

44

好友

1万

积分

第一章

积分
15161
发表于 2013-8-8 21:47:13 | 显示全部楼层
是自己研究的方法吧...?
我玩儿扫雷少点儿还好,多了完全晕掉,而且经常卡壳...
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

签到天数: 1 天

连续签到: 1 天

[LV.1]初来乍到

9

主题

11

好友

1118

积分

Continue

积分
1118
 楼主| 发表于 2013-8-8 22:29:37 | 显示全部楼层
Abel404 发表于 2013-8-8 21:47
是自己研究的方法吧...?
我玩儿扫雷少点儿还好,多了完全晕掉,而且经常卡壳... ...

恩,我也只会这两种判断方法,玩扫雷高级基本上无法赢
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

9

主题

36

好友

2780

积分

Continue

积分
2780
发表于 2013-8-18 10:23:52 | 显示全部楼层
设S1 = {x1,..xn}为某些未知块构成的集合,S1含雷F(S1)个,如果|S1| = F(S1),那全都标记雷,如果0=F(S1),那全都可以戳开,这就是规则1;如果S1包含S2,那F(S1 - S2) = F(S1) - F(S2),就是规则2
感觉靠推理就只有这点信息了
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

签到天数: 1 天

连续签到: 1 天

[LV.1]初来乍到

9

主题

11

好友

1118

积分

Continue

积分
1118
 楼主| 发表于 2013-8-19 12:40:54 | 显示全部楼层
dchneric 发表于 2013-8-18 10:23
设S1 = {x1,..xn}为某些未知块构成的集合,S1含雷F(S1)个,如果|S1| = F(S1),那全都标记雷,如果0=F(S1), ...

我也是这么认为的......但是总感觉会有更高级的推理方法
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

该用户从未签到

9

主题

36

好友

2780

积分

Continue

积分
2780
发表于 2013-8-20 03:52:24 | 显示全部楼层
踢馆帝 发表于 2013-8-19 12:40
我也是这么认为的......但是总感觉会有更高级的推理方法

仔细琢磨应该还是有的,比如一个固定形状的区域,周边数字都已知,雷的个数可以估计,那雷的排布总归是有限种,于是可能出现某几个方块永远是雷或永远不是的情况
类似于数学里的围线积分,边界决定内部值。只是局部条件从可微变成了这里扫雷的数字规则
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 1 反对 0

使用道具 举报

该用户从未签到

8

主题

13

好友

1万

积分

第一章

积分
16683
发表于 2013-10-5 11:50:16 | 显示全部楼层
本帖最后由 Athrun_Jala 于 2013-10-5 11:51 编辑

这样应该也算吧
1-2式.png
一期一会
回复 支持 反对

使用道具 举报

签到天数: 1 天

连续签到: 1 天

[LV.1]初来乍到

9

主题

11

好友

1118

积分

Continue

积分
1118
 楼主| 发表于 2013-10-5 18:09:06 | 显示全部楼层

恩,这个的确是的,但是不知道怎么将这种情况总结为一个泛化的规律
签名被小宅喵吞掉了~~~~(>_<)~~~~
回复 支持 反对

使用道具 举报

本版积分规则

小黑屋|手机版|技术宅(Z站|基宅) ( 粤ICP备18082987号-1 )

GMT+8, 2025-6-16 20:42 , Processed in 0.194635 second(s), 37 queries , Redis On.

Copyright © 2018 技术宅社区

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表