0.目录
1.介绍
1.介绍
数独是一个非常有趣味性的智力游戏,数独起源于18世纪初瑞士数学家欧拉等人研究的拉丁方阵(Latin Square)。
参与者需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个宫内的数字均含1-9,不重复。
一个数独谜题是由81个方块组成的网格。大部分爱好者把列标为1-9,把行标为A-I,把9个方块的一组(列,行,或者方框)称为一个单元,把处于同一单元的方块称为对等方块。谜题中有些方块是空白的,其他的填入了数字。
每个方块都属于3个单元,有20个对等方块。
当每个单元的方块填入了1到9的一个排列时,谜题就解决了。
本文采用解空间搜索的深度优先搜索(最小代价优先)加约束传播算法来解数独。
代码总体分为五个部分:
1.通用函数
2.全局变量(宏变量)
3.数独预处理(约束传播)
4.解数独(深度优先搜索+最小代价优先)
5.主函数
2.一些通用函数
import time
def cross(A, B):
# 例如:A = 'ABC', B = '123'
# 则返回['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']
return [a+b for a in A for b in B]
def arr_to_dict(A, B):
# 例如:A = ['A', 'B', 'C'], B = ['1', '2', '3']
# 则返回{'A': '1', 'B': '2', 'C': '3'}
return dict(zip(A, B))
def str_to_arr(str_sudoku):
# 传入:str_sudoku = '4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......'
# 返回['4', '.', '.', '.', '.', '.', '8', ... , '.', '.']
return [c for c in str_sudoku if c in cols or c in '0.']
def show_str_sudoku(str_sudoku):
# 解析字符串形式的数独并展示
for i, value in enumerate(str_sudoku):
if i%3 == 0 and i%9 != 0:
print('|', end=' ')
print(value, end=' ')
if (i+1)%9 == 0:
print()
if i == 26 or i == 53:
print('------+-------+------')
def show_dict_sudoku(dict_sudoku):
# 解析字典形式的数独并展示
width = 1 + max(len(dict_sudoku[s]) for s in squares)
line = '+'.join(['-' * (width * 3)] * 3)
for r in rows:
print(''.join(dict_sudoku[r + c].center(width) + ('|' if c in '36' else '') for c in cols))
if r in 'CF': print(line)
print()
cross函数:输出A、B交叉组合而成的字符串
arr_to_dict函数:将数组形式的数独转化为字典形式的数独
str_to_arr函数:将字符串形式的数独转化为数组形式的数独
show_str_sudoku函数:解析字符串形式的数独并显示
show_dict_sudoku函数:解析字典形式的数独并显示
3.全局变量(宏变量)
用Python按如下方式来实现单元、对等方块、方块的概念:
cols = '123456789'
rows = 'ABCDEFGHI'
# squares表示 9*9个元素编号:['A1', 'A2', 'A3', ... , 'I8', 'I9']
squares =