整个解数独问题可以大致分为3个部分:
- 从图片中提取出完整的数独
- 从数独中提取出数字并传入神经网络进行预测
- 解出数独【本文的部分】
【环境】
- Python:3.8.5
- OpenCV:4.5.1
- Keras:2.4.3
【第三部分】解数独:
1.首先是 possible 函数,检验数字 n 是否能填在 (y,x) 位置,即每行、每列、每个 9 宫格是否有重复,重复则返回 False,否则返回 True
2.然后是 solve 函数,遍历数独中所有的 0,如果 1-9 当中有数字能填进去,则问题的规模减一,调用 solve 函数本身继续求解,如果 1-9 当中没有数字能填进去,则回溯,最终返回数独的解。
import numpy as np
# 检验数字 n 是否能填在(y,x)位置
def possible(sudoku, y, x, n):
for i in range(9):
if sudoku[y][i] == n:
return False
for i in range(9):
if sudoku[i][x] == n:
return False
x0 = (x // 3) * 3
y0 = (y // 3) * 3
for i in range(3):
for j in range(3):
if sudoku[y0 + i][x0 + j] == n:
return False
return True
# 解数独
def solve(sudoku):
for y in range(9):
for x in range(9):
if sudoku[y][x] == 0:
for n in range(1, 10):
if possible(sudoku, y, x, n):
sudoku[y][x] = n
solved = solve(sudoku)
if solved is not None:
return solved
sudoku[y][x] = 0
return
return sudoku
# 测试
grid = [[0, 6, 0, 7, 0, 9, 0, 4, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 7, 4, 0, 0, 9, 0, 8],
[3, 0, 0, 0, 0, 0, 5, 0, 4],
[0, 4, 0, 0, 0, 0, 0, 9, 0],
[1, 0, 9, 0, 0, 0, 0, 0, 2],
[8, 0, 1, 0, 0, 4, 7, 0, 0],
[0, 0, 0, 0, 2, 0, 0, 0, 0],
[0, 2, 0, 9, 0, 6, 0, 5, 0]]
print(np.matrix(solve(grid)))
【第三部分总结】
本文中的解数独程序比较简单粗暴,适用于一般的数独问题,并且稍加修改后可以输出数独的所有解,不过时间复杂度高,在遇到非常难的数独问题时,会出现递归层数太多解不出来的情况。
【源码】
【GitHub链接】:GitHub - ITACHI142857/SudokuSolving: sudoku solver using python\opencv\deep learning