Python笔记03-数独求解问题

这里使用暴力的方法来求解数独,把1-9的依次填入空格,只要合乎规则就填入该数,并且寻找下一个空格,然后重复上一步,如果发现1-9都不合乎规则,则回到上一步,对填的数进行修改,如果还是不行,则退回上上一步,以此类推。
所以如果用类来做的话,这个类至少有三种方法,填入方法的方法,检查是否合格的方法,还有寻找下一个的方法。
大致结构:

class Sudoku:
    def __init__(self,board_sudoku):
    #二维列表,这里x表示的是第几排,y表示的是第几列,用0代表空格
        self.b = board_sudoku
    def try_it(self):
        pass
    def check(self):
        pass
    def next_one(self):
        pass

先写check:
按照数独规则,需要检测三步:1.横向,2.纵向,3.小九宫格。
这里需要传入三个参数x,y,value,前者两个是坐标值,后一个是填入值。
直接上代码:

def check(self,x,y,value):
    for i in range(0,9):#扫描横向有无重复值
        if value == self.b[x][i]:
            return False
    for j in range(0,9):#扫描纵向有无重复值
        if value == self.b[j][y]:
            return False
    #计算当前xy坐标处于哪一个小九宫格
    row_num = x // 3 * 3
    col_num = y // 3 * 3
    #分行取出小九宫格
    block = self.b[row_num][col_num:col_num + 3] + self.b[row_num + 1][col_num:col_num + 3] + self.b[row_num + 2][col_num:col_num + 3]
    for k in block:
        if value == k :
            return False
    #False表示有重复值不能填入,True表示这个数值ok可以填入
    return True

再就是next_one,需要x,y两个参数
代码如下:

def next_one(self,x,y):
#首先在本行寻找下一个为0的值,有则返回,无则去下一行
    for next_y1 in range(y+1,9):
        if self.b[x][next_y1] == 0:
            return x,next_y1
    for next_x in range(x+1,9):
        for next_y2 in range(0,9):
            if self.b[next_x][next_y2] == 0:
                return next_x,next_y2
    #如果找不到,说明填满了,这也意味着这个数独解开了            
    return -1,-1#其实只要不是0-8,随便返回啥都行。

然后再是填入方法了,思路就是for循环填入1-9,如果通过check检查就调用next_one方法寻找下一个,然后再填,直到找不到下一个为止。上代码:

def try_it(self,x,y):
    if self.b[x][y] == 0:
        for i in range(1,10):
            if self.check(x,y,i):
                self.b[x][y] = i
                next_x,next_y = self.next_one(x,y)
                if next_x == -1:
                #第一个出口
                    return True
                else:
                    end = self.try_it(next_x,next_y)
                    #找不到第一个出口,说明填错了,得回去重新填写。
                    if not end :
                        self.b[x][y] = 0
                    else:
                    #第二个出口
                        return True

最后是运行段:

def go(self):
#第一个为空值,就从第一个开始,否则找到下一个空值在开始
    if self.b[0][0] == 0:
        self.try_it(0,0)
    else:
        x,y = self.next_one(0,0)
        self.try_it(x,y)
    for i in self.b:
        print(i)

全部代码:

class Suku(object) :
    def __init__(self,broad):
        self.b = broad
    def check(self,x,y,value):
        for i in range(0,9):
            if value == self.b[x][i]:
                return False
        for j in range(0,9):
            if value == self.b[j][y]:
                return False
        row_num = x // 3 * 3
        col_num = y // 3 * 3
        block = self.b[row_num][col_num:col_num + 3] + self.b[row_num + 1][col_num:col_num + 3] + self.b[row_num + 2][col_num:col_num + 3]
        for k in block:
            if value == k :
                return False
        return True
    def next_one(self,x,y):
        for next_y1 in range(y+1,9):
            if self.b[x][next_y1] == 0:
                return x,next_y1
        for next_x in range(x+1,9):
            for next_y2 in range(0,9):
                if self.b[next_x][next_y2] == 0:
                    return next_x,next_y2
        return -1,-1
    def try_it(self,x,y):
        if self.b[x][y] == 0:
            for i in range(1,10):
                if self.check(x,y,i):
                    self.b[x][y] = i
                    next_x,next_y = self.next_one(x,y)
                    if next_x == -1:
                        return True
                    else:
                        end = self.try_it(next_x,next_y)
                        if not end :
                            self.b[x][y] = 0
                        else:
                            return True
    def go(self):
        if self.b[0][0] == 0:
            self.try_it(0,0)
        else:
            x,y = self.next_one(0,0)
            self.try_it(x,y)
        for i in self.b:
            print(i)
b = [[0,4,0,0,0,7,1,0,0],
         [5,3,0,0,9,0,0,7,0],
         [0,0,7,0,6,0,9,4,0],
         [4,0,6,0,8,0,7,5,1],
         [0,1,0,0,0,0,6,9,0],
         [0,5,3,0,1,0,0,0,2],
         [9,6,0,0,3,0,0,1,0],
         [3,7,0,0,5,1,0,0,0],
         [1,0,0,2,0,9,3,6,7]]
s = Suku(b)
s.go()

结果:
[6, 4, 9, 5, 2, 7, 1, 3, 8]
[5, 3, 1, 8, 9, 4, 2, 7, 6]
[8, 2, 7, 1, 6, 3, 9, 4, 5]
[4, 9, 6, 3, 8, 2, 7, 5, 1]
[2, 1, 8, 4, 7, 5, 6, 9, 3]
[7, 5, 3, 9, 1, 6, 4, 8, 2]
[9, 6, 2, 7, 3, 8, 5, 1, 4]
[3, 7, 4, 6, 5, 1, 8, 2, 9]
[1, 8, 5, 2, 4, 9, 3, 6, 7]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值