这里使用暴力的方法来求解数独,把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]