Проблема в том, что я сделал короткий алгоритм, который находит его через лабиринт и отмечает все квадраты, которые он посетил синим цветом. Основная программа работает нормально, но проблема в том, что GUI отображает только лабиринт с посещенными квадратами после завершения всего процесса. Обычно это не проблема, но мне нужно уметь заметно видеть, как алгоритм проходит лабиринт по мере его появления. Проблема в том, что когда я UpdateMaze
функцию UpdateMaze
каждую итерацию алгоритма поиска, она, похоже, не влияет на результат до тех пор, пока весь обход не будет завершен.
import tkinter as tk
from tkinter import *
import time
class MazeGUI():
def __init__(self):
self.maze =[
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
[4, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 4],
[4, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 4],
[4, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 4],
[4, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 4],
[4, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 4],
[4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 4],
[4, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 4],
[4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 4],
[4, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 4],
[4, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 4],
[4, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 4],
[4, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 4],
[4, 0, 1, 2, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 4],
[4, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 4],
[4, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 4],
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
]
self.wall = tk.PhotoImage(file = "MazePiece_Wall.gif")
self.space = tk.PhotoImage(file = "MazePiece_Space.gif")
self.edge = tk.PhotoImage(file = "MazePiece_Outer.gif")
self.visited = tk.PhotoImage(file = "MazePiece_Visited.gif")
self.finish = tk.PhotoImage(file = "MazePiece_Finish.gif")
def UpdateMaze(self):
for y in range(len(self.maze)):
for x in range(len(self.maze[y])):
if self.maze[y][x] == 0:
label = Label(root, image=self.space,
width=20, height=20).grid(row=y, column=x)
elif self.maze[y][x] == 1:
label = Label(root, image=self.wall,
width=20, height=20).grid(row=y, column=x)
elif self.maze[y][x] == 2:
label = Label(root, image=self.finish,
width=20, height=20).grid(row=y, column=x)
elif self.maze[y][x] == 3:
label = Label(root, image=self.visited,
width=20, height=20).grid(row=y, column=x)
elif self.maze[y][x] == 4:
label = Label(root, image=self.edge,
width=20, height=20).grid(row=y, column=x)
def Move(Maze,x,y):
if Maze.maze[y][x] == 2:
return True
elif Maze.maze[y][x] == 1:
return False
elif Maze.maze[y][x] == 3:
return False
elif Maze.maze[y][x] == 4:
return False
Maze.maze[y][x] = 3
if ((x < len(Maze.maze)-1 and Move(Maze,x+1, y))
or (y > 0 and Move(Maze,x, y-1))
or (x > 0 and Move(Maze,x-1, y))
or (y < len(Maze.maze)-1 and Move(Maze,x, y+1))):
return True
return False
root = Tk()
Maze = MazeGUI()
root.lift()
StartPosX = 1
StartPosY = 1
Move(Maze,StartPosX,StartPosY)
Maze.UpdateMaze()
root.mainloop()
Я думаю, что следующее - это то, что показывает основы того, как делать то, что вы хотите. Он использует tkinter
универсальный after()
метода периодически вызывать make_move()
метод, который в конечном итоге вызывает update_maze()
для повторных лабиринтов следующих каждого хода.
Возможно, это не похоже на то, что происходит, но через некоторое время вы увидите, что отображаемый лабиринт изменился. Это непредсказуемо точно, как долго это происходит из-за использования random
модуля, который я представил для генерации того, каким должен быть следующий шаг, поскольку я действительно не понимаю логики для этого в функции Move()
в вашем примере кода. Это то, что, вероятно, понадобится "фиксировать" для taylor, чтобы оно точно для всего, что вы пытаетесь выполнить.
Примечание. Я также изменил свой код, чтобы он больше соответствовал руководству PEP 8 - Style для кода Python в отношении форматирования кода и наименования классов, функций, переменных и т.д., Чтобы сделать его более читаемым (IMO).
from random import randint
import tkinter as tk
from tkinter import *
import time
MOVE_DELAY = 1000 # Time delay between moves in millisec.
class MazeGUI():
SPACE = 0
WALL = 1
FINISH = 2
VISITED = 3
EDGE = 4
def __init__(self):
self.maze = [
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
[4, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 4],
[4, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 4],
[4, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 4],
[4, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 4],
[4, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 4],
[4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 4],
[4, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 4],
[4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 4],
[4, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 4],
[4, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 4],
[4, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 4],
[4, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 4],
[4, 0, 1, 2, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 4],
[4, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 4],
[4, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 4],
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
]
self.wall = tk.PhotoImage(file="MazePiece_Wall.gif") # black
self.space = tk.PhotoImage(file="MazePiece_Space.gif") # white
self.edge = tk.PhotoImage(file="MazePiece_Outer.gif") # red
self.finish = tk.PhotoImage(file="MazePiece_Finish.gif") # green
self.visited = tk.PhotoImage(file="MazePiece_Visited.gif") # blue
self.create_maze()
def create_maze(self):
global root
self.maze_frame = tk.Frame(root)
self.create_maze_labels()
self.maze_frame.pack()
def update_maze(self):
global root
self.maze_frame.grid_forget() # Remove all the existing Labels.
self.create_maze_labels()
self.maze_frame.update_idletasks() # Update display.
def create_maze_labels(self):
for y in range(len(self.maze)):
for x in range(len(self.maze[y])):
if self.maze[y][x] == self.SPACE:
Label(self.maze_frame, image=self.space,
width=20, height=20).grid(row=y, column=x)
elif self.maze[y][x] == self.WALL:
Label(self.maze_frame, image=self.wall,
width=20, height=20).grid(row=y, column=x)
elif self.maze[y][x] == self.FINISH:
Label(self.maze_frame, image=self.finish,
width=20, height=20).grid(row=y, column=x)
elif self.maze[y][x] == self.VISITED:
Label(self.maze_frame, image=self.visited,
width=20, height=20).grid(row=y, column=x)
elif self.maze[y][x] == self.EDGE:
Label(self.maze_frame, image=self.edge,
width=20, height=20).grid(row=y, column=x)
def make_move(self, x, y):
global root
status = self.move(x, y)
# if status: # Not sure what to do with return value...
self.update_maze()
# Select a random adjoining cell (dx & dy both +/-1).
dx, dy = randint(0, 2) - 1, randint(0, 2) - 1
x, y = x+dx, y+dy # Next position.
root.after(MOVE_DELAY, self.make_move, x, y) # Repeat...
def move(self, x, y):
if self.maze[y][x] == self.FINISH:
return True
elif self.maze[y][x] == self.WALL:
return False
elif self.maze[y][x] == self.VISITED:
return False
elif self.maze[y][x] == self.EDGE:
return False
# Spot is empty (self.SPACE).
self.maze[y][x] = self.VISITED
if ((x < len(self.maze)-1 and self.move(x+1, y))
or (y > 0 and self.move(x, y-1))
or (x > 0 and self.move(x-1, y))
or (y < len(self.maze)-1 and self.move(x, y+1))):
return True
return False
root = Tk()
maze = MazeGUI()
start_posx, start_posy = 1, 1
maze.make_move(start_posx, start_posy)
maze.update_maze()
root.mainloop()
PS Для всех, кого это интересует, вот изображения .gif
которые я сделал и использовал для тестирования (чтобы вы могли загрузить их для запуска кода):
MazePiece_Finish.gif
MazePiece_Outer.gif
! MazePiece_Space.gif
MazePiece_Visited.gif
MazePiece_Wall.gif
Move()
приветствуется - теперь оно имеет для меня гораздо больше смысла. Однако код в моем опубликованном ответе на самом деле не делает то, что, как я теперь думаю, вы хотите (то есть для анимации обработки функции). Проблема в том, что функция изменяет содержимое лабиринта только в одном месте, когда выполняетMaze.maze[y][x] = 3
, и делает это только изредка. Я думаю, что вам нужно разработать какой-то анимированный способ показать, что делает его внутренняя логика. Если вы можете сделать это, я смогу обновить мой ответ, если вы не можете понять, как это сделать из существующего кода.