简体   繁体   English

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

[英]Sudoku GUI in Python with Tkinter - StringVar not updating

I recently successfully wrote a recursive code that uses backtracking to solve a simple sudoku puzzle.我最近成功编写了一个递归代码,它使用回溯来解决一个简单的数独难题。 I want to create it so that I solved the puzzle live, ie with the numbers changing in real-time and wanted to do so using the tkinter module.我想创建它,以便我实时解决难题,即数字实时变化,并希望使用 tkinter 模块这样做。 I created a 9*9 board with each number as a particular label and stored the text of the label in a StringVar() so I could update it continuously.我创建了一个 9*9 板,每个数字作为特定的 label 并将 label 的文本存储在 StringVar() 中,以便我可以不断更新它。 All the StringVars were stored in a 9*9 array(called textvars) so that they corresponded to the original sudoku board I wanted to solve, and I could thus use the row and column number to update the text.所有的 StringVars 都存储在一个 9*9 数组(称为 textvars)中,因此它们对应于我想要解决的原始数独板,因此我可以使用行号和列号来更新文本。 The following is the code for this part:以下是这部分的代码:

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)

These text variables and boards were passed to a solve_board() function which used backtracking and when updating the board, it updated the text alongside using the.set() function, like so:这些文本变量和板被传递给使用回溯的solve_board() function,当更新板时,它使用.set() function更新了文本,如下所示:

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))

All the bits that are not gui or tkinter related work perfectly, although they were typed in a hurry leading to less than optimal code.所有不是 gui 或 tkinter 相关的位都可以完美地工作,尽管它们是匆忙输入的,导致代码不是最优的。

When this code is run, the board displayed on the tkinter window is the unsolved board while the board being printed is fully solved.运行此代码时,tkinter window 上显示的板是未解决的板,而正在打印的板已完全解决。

I hope you could help me figure out as to why this code is not working and I have attached the rest of the code, an is_valid function and a main one below for further reference.我希望你能帮助我弄清楚为什么这段代码不起作用,我附上了代码的 rest、is_valid function 和下面的主要代码以供进一步参考。 Thank you.谢谢你。

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()

EDIT:编辑:

The code:编码:

board[rowno][colno]=0
textvars[rowno][colno].set('')

This is used to reflect the backtracking process, ie if a choice made is incorrect, the program goes back to the last time it made a choice and it resets the choice by setting it to 0. Setting the text to '' is simply to reflect the reset made my the program in the tkinter window.这用于反映回溯过程,即如果做出的选择不正确,则程序会返回上次做出选择的时间,并将选择设置为 0 来重置选择。将文本设置为 '' 只是为了反映重置使我的程序在 tkinter window 中。

I think you need to return True at the end of solve_board() function.我认为您需要在solve_board() function 的末尾返回True Also return at once if solve_board() return True in the if block.如果solve_board()在if 块中返回True ,也立即返回。

Since mainloop() is not executed when solve_board() is running, therefore if you want to see the update during solving, you need to call root.update() after setting the StringVar:由于在solve_board()运行时solve_board() mainloop()被执行,因此如果想在求解过程中看到更新,需要在设置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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM