from sudoku.config.game_setting import Settings
from tkinter import *
import copy
import random
class ShuduGame:
def __init__(self, init_metrix):
self.setting = Settings()
self.window = Tk()
self.window.title(self.setting.screen_title)
self.window.geometry(self.setting.screen_size)
# init_metrix是数字表示的初始化矩阵
self.init_metrix = copy.deepcopy(init_metrix)
# run_metrix是运行太矩阵
self.run_metrix = copy.deepcopy(init_metrix)
# 当前矩阵,和图形上一一对应
self.cur_metrix = copy.deepcopy(init_metrix)
# self.va_list是字符变量表示的矩阵
self.va_metrix = [[StringVar() for i in range(9)] for j in range(9)]
self.num_to_val(init_metrix)
# 棋盘
self.e_list = [[None for i in range(9)] for j in range(9)]
self.val_to_screen(self.va_metrix)
# 棋盘是否合法判断标志
self.board_valid = StringVar()
# 添加按钮
self.add_button()
self.hardship = 50
self.answer = []
self.window.mainloop()
def num_to_val(self, metrix):
for i in range(9):
for j in range(9):
if metrix[i][j] == 0:
self.va_metrix[i][j].set('')
else:
self.va_metrix[i][j].set(str(metrix[i][j]))
def val_to_screen(self, val):
for i in range(9):
for j in range(9):
x = 60 * j
y = 60 * i
if val[i][j].get():
color = 'red'
else:
color = 'white'
self.e_list[i][j] = Entry(self.window, textvariable=val[i][j], justify='center',
font=('Arial', 16), bg=color)
self.e_list[i][j].place(x=x, y=y, width=60, height=60)
def set_hardship(self, intensity):
self.hardship = intensity
def add_button(self):
show_valid = Label(self.window, textvariable=self.board_valid, bg='blue', font=('Arial', 14), width=12,
height=5)
show_valid.place(x=640, y=0)
# 添加检查button,在窗口界面设置放置Button按键,注意默认不执行的话,需要lambda
b_check = Button(self.window, text='check', font=('Arial', 12), width=6, height=1,
command=lambda: self.check_valid_totle())
b_check.place(x=0, y=561)
# 添加检查button,在窗口界面设置放置Button按键,注意默认不执行的话,需要lambda
b_run = Button(self.window, text='run', font=('Arial', 12), width=6, height=1,
command=lambda: self.run_shudu())
b_run.place(x=120, y=561)
b_init = Button(self.window, text='自定义', font=('Arial', 12), width=6, height=1,
command=lambda: self.usr_define())
b_init.place(x=0, y=601)
b_random = Button(self.window, text='随机生成', font=('Arial', 12), width=8, height=1,
command=lambda: self.random_shudu())
b_random.place(x=120, y=601)
s_hardship = Scale(self.window, label='空格个数', from_=25, to=62, orient=HORIZONTAL, length=400, showvalue=1,
tickinterval=2, resolution=1, command=self.set_hardship)
s_hardship.set(42)
s_hardship.place(x=0, y=641)
def num_from_board(self):
metrix = [[0 for i in range(9)] for j in range(9)]
for i in range(9):
for j in range(9):
if self.va_metrix[i][j].get() == "":
metrix[i][j] = 0
else:
metrix[i][j] = int(self.va_metrix[i][j].get())
return metrix
def check_1_to_9(self, nums):
for i in range(1, 10):
if i not in nums:
return False
return True
def check_valid_totle(self):
self.cur_metrix = self.num_from_board()
for i in range(9):
# 检查行
temp = []
for j in range(9):
temp.append(self.cur_metrix[i][j])
if not self.check_1_to_9(temp):
self.board_valid.set("invalid")
return
# 检查列
temp = []
for j in range(9):
temp.append(self.cur_metrix[j][i])
if not self.check_1_to_9(temp):
self.board_valid.set("invalid")
return
# 检查宫
temp = []
hang = i // 3
lie = i % 3
for j in [3 * hang, 3 * hang + 1, 3 * hang + 2]:
for k in [3 * lie, 3 * lie + 1, 3 * lie + 2]:
temp.append(self.cur_metrix[j][k])
if not self.check_1_to_9(temp):
self.board_valid.set("invalid")
return
self.board_valid.set("valid")
def run_shudu(self):
def put_index(index):
# 存在两个答案了就不需要再做了
if len(self.answer) > 1:
return
if index > 80:
self.answer.append(copy.deepcopy(self.run_metrix))
self.num_to_val(self.run_metrix)
return
indexi = index // 9
indexj = index % 9
if self.init_metrix[indexi][indexj]:
put_index(index + 1)
else:
for i in range(1, 10):
self.run_metrix[indexi][indexj] = i
# 如果第i个通过,填写第i+1个
if self.check_valid(indexi, indexj):
put_index(index + 1)
# 1-9都不行就复位返回上层
self.run_metrix[indexi][indexj] = 0
return
return
self.answer = []
self.init_metrix = self.num_from_board()
self.cur_metrix = copy.deepcopy(self.init_metrix)
self.run_metrix = copy.deepcopy(self.init_metrix)
self.num_to_val(self.init_metrix)
self.val_to_screen(self.va_metrix)
put_index(0)
def check_valid(self, indexi, indexj):
if self.run_metrix[indexi][indexj] > 9 or self.run_metrix[indexi][indexj] < 1:
return False
for i in range(9):
# 检查行,同行是否还有相同元素
if i != indexj and self.run_metrix[indexi][i] == self.run_metrix[indexi][indexj]:
return False
# 检查列
if i != indexi and self.run_metrix[i][indexj] == self.run_metrix[indexi][indexj]:
return False
# 检查宫
gong_indexi_begin = indexi // 3 * 3
gong_indexj_begin = indexj // 3 * 3
for i in [gong_indexi_begin, gong_indexi_begin + 1, gong_indexi_begin + 2]:
for j in [gong_indexj_begin, gong_indexj_begin + 1, gong_indexj_begin + 2]:
if i != indexi and j != indexj and self.run_metrix[i][j] == self.run_metrix[indexi][indexj]:
return False
return True
def usr_define(self):
self.answer = []
self.init_metrix = self.num_from_board()
self.cur_metrix = copy.deepcopy(self.init_metrix)
self.run_metrix = copy.deepcopy(self.init_metrix)
self.num_to_val(self.init_metrix)
self.val_to_screen(self.va_metrix)
def random_shudu(self):
# 随机生成数独的原则:
# 1.已知一个数独答案
# 2.将任意两个同宫的行或者列进行交换,也是一个数独答案
# 3.这样的交换进行随机次
# 4.在这个随机答案中扣除随机hard_ship个空格,hard_ship是进度条长度
random_init = [[7, 6, 1, 9, 3, 4, 8, 2, 5],
[3, 5, 4, 6, 2, 8, 1, 9, 7],
[9, 2, 8, 1, 5, 7, 6, 3, 4],
[2, 1, 9, 5, 4, 6, 3, 7, 8],
[4, 8