AIGC标识 我用Python写了一个扫雷辅助工具,最难的部分根本不是算法

image

一开始只是好奇。

上班摸鱼的时候偶尔会开一局扫雷,高级模式最快也就两分多钟。后来刷到一个视频,说世界纪录是26秒。我当时想的是:这手速也太离谱了吧?

查了一下才知道,人家用的是双击(Chording),配合肌肉记忆级别的定式识别。不是一格一格点的。

后来我就想,能不能写个脚本,帮我把那些"一眼就能确定"的格子自动标出来。这样人只需要处理需要推理的部分就行。

说干就干。

第一版:规则引擎,半天搞定

核心逻辑其实比想象中简单。

每一轮只需要做两件事:

  1. 遍历所有已翻开的数字格,计算它的"有效数字"(显示的数字减去周围已标雷数)
  2. 如果有效数字等于周围未开格子数 → 这些格子全是雷,标上
  3. 如果有效数字为0 → 周围未开格子全安全,点开

就这么三条规则,已经能处理初级模式90%以上的局面。

def basic_deduce(board):
    """确定性推理:返回 (必安全列表, 必雷列表)"""
    safe_cells = set()
    mine_cells = set()

    for (x, y), num in board.revealed_cells():
        neighbors = board.get_unrevealed_neighbors(x, y)
        flagged = board.get_flagged_neighbors(x, y)
        effective = num - len(flagged)

        if effective == 0:
            safe_cells.update(neighbors)
        elif effective == len(neighbors):
            mine_cells.update(neighbors)

    return safe_cells, mine_cells

写完运行了一下,初级基本全自动通关,中级也能走一大半。但高级模式大概到中盘就卡住了。

第二版:加了定式匹配,提升明显

"卡住"的原因很简单:很多局面不是单个数字能判断的,需要两个数字联动。

比如经典的1-2-1定式。如果把局面写成约束方程:

x₁ + x₂      = 1   (数字1的约束)
x₁ + x₂ + x₃ = 2   (数字2的约束)
      x₂ + x₃ = 1   (数字1的约束)

人脑看到"1-2-1"就知道两边安全、中间是雷。但程序需要把这些局部约束提取出来,然后做集合运算。

我的做法是:每轮先用基础规则推一遍,推不动了,就把相邻两个数字格共享的未开格子提取出来做集合减法。

def pattern_deduce(board):
    """局部定式推理"""
    for cell_a in board.frontier_cells():
        for cell_b in board.adjacent_frontier_cells(cell_a):
            shared = cell_a.neighbors & cell_b.neighbors
            a_only = cell_a.neighbors - shared
            b_only = cell_b.neighbors - shared

            # 1-n定式
            a_eff = cell_a.effective_number()
            b_eff = cell_b.effective_number()

            if a_eff - len(shared) == 0:
                # a的雷全在共享区,b独享的全是雷
                if len(b_only) == b_eff:
                    yield 'mines', b_only
            # ... 其他定式

这一版加进去之后,高级模式能走80%以上了。

第三版:回溯搜索,但遇到了真问题

剩下那20%的局面,局部推理完全不够用。需要把整个边界当作一个约束满足问题来解。

标准的做法是回溯搜索 + 概率计算。但我发现一个问题:

不是算法难,是截图识别太坑了。

我一开始用 pyautogui 截图 + 像素匹配来识别数字。结果发现:

  • 不同分辨率下数字像素位置不一样
  • Win10和Win11的扫雷界面颜色有差异
  • 窗口被其他窗口遮挡一点点就全部识别失败
  • 1和7在低分辨率下几乎无法区分

光调试识别逻辑就花了我一个周末。

最后换了策略:直接用目标扫雷程序的窗口句柄读取内存,绕过了图像识别。但这就意味着只能适配特定版本——我用的是 saolei.ijinshan.com 的经典版,界面渲染方式比较规整,内存结构也容易定位。

最终效果和一些意外发现

整套跑下来,在高级模式(16×30,99雷)的表现:

  • 纯规则引擎:通关率约35%,平均用时8秒
  • 规则+定式:通关率约65%,平均用时5秒
  • 规则+定式+回溯:通关率约90%,平均用时3秒

剩下10%没通的那几局,全是出现了"真·无解"的局面——无论你怎么推,都有两个以上概率相等的选项,只能猜。

另外几个有意思的发现:

  1. 高级扫雷大概5%的局在第一轮点击后就会触发无解局面——程序也无能为力
  2. 角落开局的中奖率(点开一片空地)远比中心开局低
  3. 双击操作带来的速度提升远超任何算法优化——从逐格点击切换到双击,同样推理能力下速度翻倍

代码和游戏

自己试着玩的话:

  • 扫雷客户端:saolei.ijinshan.com,经典三档难度,Win10/11都能用
  • 代码思路参考了扫雷网的 CSolver,感兴趣的可以去看源码

另外提一句,如果你的目标是练逻辑思维而不是竞速,建议关了计时器慢慢推。扫雷最大的乐趣不在于快,在于每一次"我确定这格一定是雷"之后的确认感。

posted @ 2026-07-13 10:37  PC修复电脑医生  阅读(24)  评论(0)    收藏  举报