专栏名称: 编程派
Python程序员都在看的公众号,跟着编程派一起学习Python,看最新国外教程和资源!
目录
相关文章推荐
小小的python学习社  ·  Python爬虫入门详细教程,通俗易懂,看一 ... ·  6 小时前  
Python爱好者社区  ·  DeepSeek梁文锋实习往事曝光!月薪1. ... ·  2 天前  
Python爱好者社区  ·  清华大学104页《DeepSeek入门到精通 ... ·  昨天  
小小的python学习社  ·  【2025版附安装包】超详细Python+P ... ·  2 天前  
小小的python学习社  ·  【2025版附安装包】超详细Python+P ... ·  2 天前  
Python中文社区  ·  量化交易复盘:如何用这套简单的TSI+EMA ... ·  3 天前  
51好读  ›  专栏  ›  编程派

【Python破解九宫格数独】:九宫格生成与数独求解

编程派  · 公众号  · Python  · 2017-04-20 11:34

正文

作者:冰不语

来源:「CVPy」公众号

前言

在此之前, OpenCV玩九宫格数独(一) OpenCV玩九宫格数独(二) 分别介绍了如何从九宫格图片中提取出已知数字和如何用knn训练数字识别模型。在这些前期工作都已经完成的基础上,接下来我们需要做什么呢?

我们要做的有三部分:

1.生成九宫格,也就是生成一个9x9的矩阵,把已知的数字按照图片中的位置填到矩阵中的相应位置,其他位置全部置0。

2.编写数独求解算法,对九宫格矩阵进行求解。

3.把填完的九宫格重新填充到图片中去。

我们仍然是一步一步来说。

生成九宫格

这里就需要用到我们之前两篇的内容了,生成九宫格的步骤如下:

1.从九宫格图片中提取数字(第一篇内容)

2.用训练的数字识别模型对上一步的数字进行识别。

这里需要注意的是,提取之后的数字,要按照训练模型之前的数据处理方式进行处理,然后输入knn模型识别。识别效果如下图所示。就像上一篇结尾说的一样,本文用不到一百个样本训练出来的模型仅仅能保证在本文的示例图片上取得完美效果。其他情况下不作保证。如果想要得到更完美的数字识别模型,请优化数据预处理方式和加大数据量。

3.按照位置顺序把数字填入相应的矩阵位置中。

矩阵初始化为零阵

  1. soduko = np.zeros((9, 9),np.int32)

然后按照位置求解数字在矩阵中所处的位置

  1. ## 求在矩阵中的位置    

  2. soduko[int(y/box_h)][int(x/box_w)] = number

得到的矩阵如下所示:

跟上面的图片比较一下,是不是位置一样呢?

编写算法求解九宫格矩阵

数独的求解算法有很多种,热爱数独的且热爱数学的人对此进行了深入研究,提出了各种各样的算法。这里用的是传说中的回溯法。回溯法具体内容感兴趣的可以自行搜索,我这里只是用,没有深究。

至于为什么用这个算法?。。。因为我在stackoverflow上找到了可用的代码(捂脸逃...)

代码里标注了出处:

  1. ## 数独求解算法,回溯法。来源见下面链接,有细微改动。

  2. ## http://stackoverflow.com/questions/1697334/algorithm-for-solving-sudoku

  3. def findNextCellToFill(grid, i, j):

  4.    for x in range(i,9):

  5.        for y in range(j,9):

  6.             if grid[x][y] == 0:

  7.                return x,y

  8.    for x in range(0,9):

  9.        for y in range(0,9):

  10.            if grid[x][y] == 0:

  11.                return x,y

  12.    return -1,-1

  13. def isValid(grid, i, j, e):

  14.    rowOk = all([e != grid[i][x] for x in range(9)])

  15.    if rowOk:

  16.        columnOk = all([e != grid[x][j] for x in range (9)])

  17.        if columnOk:

  18.            # finding the top left x,y co-ordinates of the section containing the i,j cell

  19.            secTopX, secTopY = 3 *int(i/3), 3 *int(j/3)

  20.            for x in range(secTopX, secTopX+3):

  21.                for y in range(secTopY, secTopY+3):

  22.                    if grid[x][y] == e:

  23.                        return False

  24.                return True

  25.    return False

  26. def solveSudoku(grid, i=0, j=0):

  27.    i,j = findNextCellToFill(grid, i, j)

  28.    if i == -1:

  29.        return True

  30.    for e in range(1,10):

  31.        if isValid(grid,i,j,e):

  32.            grid[i][j] = e

  33.            if solveSudoku(grid, i, j):

  34.                return True

  35.            # Undo the current cell for backtracking

  36.            grid [i][j] = 0

  37.    return False

然后我们根据算法对前面生成的数独求解。只需要这么一句就行:

solveSudoku ( soduko )

这里为了便于观察,分别 原始数独 求解后的数独 ,为了验算,输出结果数独的每行每列的和,如果求解正确,每行每列和都应该等于 1 + 2 +...+ 9 = 45

  1. print("\n生成的数独\n")

  2. print(soduko)

  3. print("\n求解后的数独\n")

  4. ## 数独求解

  5. solveSudoku(soduko)

  6. print(soduko)

  7. print("\n验算:求每行每列的和\n")

  8. row_sum = map(sum,soduko)

  9. col_sum







请到「今天看啥」查看全文