def find_candidates(board, row, col):
# 返回在board[row][col]位置上可以填写的候选数字列表
candidates = set(range(1, 10))
# 排除所在行的数字
candidates -= set(board[row])
# 排除所在列的数字
candidates -= {board[i][col] for i in range(9)}
# 排除所在宫的数字
start_row, start_col = 3 * (row // 3), 3 * (col // 3)
for i in range(3):
for j in range(3):
candidates -= {board[start_row + i][start_col + j]}
return candidates
def solve_sudoku(board):
while True:
solved_any = False
# 先用排除法尝试解决能直接确定的数字
for row in range(9):
for col in range(9):
if board[row][col] == 0: # 只有空位才需要处理
candidates = find_candidates(board, row, col)
if len(candidates) == 1: # 如果只有一个候选数字
board[row][col] = candidates.pop() # 填入该数字
solved_any = True
if not solved_any:
break
# 检查是否已填满
if all(board[i][j] != 0 for i in range(9) for j in range(9)):
return True # 数独已解决
# 如果无法通过排除法直接解决,则使用回溯法
return backtrack_sudoku(board)
def backtrack_sudoku(board):
# 找到下一个空位
empty_spot = find_empty_spot(board)
if not empty_spot:
return True # 数独已解决
row, col = empty_spot
candidates = find_candidates(board, row, col)
for candidate in candidates:
board[row][col] = candidate
# 在当前候选数字基础上继续求解
if backtrack_sudoku(board):
return True # 找到解
board[row][col] = 0 # 回溯
return False # 如果所有候选数字都失败,返回False
def find_empty_spot(board):
# 查找一个空位 (即值为0的格子)
for row in range(9):
for col in range(9):
if board[row][col] == 0:
return (row, col)
return None
def print_board(board):
# 格式化打印数独
for row in board:
print(row)
# 示例数独题
board = [
[2, 0, 0, 0, 0, 4, 9, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0, 0],
[7, 0, 0, 8, 2, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 6, 0, 4, 0],
[0, 8, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 1, 0, 3, 0, 7, 8, 0],
[0, 0, 5, 0, 0, 0, 0, 2, 9],
[1, 7, 2, 0, 0, 0, 4, 0, 0],
[4, 0, 8, 0, 0, 0, 0, 0, 5]
]
if solve_sudoku(board):
print_board(board)
else:
print("No solution exists.")