个人项目-数独(Python实现)——从解数独到写游戏

0.项目

项目地址:https://github.com/John-zjm/suduku
GUI地址:https://github.com/John-zjm/sudoku_Gui


1.需求分析

需求分析

1.生成终局 格式:sudoku.exe -c n
1)不重复
2)1<=n<=1000000,能处理非法参数
4)n在1000以内时,要求程序在 60 s 内给出结果
5)输出生成的数独终盘至sudoku.txt
2. 求解数独 格式:sudoku.exe -s path
1)从指定文件读取,每读81个数字视作一道数独题,忽略其他字符
2)要求文件内的数独题目是合法的
3)文件内数独个数在1000以内时,要求程序在 60 s 内给出结果
4)输出已读入数独的答案至sudoku.txt。若存在未满81个的数字,在已解出的答案后输出“存在错误格式!”


2.解题思路

  • 我主要把项目分为三部分:
    • 输入部分
    • 生成数独终局
    • 解数独

在写界面的时,只要稍作修改就可以使用后两部分。

  • 详细描述一下这三个部分:

    • 输入略过,有Python的异常处理很好写

    • 生成数独终局用的是行列变换法。数独中间的九宫格经过行列变换可以变换为2!×3!×3!×2!×3!×3!=5184(因为固定左上角为5)。这样我需要生成1000000/5184=192个九宫格就够了,而正中九宫格有8!=40320个足够满足要求。

    • 解数独我主要参考了《数独求解的候选数优化算法设计》这篇论文,运用了显性候选数规则、隐性候选数规则、九宫格交叉排除规则。Python的numpy可以很好的对数组进行计算。在进行dfs时,我对候选数进行了估值,具体是(10-候选个数) + 同行确定数字个数 + 同列确实数字个数


3.设计实现

  • 输入处理类:
    根据参数调用下列函数进行相应处理(包括参数合法性判断)
  • 终盘生成类:
    种子生成函数、交换组合函数、行列交换函数、转换输出函数
  • 数独求解类:
    初始化函数、记录函数函数、检错函数、恢复函数、深度优先遍历函数、评价函数、减少候选数函数。

这里写图片描述
单元测试:
“错误参数”:

sudoku.exe -c 20
sudoku.exe -c 1000000
sudoku.exe -s C:\Users\0\OneDrive\1.txt
sudoku.exe -s C:\
sudoku.exe -p asd

“错误数独”

sudo=[[1,2,3,4,5,6,7,8,9]for row in range(9)]
sudo=[[0 for col in range(9)]for row in range(9)] 
sudo =[[8,0,0, 0,0,0, 0,0,0]
    [0,0,3, 6,0,0, 0,0,0]
    [0,7,0, 0,9,0, 2,0,0]
    [0,5,0, 0,0,7, 0,0,0]
    [0,0,0, 0,4,5, 7,0,0]
    [0,0,0, 1,0,0, 0,3,0]
    [0,0,1, 0,0,0, 0,6,8]
    [0,0,8, 5,0,0, 0,1,0]
    [0,9,0, 0,0,0, 4,0,0]]

4.性能改进

  • 把输出改为一次输出,输入改为一次读入,多次处理。
  • 在回溯时,用估值函数,让价值大的候选数先进循环
  • 在界面中,把检测数独从全部检测,改为对修改数的所在行,所在列,所在九宫格进行检测。

生成数独
解数独
由图可以看出combine()和check_one_possible()消耗较大

def combine(self, c1, c2, c3, r1, r2, r3):
        self.table = deepcopy(self.temp)
        if (c1 == 1):
            self.colExchange(1, 2)
        
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值