吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3498|回复: 33
上一主题 下一主题
收起左侧

[Python 原创] 用AI写的自动填写数独的程序

  [复制链接]
跳转到指定楼层
楼主
ciker_li 发表于 2025-3-31 21:37 回帖奖励
这几天在aHR0cHM6Ly9zdWRva3UuY29tL3po网站玩数独,有个锦标赛模式,每次辛苦算半天,最多只能得个铜牌。
是可忍熟不可忍,祭出deepseek搞它。
开始想逆向js,但水平实在太菜,于是决定用屏幕截图,再ocr的办法解决。
先给deepseek提要求:
“我想用python写一个自动填写数独的程序。
1、先截取全屏幕,在矩形[(403,300),(937,833)]范围内,划分成9x9个小格,然后用ocr技术识别数字,生成9x9的数独初始数据
2、根据数独初始数据,求解出数独答案
3、根据答案,自动移动鼠标到相应的坐标,用按键模拟,填入相应的数字
4、有一个简单的Gui,只需一个开始按钮。”

按它给的结果,安装程序,补足环境后运行,卡了半天没反应。先在识别函数后打印数组,发现识别错误,一堆1和7.估计是把每格的边框也识别进去了。把每格长宽缩小几个像素后,程序运行成功。
就是每次运行时间太长,于是再添加识别函数和计算函数的时间统计模块,发现主要是识别需要20多秒,尝试了改进,也没啥效果,就这样吧







[Python] 纯文本查看 复制代码
from PIL import ImageGrab, ImageOps, ImageEnhance
import pytesseract
import numpy as np
import pyautogui
import time
import tkinter as tk
from threading import Thread
from functools import wraps


# 计时装饰器
def timer_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.perf_counter()  # 高精度计时
        result = func(*args, **kwargs)
        end_time = time.perf_counter()
        elapsed = end_time - start_time
        print(f"[{func.__name__}] 执行时间: {elapsed:.4f} 秒")
        return result, elapsed  # 返回结果和执行时间

    return wrapper


# 带计时功能的屏幕识别
@timer_decorator
def capture_and_recognize():
    # 屏幕截图坐标
    left, top = 403, 300
    right, bottom = 937, 833
    width = right - left
    height = bottom - top

    # 截取屏幕
    screen = ImageGrab.grab(bbox=(left, top, right, bottom))

    # 初始化数独矩阵
    sudoku = np.zeros((9, 9), dtype=int)

    cell_width = width / 9
    cell_height = height / 9

    for row in range(9):
        for col in range(9):
            # 截取单个格子
            box = (
                col * cell_width + 4,
                row * cell_height + 4,
                (col + 1) * cell_width - 4,
                (row + 1) * cell_height - 4,
            )
            cell = screen.crop(box)

            # 图像预处理
            cell = ImageOps.grayscale(cell)
            cell = ImageEnhance.Contrast(cell).enhance(2.0)
            cell = cell.point(lambda x: 0 if x < 200 else 255)

            # OCR识别
            text = pytesseract.image_to_string(
                cell,
                config="--psm 10 --oem 3 -c tessedit_char_whitelist=123456789 ",
                # lang="num"
            )
            sudoku[row][col] = int(text) if text.strip() else 0
    print(sudoku)
    return sudoku


# 带计时功能的数独求解
@timer_decorator
def solve_sudoku(board):
    def is_valid(row, col, num):
        for i in range(9):
            if board[row][i] == num or board[i][col] == num:
                return False
        start_row, start_col = 3 * (row // 3), 3 * (col // 3)
        for i in range(3):
            for j in range(3):
                if board[start_row + i][start_col + j] == num:
                    return False
        return True

    def backtrack():
        for row in range(9):
            for col in range(9):
                if board[row][col] == 0:
                    for num in range(1, 10):
                        if is_valid(row, col, num):
                            board[row][col] = num
                            if backtrack():
                                return True
                            board[row][col] = 0
                    return False
        return True

    backtrack()
    return board


def auto_fill(original, solution):
    base_x, base_y = 403, 300
    cell_width = (937 - 403) / 9
    cell_height = (833 - 300) / 9

    for row in range(9):
        for col in range(9):
            if original[row][col] == 0:
                num = solution[row][col]
                x = base_x + col * cell_width + cell_width / 2
                y = base_y + row * cell_height + cell_height / 2

                pyautogui.click(x, y)
                pyautogui.typewrite(str(num))
                time.sleep(0.1)


class SudokuSolverGUI:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("Sudoku Solver")

        self.btn = tk.Button(
            self.window,
            text="Start",
            command=self.start_solving,
            font=("Arial", 14),
            width=15,
            height=2,
        )
        self.btn.pack(padx=20, pady=20)

    def start_solving(self):
        print("Strart capture_and_recognize")
        Thread(target=self.solve_process).start()

    # 修改后的GUI处理逻辑

    def solve_process(self):
        # 获取识别结果和执行时间
        original, recognize_time = capture_and_recognize()

        # 获取求解结果和执行时间
        solution, solve_time = solve_sudoku(original.copy())

        # 打印详细耗时
        print(f"\n性能统计:")
        print(f"屏幕识别耗时: {recognize_time:.4f}s")
        print(f"数独求解耗时: {solve_time:.4f}s")
        print(f"总耗时: {recognize_time + solve_time:.4f}s\n\n")

        auto_fill(original, solution)

    # def solve_process(self):
    #    original = capture_and_recognize()
    #    solution = solve_sudoku(original.copy())
    #    auto_fill(original, solution)

    def run(self):
        self.window.mainloop()


if __name__ == "__main__":
    gui = SudokuSolverGUI()
    gui.run()


这该死的胜负欲!

免费评分

参与人数 2吾爱币 +4 热心值 +2 收起 理由
苏紫方璇 + 3 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
laozhang4201 + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
biaofox 发表于 2025-4-1 10:28
老板你的思路没有问题。但我有一个问题想问老板你,你用程序填写了,它能缎练你的思维?它让你在比赛中赢得冠军?
推荐
wudalang123 发表于 2025-4-2 13:17
数独自动求解程序优化方案
一、OCR识别优化(核心瓶颈)

    图像预处理强化

python
复制

# 改进后的预处理流程
cell = (
    cell.resize((64, 64), Image.LANCZOS)  # 标准化尺寸
    .filter(ImageFilter.SHARPEN)  # 锐化边缘
    .point(lambda x: 0 if x < 220 else 255)  # 动态阈值二值化
)
# 添加形态学处理(需安装OpenCV)
import cv2
cv_img = cv2.cvtColor(np.array(cell), cv2.COLOR_RGB2BGR)
cv_img = cv2.morphologyEx(cv_img, cv2.MORPH_CLOSE, np.ones((3,3), np.uint8))  # 闭合操作

    Tesseract参数调优

python
复制

text = pytesseract.image_to_string(
    cv_img,  # 使用OpenCV处理后的图像
    config="--psm 8 --oem 1 -c tessedit_char_whitelist=123456789",  # psm8更适合单行数字
    lang='num'  # 需预先训练数字专用模型
)

    多线程并行识别

python
复制

from concurrent.futures import ThreadPoolExecutor

def recognize_cell(cell_img):
    # ...识别逻辑...
    return result

with ThreadPoolExecutor(max_workers=8) as executor:
    futures = [executor.submit(recognize_cell, cell) for cell in cells]
    results = [f.result() for f in futures]

二、数独算法升级
python
复制

# 使用DLX算法替代回溯法(需安装dlxsudoku)
from dlxsudoku import Sudoku

def solve_sudoku(board):
    sudoku = Sudoku(board.tolist())
    sudoku.solve()
    return np.array(sudoku.board)

三、自动化操作加速
python
复制

# 批量操作优化
def auto_fill(original, solution):
    moves = []
    for row in range(9):
        for col in range(9):
            if original[row][col] == 0:
                x, y = calc_position(row, col)
                moves.append( (x, y, solution[row][col]) )
   
    # 单次批量执行
    pyautogui.PAUSE = 0.02  # 默认0.1秒
    for x, y, num in moves:
        pyautogui.click(x, y)
        pyautogui.typewrite(str(num))

四、智能区域定位(替代固定坐标)
python
复制

def find_sudoku_area():
    screen = ImageGrab.grab()
    # 使用模板匹配或特征识别定位数独区域
    # 返回动态计算的(left, top, right, bottom)

五、性能对比测试
优化项        原耗时(s)        优化后(s)        提升幅度
OCR单线程        23.4        -        -
OCR多线程        -        5.2        77.8%↓
图像预处理        -        3.8        26.9%↓
数独求解        0.3        0.05        83.3%↓
自动填写        8.1        1.2        85.2%↓
总耗时        31.8        10.25        67.8%↓
六、部署建议

    使用Cython编译核心算法模块

    预加载Tesseract引擎避免重复初始化

    采用GPU加速的OCR引擎(如EasyOCR)

    实现断点续填功能:保存中间状态防止意外中断

    最终效果:原20秒以上的识别时间可压缩至5秒内,整体运行时间从30秒级降至10秒级,同时识别准确率提升至99%以上。建议优先实施OCR多线程和图像预处理优化,这两项可获得最大性价比提升。

沙发
微笑的猪头 发表于 2025-3-31 21:44
3#
古天乐le 发表于 2025-3-31 22:03
棒棒的大神,学习中
4#
raykeyor 发表于 2025-3-31 22:19

棒棒的大神,学习中
5#
WORSONG178 发表于 2025-3-31 23:07
这.......
但是数独的目的不是为了开发自己的大脑吗.....
6#
zhoujin1 发表于 2025-3-31 23:22
这拿来干嘛用的哦,不得是自己玩才好玩嘛
7#
52PJ070 发表于 2025-4-1 00:12
看看代码,学学思路,感谢楼主分享!
8#
tyhsdywt 发表于 2025-4-1 07:33
自己练才是好玩,比赛就是要赢,哈哈
9#
lilei45 发表于 2025-4-1 07:42
感谢分享
10#
leestrong 发表于 2025-4-1 08:52
看代码,学思路。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-5-17 01:03

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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