python实现自动解数独小程序

让我来详细讲解“Python实现自动解数独小程序”的完整攻略,这里分为以下几个步骤:

让我来详细讲解“Python实现自动解数独小程序”的完整攻略,这里分为以下几个步骤:

1. 获取数独题目数据

数独题目数据可以从文件中读取或者通过API获取,接下来我们以从文件中获取数独题目数据为例进行讲解。

def read_sudoku(file_path):
    """
    读取数独题目数据
    :param file_path: 文件路径
    :return: 数独数据
    """
    with open(file_path, 'r') as f:
        return [[int(i) for i in line.strip()] for line in f.readlines()]

在这个函数里,首先通过 open() 函数打开文件,并使用 readlines() 方法读取文件内容。然后使用列表推导式将读取到的每一行进行处理,将每个字符转换成整数类型并存入一个列表中,最后将这个列表数据返回。

2. 实现数独的求解算法

数独问题可以使用深度优先搜索(DFS)求解。搜索时从左上角开始,依次向右搜索,当到达一行的末尾时,就跳到下一行的开头,直到所有单元格都被填满为止。在填写单元格时,我们对候选数字逐个尝试。如果当前单元格可以放置一个数字,则递归地尝试填写下一个单元格。如果成功,则返回结果,否则回溯到上一个单元格,重新尝试。

def dfs(sudoku, x, y):
    """
    DFS求解数独
    :param sudoku: 数独数据
    :param x: 当前搜索的行数
    :param y: 当前搜索的列数
    :return: 是否成功
    """
    if y == 9:
        return dfs(sudoku, x + 1, 0)
    if x == 9:
        return True
    if sudoku[x][y] != 0:
        return dfs(sudoku, x, y + 1)

    for i in range(1, 10):
        if check(sudoku, x, y, i):
            sudoku[x][y] = i
            if dfs(sudoku, x, y + 1):
                return True
            sudoku[x][y] = 0
    return False

在这个函数里,我们使用三个变量 xysudoku 分别表示当前搜索到的行数、列数和数独数据。首先判断是否到达数独的右侧或下侧,如果是则回溯到上一个单元格,如果当前单元格不是空格(即已经填过数字),则直接向下搜索。如果当前单元格是空格(即未填数字),我们从 1 到 9 逐个尝试填写当前单元格,如果当前数字可以被填写,则将其填入当前单元格,并递归地尝试填写下一个单元格。如果成功,则返回 True,否则回溯到上一个单元格,重新尝试。

在这个函数中,还需要实现 check() 函数,用于判断当前位置是否可以填写指定数字。这个操作需要分别判断当前行、列、块是否存在重复数字,这里不再赘述。

3. 输出求解结果

def print_sudoku(sudoku):
    """
    打印数独数据
    :param sudoku: 数独数据
    """
    for i in range(9):
        for j in range(9):
            print(sudoku[i][j], end=' ')
            if j % 3 == 2:
                print('|', end=' ')
        print()
        if i % 3 == 2:
            print('-' * 21)

这里的 print_sudoku() 函数用于输出求解之后的数独结果。可以用于调试、展示或者将结果写入文件中等操作。

4. 完整代码

下面是完整的实现代码:

def read_sudoku(file_path):
    """
    读取数独题目数据
    :param file_path: 文件路径
    :return: 数独数据
    """
    with open(file_path, 'r') as f:
        return [[int(i) for i in line.strip()] for line in f.readlines()]


def print_sudoku(sudoku):
    """
    打印数独数据
    :param sudoku: 数独数据
    """
    for i in range(9):
        for j in range(9):
            print(sudoku[i][j], end=' ')
            if j % 3 == 2:
                print('|', end=' ')
        print()
        if i % 3 == 2:
            print('-' * 21)


def check(sudoku, x, y, num):
    """
    判断数独中某个位置是否可以填入指定数字
    :param sudoku: 数独数据
    :param x: 行数
    :param y: 列数
    :param num: 待填数字
    :return: 是否可以填入
    """
    for i in range(9):
        if sudoku[i][y] == num:
            return False
        if sudoku[x][i] == num:
            return False
        if sudoku[(x // 3) * 3 + i // 3][(y // 3) * 3 + i % 3] == num:
            return False
    return True


def dfs(sudoku, x, y):
    """
    DFS求解数独
    :param sudoku: 数独数据
    :param x: 当前搜索的行数
    :param y: 当前搜索的列数
    :return: 是否成功
    """
    if y == 9:
        return dfs(sudoku, x + 1, 0)
    if x == 9:
        return True
    if sudoku[x][y] != 0:
        return dfs(sudoku, x, y + 1)

    for i in range(1, 10):
        if check(sudoku, x, y, i):
            sudoku[x][y] = i
            if dfs(sudoku, x, y + 1):
                return True
            sudoku[x][y] = 0
    return False


if __name__ == '__main__':
    file_path = 'data.txt'
    sudoku = read_sudoku(file_path)

    print_sudoku(sudoku)

    if dfs(sudoku, 0, 0):
        print('Solution:')
        print_sudoku(sudoku)
    else:
        print('Cannot solve!')

5. 示例说明

示例1:从文件中读取数独题目数据

文件 ./data.txt 内容为:

040000600
000430805
900081074
006507028
702060904
830902500
590760040
204848100
007000020
file_path = 'data.txt'
sudoku = read_sudoku(file_path)

可以将以上代码粘贴至 Python 交互式命令行执行,将读取到的数独数据保存在变量 sudoku 中,可以通过 print_sudoku(sudoku) 函数输出读取到的数据。

示例2:求解数独题目并输出解

if dfs(sudoku, 0, 0):
    print('Solution:')
    print_sudoku(sudoku)
else:
    print('Cannot solve!')

以上代码是对数独数据求解的核心操作。将 dfs(sudoku, 0, 0) 的执行结果传递给一个 if 语句进行判断,如果求解成功,则输出 Solution: 和求解结果;如果求解不成功,则输出 Cannot solve!

本文标题为:python实现自动解数独小程序

基础教程推荐