python解数独的思路_用Python解数独[0]

目录

[0] 前言

首先声明阅读本文需要哪些Python基础知识:for循环

if条件判断

列表(list)的基本方法:list.append(), list.remove(), list.count(), list.extend(), len(list)

函数基本概念

具备这些知识就足够了,我们将使用这些“基础知识”,做一个足够“复杂”的项目。

然后需要解释下为什么要用数独项目帮助新手入门:个人原因,我自己很喜欢数独这个游戏,以前也花了很多时间去玩;

数独这个游戏足够纯粹,用一个二维数组就能表示出来,不需要其它任何属性;

解决一个数独问题,过程足够复杂,而用到的Python知识又非常基础;

因此我个人认为数独项目非常适合刚刚掌握Python基础知识的新手,大胆上手练习,仔细学习思考,能帮你建立信心并帮助成长。

现在,我们正式开始吧。

[1] 数独问题

数独的规则很简单,在一个9*9的棋盘上,已经出现了若干个数字(1-9),要求根据已有数字遵照规则求出所有空白地方的数字,规则如下:数字范围是1-9;

每一行数字不能重复;

每一列数字不能重复;

粗实线划分出的9个九宫格,每个九宫格内数字不能重复;

那么我们在解决数独问题时,会遇到如下两种情况:可以根据规则,直接得出某个单元格的答案第9行第4列的单元格,因为第4列已经有8个数字,因此可以直接确定该单元格数字为8第6行第1列的单元格,第6行只剩下数字2和9未出现,而第1列已经出现数字9,因此该单元格数字为2

2. 根据规则无法直接得出答案,只能得到取值范围第1行第1列,根据行判断可能的取值是[2,4,5,6,7],根据列判断可能的取值是[1,2,3,5,6],根据九宫格判断可能的取值是[1,3,4,5,6],综合三个取值,最终取值范围是[5,6]

[2] 数独模型和解决数独方法

[2][0] 用二维数组表示数独

数独可以很直观地用二维数组来表示,所谓二维数组可以简单理解为,数组中的每一个元素依然是一个数组

我们可以用空字符串 '' 来表示空白单元格,有数字的单元格在对应位置填上数字即可,类似于这样

soduku = [[] for i in range(9)]

soduku[0] = ['',8,9,1,'',3,'','','']

soduku[1] = ['',2,7,4,'','',8,'','']

soduku[2] = ['','','',5,2,'','','','']

soduku[3] = ['',7,6,9,'','',5,'',8]

soduku[4] = [8,'',3,6,'',1,2,'','']

soduku[5] = ['',4,5,3,8,7,1,6,'']

soduku[6] = [7,'',8,2,1,4,3,9,5]

soduku[7] = [9,3,1,7,6,5,4,'',2]

soduku[8] = [4,'',2,'','',9,'','',6]

如果看不懂

soduku = [[] for i in range(9)]

其实就是

soduku = []

for i in range(9):

soduku.append([])

或者是

soduku = [[],[],[],[],[],[],[],[],[]]

[2][1] 解决数独问题基本思路

经过简单的分析,我们其实已经总结出解决数独问题的方法:根据单元格所处的行、列、九宫格,分别计算出单元格的行值域、列值域和九宫格值域;(所谓值域,就是指该单元格的取值范围)

3个值域求交集,得到单元格最终的值域;

那么如何用代码实现以上的基本思路呢,不要着急,我们梳理一下需要做哪些事情:求每个单元格的行值域

只有该行的数字会影响到单元格的行值域,因此求数独每个单元格的行值域,可以简化为求每一行每个单元格的行值域,也就是把相同的事情重复做9次就好了。

如何求一行每个单元格的行值域呢,比如第一行是

soduku[0] = ['',8,9,1,'',3,'','','']

直观地去看,其实第一行空白单元格的行值域,就是这一行未出现数字的集合,即[2,4,5,6,7],每个单元格的行值域都是[2,4,5,6,7]。代码实现思路也就很明显了,数字全集是[1,2,3,4,5,6,7,8,9],这一行里出现了哪些数字,我们就从全集里去除这些数字,最后剩下数字组成的数组就是这一行每个单元格的行值域。

row = ['',8,9,1,'',3,'','','']

row_value_range = list(range(1,10)) # range(1,10)并不是列表类型,因此需要用list()方法转化为列表

for i in row:

if i == '': # 不要忘记数组中还有空单元格

continue

else:

row_value_range.remove(i)

改写为函数

row = ['',8,9,1,'',3,'','','']

def valueRange(row):

row_value_range = list(range(1,10))

for i in row:

if i == '':

continue

else:

row_value_range.remove(i)

return row_value_range

print(valueRange(row))

PS D:\python\0624-soduku> python test7.py

[2, 4, 5, 6, 7]

但是有一个问题,其实我们希望得到的输出是

[[2, 4, 5, 6, 7],8,9,1,[2, 4, 5, 6, 7],3,[2, 4, 5, 6, 7],[2, 4, 5, 6, 7],[2, 4, 5, 6, 7]]

为了保持元素的统一,即数组内元素都是数组(而不是数组和数字掺杂),应该得到如下输出

[[2, 4, 5, 6, 7],[8],[9],[1],[2, 4, 5, 6, 7],[3],[2, 4, 5, 6, 7],[2, 4, 5, 6, 7],[2, 4, 5, 6, 7]]

那么我们的行值域函数还需要继续改进

row = ['',8,9,1,'',3,'','','']

def valueRange(row):

temp = copy.deepcopy(row)

row_value_range = list(range(1,10))

for i in row:

if i == '':

continue

else:

row_value_range.remove(i)

for j in temp:

if j == '':

j = row_value_range

else:

j = [j]

return temp

看起来代码逻辑很合理,然后执行之后发现

PS D:\python\0624-soduku> python test5.py

['', 8, 9, 1, '', 3, '', '', '']

哦?为什么没有任何变化???

预知后事如何,且听下回分解

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值