使用python解决数独问题的实例

这是一个使用Python编写的数独求解器,通过定义一个Sudoku类来处理数独数据。类包含了输入数独、检查输入合理性、获取可填数字以及使用回溯法求解的方法。程序首先从用户那里接收9x9的数独矩阵,然后通过递归回溯策略尝试填满所有空白单元格,找到解决方案。
摘要由CSDN通过智能技术生成
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代表空的格子

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值