Python 中的数独 GUI 与 Tkinter - StringVar 未更新
Sudoku GUI in Python with Tkinter - StringVar not updating
我最近成功地编写了一个使用回溯来解决一个简单的数独游戏的递归代码。我想创建它以便我实时解决难题,即实时更改数字并希望使用 tkinter 模块这样做。我创建了一个 9*9 板,每个数字都作为一个特定的标签,并将标签的文本存储在 StringVar() 中,这样我就可以不断更新它。所有 StringVars 都存储在一个 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 window 上显示的板是未解决的板,而正在打印的板已完全解决。
我希望你能帮我弄清楚为什么这段代码不起作用,我附上了其余代码、一个 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 window.
我认为你需要在 solve_board()
函数的末尾添加 return True
。如果 solve_board()
return True
在 if 块中也立即 return。
由于mainloop()
在solve_board()
为运行时不执行,因此如果想在求解过程中看到更新,需要在设置后调用root.update()
字符串变量:
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
我最近成功地编写了一个使用回溯来解决一个简单的数独游戏的递归代码。我想创建它以便我实时解决难题,即实时更改数字并希望使用 tkinter 模块这样做。我创建了一个 9*9 板,每个数字都作为一个特定的标签,并将标签的文本存储在 StringVar() 中,这样我就可以不断更新它。所有 StringVars 都存储在一个 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 window 上显示的板是未解决的板,而正在打印的板已完全解决。
我希望你能帮我弄清楚为什么这段代码不起作用,我附上了其余代码、一个 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 window.
我认为你需要在 solve_board()
函数的末尾添加 return True
。如果 solve_board()
return True
在 if 块中也立即 return。
由于mainloop()
在solve_board()
为运行时不执行,因此如果想在求解过程中看到更新,需要在设置后调用root.update()
字符串变量:
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