python - 带有 Tkinter 的 Python 中的数独 GUI - StringVar 未更新
问题描述
我最近成功编写了一个递归代码,它使用回溯来解决一个简单的数独难题。我想创建它,以便我实时解决难题,即数字实时变化,并希望使用 tkinter 模块来实现。我创建了一个 9*9 的板,每个数字作为一个特定的标签,并将标签的文本存储在 StringVar() 中,这样我就可以不断更新它。所有的 StringVar 都存储在一个 9*9 数组(称为 textvars)中,因此它们对应于我想要解决的原始数独板,因此我可以使用行号和列号来更新文本。以下是这部分的代码:
def main():
textvars = []
t1 = []
board = [[3, 0, 6, 5, 0, 8, 4, 0, 0],
[5, 2, 0, 0, 0, 0, 0, 0, 0],
[0, 8, 7, 0, 0, 0, 0, 3, 1],
[0, 0, 3, 0, 1, 0, 0, 8, 0],
[9, 0, 0, 8, 6, 3, 0, 0, 5],
[0, 5, 0, 0, 9, 0, 6, 0, 0],
[1, 3, 0, 0, 0, 0, 2, 5, 0],
[0, 0, 0, 0, 0, 0, 0, 7, 4],
[0, 0, 5, 2, 0, 6, 3, 0, 0]]
for i in range(9):
t1 = []
for j in range(9):
txt = StringVar()
if board[i][j]==0:
txt.set('')
else:
txt.set(str(board[i][j]))
Label(root,height = 2, width = 4, textvariable = txt, relief = "solid").grid(row = i, column = j)
t1.append(txt)
textvars.append(t1)
solve_board(board, textvars)
这些文本变量和板被传递给使用回溯的 solve_board() 函数,当更新板时,它使用 .set() 函数更新文本,如下所示:
def solve_board(board,textvars):
for rowno in range(9):
for colno in range(9):
if board[rowno][colno] == 0:
for i in range(1,10):
if (is_valid(board,rowno,colno,i)):
board[rowno][colno]=i
textvars[rowno][colno].set(str(i))
solve_board(board,textvars)
board[rowno][colno]=0
textvars[rowno][colno].set('')
return False
print (np.matrix(board))
所有与 gui 或 tkinter 无关的位都可以完美地工作,尽管它们是匆忙输入的,导致代码不是最优的。
运行此代码时,tkinter 窗口上显示的板是未解决的板,而正在打印的板已完全解决。
我希望你能帮助我弄清楚为什么这段代码不起作用,我已经附上了其余的代码,一个 is_valid 函数和一个主要的函数,以供进一步参考。谢谢你。
def is_valid(b,r,c,n): #check if number insertion is valid
if n in b[r]: #if in row
return False
for x in range(0,9):
if n == b[x][c]: #check for column
return False
sr = r - r%3
sc = c - c%3
for x in range(sr,sr+3):
for y in range(sc,sc+3):
if b[x][y]==n:
return False
return True
if __name__ == "__main__":
root = Tk()
root.title("Sudoku")
main()
root.mainloop()
编辑:
编码:
board[rowno][colno]=0
textvars[rowno][colno].set('')
这用于反映回溯过程,即如果做出的选择不正确,则程序会返回上次做出选择的时间,并将选择设置为 0 来重置选择。将文本设置为 '' 只是为了反映重置使我的程序出现在 tkinter 窗口中。
解决方案
我认为您需要在函数True
结束时返回。如果在 if 块中返回solve_board()
,也立即返回。solve_board()
True
由于在运行mainloop()
时不执行solve_board()
,因此如果想在求解过程中看到更新,需要root.update()
在设置好StringVar后调用:
def solve_board(board, textvars):
for rowno in range(9):
for colno in range(9):
if board[rowno][colno] == 0:
for i in range(1, 10):
if is_valid(board, rowno, colno, i):
board[rowno][colno] = i
textvars[rowno][colno].set(str(i))
root.update()
if solve_board(board, textvars):
return True
board[rowno][colno] = 0
textvars[rowno][colno].set('')
root.update()
return False
print(np.matrix(board))
return True
推荐阅读
- sql - 如何从 wordpress 中的这个对象数组中检索我的值
- javascript - 在javascript中清除div
- node.js - 使用 Mongoose(MongoDB) 实现 post('updateOne') 钩子中间件
- svelte - 生命周期商店
- mysql - 导入产品时出现 Opencart DB 错误
- python - 循环 hbar 图时,条的长度是恒定的,而不是 x 刻度标签
- javascript - 同一页面中的多个滑翔机与 wordpress 中的 glider.js
- c - 如何在c中的文件上写入文本?
- mongodb - $lookup 查找由 id 匹配的对象数组
- google-analytics - Google Analytics 4 / 每个事件具有多个值的自定义维度