扫雷不死的秘密

原文链接:http://www.titilima.cn/?action=show&id=276

Windows的扫雷游戏有这么一个秘密:在你第一次点击游戏区中的方块时,出现的绝对不会是地雷。

实践是检验真理的唯一标准,我用IDA拆了winmine.exe,版本是5.1.2600.0。下面我只简要介绍分析的结果,不再特别列出晦涩的汇编代码。

扫雷游戏的游戏区数据放在一个庞大的一维BYTE数组中,这个变量的名字是rgBlk。并且,用于获取指定坐标信息的公式是:

  1. LPBYTE pbPos = &rgBlk[y * 32 + x];

注意,这里的x和y是以1为起始索引的;换句话说,rgBlk[0]~rgBlk[31]是不被使用的。另外,对于最大的游戏区(30*24)来说,rgBlk的大小是足够可以胜任的。

那么下面我们的实验开始,在调试器中检查rgBlk的内存。为了显示的简洁明了,我选择了初级9*9的区域。

在上图中我对db输出的结果做了处理,其中白色背景的被选定文本区域是游戏区的有效内存数据,灰色的文字也代表了无效(横坐标大于9)的数据。红色的8f代表随机生成的地雷,1f代表这个方块还未被翻开。

接下来我故意打开第2行第1列的方块,并继续检查游戏区的数据,如下图。

如你所见,这个方块并不是雷,它的数据变成了42。与此同时,第1行第1列的方块却变成了8f,也就是地雷的数据。

好了,下面再打开第1行第1列的方块,游戏结束。最后的结果表示,地雷的位置和内存中的数据是一样的。

最后当然是揭秘环节。在玩家点击了一个含有地雷的方块时,游戏会做出如下判断:

  1. 如果游戏已经进行(不是第一次点击),则引爆地雷,游戏结束。
  2. 如果本次点击为第一次点击,则从左上角开始依次搜索,直到找到一个不是地雷的方块,并将其修改为地雷。原有的地雷方块做无雷处理。

上面的逻辑是在StepSquare函数中实现的,有兴趣的可以详细了解一下逆向后的代码。

从用户体验的角度来讨论的话,这么做的原因很简单:如果不特殊处理的话,从概率学的角度上来讲,那种每次玩扫雷都会被第一个方块炸死的衰人还是会有的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值