带有Tkinter的Python中的数独GUI-StringVar未更新

问题描述 投票:0回答:1

我最近成功编写了一个递归代码,该代码使用回溯来解决一个简单的数独难题。我想创建它以便实时解决难题,即实时更改数字,并希望使用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窗口中。

python user-interface tkinter tk sudoku
1个回答
0
投票

我认为您需要在True函数的结尾处返回solve_board()。如果solve_board()在if块中返回True,也请立即返回。

由于mainloop()运行时未执行solve_board(),因此,如果要在求解过程中查看更新,则需要在设置StringVar之后调用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
© www.soinside.com 2019 - 2024. All rights reserved.