import numpy # 导入numpy库,用于创建和操作二维数组
class Sudoku(object): # 定义一个数独类
def __init__(self): # 初始化方法
self.data = numpy.empty((9, 9), int) # 创建一个空的9x9数组,作为数独的数据
self.n = 0 # 创建一个变量n,用于记录当前填充的空白单元格的索引
def input_sudoku(self): # 定义一个输入数独的方法
"""输入完整的数独"""
for index in range(9): # 遍历每一行
while True: # 循环直到输入有效
list_nums = list(input(f'请输入第{index + 1}行:')) # 让用户输入一行的数字,转换为列表
# 输入合理性检查
if len(list_nums) == 9: # 如果输入的长度为9,说明有效
self.data[index, :] = list_nums # 把输入的数字赋值给对应的行
break # 跳出循环
else: # 如果输入的长度不为9,说明无效
print('数字长度不正确...') # 提示用户重新输入
def get_suitable_nums(self, index: tuple): # 定义一个得到可以填入的数字的方法
"""
得到可以填入的数字
:param index: 位置索引,形如(1,2)
:return: 可以填入的数字列表
"""
# 获得该行的全部数字
set_1 = set(self.data[index[0], :]) # 把该行的数字转换为集合,去除重复元素
# 获得该列的全部数字
set_2 = set(self.data[:, index[1]]) # 把该列的数字转换为集合,去除重复元素
# 获得九宫格里的数
list_3 = [] # 创建一个空列表,用于存放九宫格里的数
x, y = ((index[0] // 3) * 3, (index[1] // 3) * 3) # 计算九宫格左上角单元格的坐标
for row in [x, x + 1, x + 2]: # 遍历九宫格所在的三行
for column in [y, y + 1, y + 2]: # 遍历九宫格所在的三列
list_3.append(self.data[row, column]) # 把九宫格里的数添加到列表中
set_3 = set(list_3) # 把列表转换为集合,去除重复元素
return list(set(range(1, 10)) - (set_1 | set_2 | set_3)) # 返回1到9中除了已经出现过的数以外的数
def solve(self): # 定义一个解决数独谜题的方法
"""使用回溯法得出解"""
list_1 = numpy.argwhere(self.data == 0) # 找出所有空白单元格的索引,存放在一个列表中
def func1(n): # 定义一个递归函数,用于填充空白单元格
if n == len(list_1): # 如果已经填满所有空白单元格,说明找到了解
print(self.data)
return True
nums = self.get_suitable_nums(list_1[n]) # 得到可以填入当前位置的数字列表
if not nums: # 如果没有可以填入的数字,说明当前路径不可行,返回False
return False
for num in nums: # 遍历每个可行的数字
self.data[tuple(list_1[n])] = num # 填入数字
if func1(n + 1): # 对下一个空白单元格递归调用,如果返回True,说明找到了解,返回True
return True
self.data[tuple(list_1[n])] = 0 # 如果遍历完所有数字都没有找到解,说明当前路径不可行,恢复原值,返回False
return False
if not func1(0): # 对第一个空白单元格调用递归函数,如果返回False,说明无解
print("无解")
if __name__ == '__main__': # 如果是直接运行这个文件
sudoku = Sudoku() # 创建一个数独类的实例
sudoku.input_sudoku() # 调用输入数独的方法
sudoku.solve() # 调用解决数独的方法
输入数独的格式:000560505,其中0代表空的格子