Python 九宫格数独求解

引言

在这篇文章中,我将教你如何使用Python解决九宫格数独问题。这是一个非常经典的数学问题,也是编程中一个很好的练习。首先,让我们来了解一下整个问题的流程。

流程图

我们可以使用下面这个流程图来概述整个解决问题的过程。

erDiagram
    开始 --> 输入数独终盘
    输入数独终盘 --> 初始化
    初始化 --> 解数独
    解数独 --> 输出解答
    输出解答 --> 结束

实现步骤

下面我将详细介绍每个步骤需要做的事情,并提供相关的代码。请注意,这里假设你已经熟悉Python的基础知识。

步骤 1: 输入数独终盘

首先,我们需要输入数独终盘。数独终盘是一个已经填好数字的9x9的矩阵。其中空格用数字0表示。

# 输入数独终盘
board = [
    [5, 3, 0, 0, 7, 0, 0, 0, 0],
    [6, 0, 0, 1, 9, 5, 0, 0, 0],
    [0, 9, 8, 0, 0, 0, 0, 6, 0],
    [8, 0, 0, 0, 6, 0, 0, 0, 3],
    [4, 0, 0, 8, 0, 3, 0, 0, 1],
    [7, 0, 0, 0, 2, 0, 0, 0, 6],
    [0, 6, 0, 0, 0, 0, 2, 8, 0],
    [0, 0, 0, 4, 1, 9, 0, 0, 5],
    [0, 0, 0, 0, 8, 0, 0, 7, 9]
]

步骤 2: 初始化

在解数独之前,我们需要初始化一些变量和数据结构。我们可以使用一个辅助矩阵来记录每个位置是否已经被填入数字。

# 初始化
def init(board):
    rows = [set() for _ in range(9)]  # 记录每行已经出现的数字
    cols = [set() for _ in range(9)]  # 记录每列已经出现的数字
    boxes = [[set() for _ in range(3)] for _ in range(3)]  # 记录每个3x3小方格已经出现的数字
    
    # 遍历数独终盘,将已经填入的数字添加到相应的集合中
    for i in range(9):
        for j in range(9):
            num = board[i][j]
            if num != 0:
                rows[i].add(num)
                cols[j].add(num)
                boxes[i//3][j//3].add(num)
    
    return rows, cols, boxes

rows, cols, boxes = init(board)

步骤 3: 解数独

现在我们来解数独。我们可以使用回溯法来递归地尝试填入数字,直到找到一个解答或者尝试完所有可能的数字。

# 解数独
def solve(board, rows, cols, boxes):
    for i in range(9):
        for j in range(9):
            if board[i][j] == 0:
                for num in range(1, 10):
                    if isValid(board, i, j, num, rows, cols, boxes):
                        board[i][j] = num
                        rows[i].add(num)
                        cols[j].add(num)
                        boxes[i//3][j//3].add(num)
                        
                        if solve(board, rows, cols, boxes):
                            return True
                        
                        # 回溯
                        board[i][j] = 0
                        rows[i].remove(num)
                        cols[j].remove(num)
                        boxes[i//3][j//3].remove