![352ca3fdb0d7ddfbc0905ae69f87b6dc.png](https://i-blog.csdnimg.cn/blog_migrate/6c06159ff5189985643fba1398f94f6a.png)
目录
- 用Python解数独[0]
- 用Python解数独[1]:求每个单元格的行值域
- 用Python解数独[2]:求列值域和九宫格值域
- 用Python解数独[3]:求总值域
- 用Python解数独[4]:缩减值域
- 用Python解数独[5]:检测唯一值缩减值域
- 用Python解数独[6]:递归获得最终答案
- 用Python解数独[7]:递归(完结篇)
[2][1] 解决数独问题基本思路
7、递归获得最终答案
上一回我们对于值域列表缩减函数进行了改造,增加了检测唯一值的方法,但最终我们依然没有得到答案,还有很多单元格的答案没有确定,应该怎么办呢?
![6a157f48c04066e0b54f066e4788662b.png](https://i-blog.csdnimg.cn/blog_migrate/efe890c1e1f4538acf9a3c9235982291.jpeg)
在当前这种情况下,我们已经无法从数独中直接确定某个单元格的答案了,但是我们可以用试验的办法,去验证某个单元格的答案是值域里的哪一个值。我们以第7行第7列单元格为例,我们假设它的值是1,则这个变化会引起一系列的变化,最终我们得到这个:
![d649d7794e62f66e5c5073fac349ac6f.png](https://i-blog.csdnimg.cn/blog_migrate/84010d5089d3f837e09ad6a84fb6bb19.jpeg)
在第二个九宫格出现了2个7,因此我们可以判断第7行第7列的值不是1,而应该是6。我们通过这种测试验证的方法获得了某个单元格的答案。我们现在需要用代码来实现:
# 主函数,输入值域列表,如遇到多个取值的单元格,依次尝试值域里的每个值,通过递归的方法检测值是否正确
这段代码其实还是挺复杂的,容我细细解读:
# 主函数,输入值域列表,如遇到多个取值的单元格,依次尝试值域里的每个值,通过递归的方法检测值是否正确
- 我们设置i和j两个循环,是为了遍历total_value_range里的每一个元素
- 当len(total_value_range[i][j]) = 1时,也就是说这个单元格是已知单元格,取值已经确定了;如果len(total_value_range[i][j]) > 1,这个单元格是未知单元格,值域列表有多个取值;
- 对于未知单元格,我们遍历它的值域,同时拷贝一份total_value_range,并把值域里的值赋给test_value[i][j],开始进行“试验”,看test_value[i][j]里的哪一个值是正确的;
# 检查行值域列表是否合法
- 赋值之后,我们立即使用之前的generator_soduku()和reduce_totalValueRange()方法,基于已有条件生成一个最新的值域列表;
- 然后我们需要做的是,用soduku_checkRepeat()方法检验当前的值域列表是否合法,soduku_checkRepeat()方法的原理也很简单:
- 首先我们写出一个检查行值域列表是否合法的函数:将一行已知单元格都选出放到一个列表里,检查列表是否有重复值;
- 有了行值域检查函数,只需将数独进行行列转换和九宫格转换然后分别进行检测,如果三项检测均为True,则最后返回True,有一项False,最后返回False
- 如果soduku_checkRepeat()显示当前值域列表合法,则使用sodukuRate()方法检测当前值域列表每个单元格是否都是已知单元格(各单元格值域长度均为1)
- 若每个单元格值域长度均为1,则说明已经得到最终正确答案,则返回test_value,即最终正确答案;
- 若sodukuRate(test_value)不为1,则说明经过一番操作后还未得到正确答案,或者得到错误答案,因此我们将当前的值域列表test_value作为参数,用if判断trial(test_value),这个就用上了递归的概念,我们稍后详细解释;
- 如果soduku_checkRepeat()显示当前值域列表不合法,则说明total_value_range[i][j]当前的取值k不正确,我们continue,继续循环;
- 如果for k in total_value_range[i][j],这个循环结束了,说明所有的取值k都是导向错误的结果(在第一层trial()是不会出现的,会出现在第二层trial()时),则返回False;
最终运行代码,得到了结果
PS
把全部源码展示出来:
import
下一期我们将详细解释这个利用了递归的函数,具体是如何运行的,我们这个用Python解数独栏目也将迎来尾声。
下一篇链接:用Python解数独[7]:递归(完结篇)