Судоку GUI в Python с Tkinter - StringVar не обновляется - PullRequest
0 голосов
/ 18 апреля 2020

Недавно я успешно написал рекурсивный код, который использует возврат для решения простой головоломки судоку. Я хочу создать его так, чтобы я решил головоломку вживую, то есть с изменением чисел в реальном времени, и хотел сделать это с помощью модуля 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, является нерешенной, в то время как печатная плата полностью решена.

Надеюсь, вы могли бы помочь мне выяснить, почему этот код не работает, и я приложил остальную часть кода, функцию 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.

1 Ответ

0 голосов
/ 18 апреля 2020

Я думаю, вам нужно вернуть True в конце solve_board() функции. Также верните сразу, если solve_board() верните True в блоке if.

Так как 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
...