喵宅苑 MewoGarden × 技术宅社区II | Z站 Z Station 棒棒哒纯文字二次元技术社区

正文

【原创】自动WINXP扫雷器

作者:踢馆帝
[i=s] 本帖最后由 踢馆帝 于 2013-8-8 19:18 编辑
序言
本人平时无聊时总会玩玩扫雷游戏,某天一如既往的被炸死后,突然想写一个自动扫雷的程序来玩玩,经过几天的思考和CODING,算是完成了一个初版,下面就来简单介绍一下扫雷的基础和程序的流程。
命名
先规定一下本文中使用的基本名词
(1)扫雷中的方格称为<>
(2)有数字的块称为<数字块>
(3)没有点击也没有做标记的块称为<未知块>
(4)已经确定是雷的称为<>
(5)<>周围相邻的所有块的集合称为<8-邻域>
(6)将<8-邻域>扩大一个单位,并去除四个角落,称为<20-邻域>
<8-邻域><20-邻域>示意图
<8-邻域>:红色区域除去a
<20-邻域>:黄色区域除去a
扫雷基础
在扫雷游戏刚开始,第一步貌似点哪里被炸的几率都一样,但其实并非如此,我们以WINDOWS-XP的扫雷(简称<XP扫雷>)为例,<XP扫雷>的第一步一定不会是雷,有兴趣的童鞋可以用DEBUG工具分析或者查看源代码。<XP扫雷>的运行机制是当用户第一次点击时,生成雷区,如果用户点击的<>正好是雷,则重新生成雷区。因此第一步不用担心。
既然第一步不会被炸,那么随便点哪里都一样吗?其实也不是,因为我们希望第一步能点开一片区域(也就是被点击的<><8-邻域>没有雷),这样我们就可以从区域的边界来推算下一步该如何选择。
好了,那么问题就变成这样了:<XP扫雷>刚开始时,哪些<>在点击后,<8-邻域>一个雷都没有的几率最大?相信大家凭直觉就能知道是雷区的角落和边界,实际上也正是如此,通过计算也能得出角落是最优选择,其次是边界。
判断方法1
假如第一步已经点开了一片区域,那么下面我们就要推算哪些是雷,哪些不是雷了。
先说最简单的判断方法,也就是<数字块><8-邻域>中的<未知块>的数量等于<数字块>的数字,此时,所有的<未知块>都是<>。下面的图就是一个典型例子。
判断方法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>互相不想交,则也可以适用上面的判断。
更高级的判断方法
本人比较愚笨,只会用这两种方法,穷途末路以后就全拼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
屏幕最上面的图表是概率图,概率0是白色,概率1是红色,概率越大颜色越深
屏幕左下角是雷区状态图,用数字表示了每个块的状态
程序下载地址http://115.com/lb/5lbfjwj6# automine.rar 115网盘礼包码:5lbfjwj6

回复

这样应该也算吧

作者:踢馆帝
查看回复

本帖最后由

作者:Athrun_Jala
[i=s] 本帖最后由 Athrun_Jala 于 2013-10-5 11:51 编辑 这样应该也算吧
查看回复

我也是这么认为的

作者:dchneric
踢馆帝 发表于 2013-8-19 12:40 我也是这么认为的......但是总感觉会有更高级的推理方法
仔细琢磨应该还是有的,比如一个固定形状的区域,周边数字都已知,雷的个数可以估计,那雷的排布总归是有限种,于是可能出现某几个方块永远是雷或永远不是的情况 类似于数学里的围线积分,边界决定内部值。只是局部条件从可微变成了这里扫雷的数字规则
查看回复

为某些未知块构成的集合

作者:踢馆帝
dchneric 发表于 2013-8-18 10:23 设S1 = {x1,..xn}为某些未知块构成的集合,S1含雷F(S1)个,如果|S1| = F(S1),那全都标记雷,如果0=F(S1), ...
我也是这么认为的......但是总感觉会有更高级的推理方法
查看回复

为某些未知块构成的集合

作者:dchneric
设S1 = {x1,..xn}为某些未知块构成的集合,S1含雷F(S1)个,如果|S1| = F(S1),那全都标记雷,如果0=F(S1),那全都可以戳开,这就是规则1;如果S1包含S2,那F(S1 - S2) = F(S1) - F(S2),就是规则2 感觉靠推理就只有这点信息了
查看回复

是自己研究的方法吧

作者:踢馆帝
Abel404 发表于 2013-8-8 21:47 是自己研究的方法吧...? 我玩儿扫雷少点儿还好,多了完全晕掉,而且经常卡壳... ...
恩,我也只会这两种判断方法,玩扫雷高级基本上无法赢
查看回复

是自己研究的方法吧

作者:Abel404
是自己研究的方法吧...? 我玩儿扫雷少点儿还好,多了完全晕掉,而且经常卡壳...
查看回复

帖子底部更新了程序的下载地址

作者:踢馆帝
帖子底部更新了程序的下载地址,大家可以下载来玩,需要.net4.0环境
查看回复
上一页
下一页
0%
站点地图友情链接:
喵宅苑
喵空间社区程序
喵宅苑 静态版
宅喵RPG地图编辑器
络合兔
Lanzainc
技术宅
小五四博客
莉可POI
Mithril.js
枫の主题社
Project1
午后少年
机智库
七濑胡桃
xiuno
幻想の日常
魂研社
Nothentai
0xffff
欲望之花
泽泽社长
淀粉月刊
HAYOU
红客联盟
异次元
轻之国度
神奇宝贝新生代
游戏狗
口袋双子星
我的世界论坛
梦次元
动漫东东
动漫国际
精艺论坛
78动漫
吐槽弹幕网
漫客栈