总体逻辑为:从行列上去寻找非重复值,直到找到一个可选的唯一值,重复遍历找到最终的确认结果。
import math
class sudoku():
def __init__(self, sudo_list):
self.sudo_list = sudo_list
self.init_range = set([x for x in range(1, 10)])
def _init_list(self):
self.sudo_list_bak = [[0 for x in range(9)] for y in [0 for x in range(9)]]
for row in range(9):
for column in range(9):
bak_dict = {}
bak_dict['value'] = self.sudo_list[row][column]
block = (math.floor(row / 3) + 1, math.floor(column / 3) + 1)
bak_dict["row"] = row
bak_dict["column"] = column
bak_dict["block"] = block
self.sudo_list_bak[row][column] = bak_dict
for row in range(9):
for column in range(9):
current_dict = self.sudo_list_bak[row][column]
# print(row,column,current_dict)
if current_dict['value'] == 0:
current_dict['bakvalue'] = self.init_range.copy()
current_dict['bakvalue'] = self._getback_value(current_dict['row'], current_dict['column'],
current_dict['block'])
def _getback_value(self, row, column, block):
row_value = self._getback_row_value(row)
column_value = self._getback_column_value(column)
block_value = self._getback_block_value(row, column)
return row_value.intersection(column_value, block_value)
def _getback_row_value(self, row):
exists_value_list = [i["value"] for i in self.sudo_list_bak[row]]
row_value = self.init_range.copy()
for i in exists_value_list:
row_value.discard(i)
return row_value
def _getback_column_value(self, column):
exists_value_list = [i[column]["value"] for i in self.sudo_list_bak]
column_value = self.init_range.copy()
for i in exists_value_list:
column_value.discard(i)
return column_value
def _getback_block_value(self, row, block):
exists_value_list = []
for x in self.sudo_list_bak:
for y in x:
if y["block"] == block:
y['value'].append(exists_value_list)
block_value = self.init_range.copy()
for i in exists_value_list:
block_value.discard(i)
return block_value
def compli_judge(self):
for x in self.sudo_list_bak:
for y in x:
if y['value'] == 0:
return True
return False
def loop(self):
a = 0
while self.compli_judge():
for x in self.sudo_list_bak:
for y in x:
if y['value'] == 0 and len(y['bakvalue']) == 1:
y['value'] = list(y['bakvalue'])[0]
y.pop('bakvalue')
for x_new in self.sudo_list_bak:
for y_new in x_new:
if y_new['value'] == 0 and (
y_new['row'] == y['row'] or y_new['column'] == y['column'] or y_new['block'] ==
y[
"block"]):
y_new['bakvalue'].discard(y['value'])
a += 1
if a == 10:
print('10次以上循环退出')
break
def result(self):
self._init_list()
self.loop()
for x in range(9):
for y in range(9):
self.sudo_list[x][y] = self.sudo_list_bak[x][y]['value']
return self.sudo_list
def result(self):
return self.sudo_list
if __name__ == '__main__':
sudolist = [
[5, 0, 2, 4, 0, 0, 9, 0, 1],
[0, 6, 0, 0, 0, 1, 2, 0, 0],
[0, 9, 0, 0, 0, 0, 7, 8, 3],
[0, 0, 0, 0, 8, 4, 0, 3, 9],
[0, 0, 0, 1, 2, 7, 0, 0, 5],
[4, 8, 0, 5, 9, 0, 6, 0, 7],
[2, 0, 6, 0, 1, 5, 3, 9, 8],
[0, 1, 3, 0, 0, 2, 5, 7, 0],
[0, 0, 7, 0, 0, 0, 4, 0, 0]
]
sudo = sudoku(sudolist)
reuslt_list = sudo.result()
for x in range(9):
if x % 3 == 0:
print("—" * 21)
for y in range(9):
if y % 3 == 0:
print("|", end="")
print(reuslt_list[x][y], end=" ")
print("")
print("—" * 21)