Python技术迷

破世界纪录了!用Python实现自动扫雷!

前阵子闲着无聊,晚上十二点多刷视频的时候看到有人用 AI 来玩扫雷,速度飞快。我那时候就想:这玩意我能不能自己撸一个?想着想着就把笔记本打开了,结果越写越上头,第二天早上四点才睡,搞出了一个自动扫雷脚本。 最神奇的是,跑起来之后我都愣了:这速度比网上那些“世界纪录”级别的都快。

不是因为我有多强,而是扫雷这种游戏——只要算法靠谱、鼠标点得快,你玩得再好都不可能比程序快。

事情是怎么开始的?

电脑桌面那个经典的扫雷图标其实我已经几年没点了。真正开始写是在某个晚上,我朋友突然问:“你不是搞 Python 吗?扫雷你能自动玩吗?”

我嘴上说:“应该不难吧。” 心里想的是:好像还真能搞。

扫雷逻辑简单:

  • 无雷格子会显示数字
  • 数字代表周围 8 个格子里的雷数
  • 如果你能推算周围哪些是雷,就能把剩下的安全格点开

所以核心任务只有两个:

  1. 让 Python 识别格子的数字

  2. 让 Python 推断雷的位置并自动点击

听起来是不是挺简单? 实际上做起来也确实不复杂,但细节特别多。

第一步:截图 + 识别数字

我用的是 Python 搭配 OpenCV。 扫雷的界面非常规则,每个格子大小一致,所以我直接让程序不断截图,然后切出每个格子的小图片,丢给模板匹配(template matching)。

最早我傻乎乎地用 OCR,结果效果感人。 扫雷的数字那么小,OCR 根本识别不准。

后来改成模板匹配,小图直接对比,大大提高准确率。

示例代码大概长这样:

import cv2
import numpy as np
import pyautogui

# 加载数字模板
templates = {
    i: cv2.imread(f"./tpl/{i}.png", 0)
for i in range(1, 8)
}

defcapture_board():
    screenshot = pyautogui.screenshot()
    img = cv2.cvtColor(np.array(screenshot), cv2.COLOR_BGR2GRAY)
return img

defmatch_number(cell_img):
    best = (0, None)
for n, tpl in templates.items():
        res = cv2.matchTemplate(cell_img, tpl, cv2.TM_CCOEFF_NORMED)
        score = res.max()
if score > best[0]:
            best = (score, n)
return best[1] if best[0] > 0.7elseNone

数字识别这块调了好久,各种缩放、对比度、锐化都试过,最后解决方式特别憨憨:按固定尺寸截图 + 固定模板匹配扫雷画面不变,这招反而最稳定。

第二步:根据数字推算雷的位置

扫雷规则其实可以拆成一堆简单的约束:

如果一个格子的数字是 1,且周围只有一个未知格,那未知格就是雷。

如果数字是 2,周围有两个未知格,也同理。

所以核心就是扫描棋盘,找每个数字格,统计它周围:

  • 未翻开格子数
  • 已标雷的格子数

然后判断还能不能推断。

示例逻辑:

defsolve(board):
    actions = []
for r in range(rows):
for c in range(cols):
            num = board[r][c]
if num in range(1, 8):
                around = get_neighbors(board, r, c)
                unopen = [p for p in around if p.value == "unknown"]
                flags = [p for p in around if p.value == "flag"]

# 标记雷
if len(flags) + len(unopen) == num and len(unopen) > 0:
for p in unopen:
                        actions.append(("flag", p.r, p.c))

# 点安全格
if len(flags) == num and len(unopen) > 0:
for p in unopen:
                        actions.append(("open", p.r, p.c))
return actions

其实核心算法就是硬推理,不用什么 AI、深度学习,扫雷游戏本质就是个确定性谜题。

第三步:自动操作鼠标

扫雷窗口固定位置,鼠标点击也很容易。

defclick_cell(row, col, button="left"):
    x = board_x + col * cell_w + cell_w//2
    y = board_y + row * cell_h + cell_h//2
    pyautogui.click(x, y, button=button)

刚开始我把点击速度设得很慢,怕出错。 后来把延迟调到几乎没有,结果鼠标飞一样点。

第一次跑起来的时候我人都傻了:扫雷在屏幕上像一个抖腿的机器人一样高速闪烁。

随机十遍专家模式(Expert Mode),最快一局直接给我干到 0.18 秒。 这是那种人眼根本看不清“发生了什么”的速度。

我当时都怀疑是不是程序没玩、直接点的某个通关按钮。 后来把整个过程录屏下来才相信它真的玩了。

网上公开最快纪录基本都是 0.x 秒 ~ 1.x 秒而我的这个……嗯,不能说世界第一,但绝对是“能和世界纪录平起平坐”的那种级别。

做完之后我才发现的几个坑

  1. 扫雷界面缩放会导致模板匹配失败

如果 Windows 缩放不是 100% 就会炸。

  1. 偶发的“猜雷”局面无法解决

扫雷本来就存在无法逻辑推断,只能赌概率的局面。 我的脚本遇到这种情况会选择概率最大的格子,但偶尔也会踩雷。

  1. 鼠标太快会触发系统保护

尤其在一些笔记本上,连续点击过快会被系统吞掉一些事件。

做完之后,我朋友说:“你做这个有啥用?”

我说:“用处?没有。但爽。”

其实就像很多程序员捣鼓的奇怪脚本一样:不是因为它有用,是因为我能搞出来。

如果你也想玩,这类自动化脚本真的特别适合作为 Python + OpenCV 的入门练习。

-END-

我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领