checkpoint: Graphics now draws paths

Move the path drawing functionality to the Graphics class. The Cell
class no longer needs to reference an instance of the Graphics class.
This commit is contained in:
Dan Anglin 2024-02-18 02:21:09 +00:00
parent 429990d12e
commit 9bb23b6c6d
Signed by: dananglin
GPG key ID: 0C1D44CFBEE68638
4 changed files with 48 additions and 43 deletions

21
app.py
View file

@ -11,11 +11,13 @@ class App(Tk):
self.title("Maze Solver") self.title("Maze Solver")
# Position the window to the centre of the screen # Position the window to the centre of the screen
# screen_width = self._root.winfo_screenwidth() height = 800
# screen_height = self._root.winfo_screenheight() width = 1000
# centre_x = int(screen_width/2 - width/2) screen_width = self.winfo_screenwidth()
# centre_y = int(screen_height/2 - height/2) screen_height = self.winfo_screenheight()
# self._root.geometry(f"{width}x{height}+{centre_x}+{centre_y}") centre_x = int(screen_width/2 - width/2)
centre_y = int(screen_height/2 - height/2)
self.geometry(f"{width}x{height}+{centre_x}+{centre_y}")
# Styling # Styling
self.style = ttk.Style() self.style = ttk.Style()
@ -41,6 +43,11 @@ class App(Tk):
self.solver = Solver(self.maze) self.solver = Solver(self.maze)
self.algorithm_map = {
"Breadth-First Search": self.solver.solve_with_dfs_r,
"Depth-First Search": self.solver.solve_with_bfs_r,
}
self.side_panel = self._create_side_panel() self.side_panel = self._create_side_panel()
self.side_panel.grid(column=0, row=0) self.side_panel.grid(column=0, row=0)
@ -74,6 +81,10 @@ class App(Tk):
solve = ttk.Button( solve = ttk.Button(
frame, frame,
text="Solve the maze", text="Solve the maze",
command=lambda: self.solver.solve(
solve_method=self.algorithm_map[algorithm.get()],
enable_random_direction=randomness.get(),
),
) )
solve.pack() solve.pack()
return frame return frame

32
cell.py
View file

@ -27,6 +27,9 @@ class CellWall:
self._line_colour = "black" self._line_colour = "black"
def configure(self, build: bool) -> None: def configure(self, build: bool) -> None:
"""
builds or destroys the cell wall.
"""
if build: if build:
self._build_wall() self._build_wall()
else: else:
@ -71,7 +74,6 @@ class Cell:
self, self,
x1: int, y1: int, x1: int, y1: int,
x2: int, y2: int, x2: int, y2: int,
graphics=None,
) -> None: ) -> None:
# Validation # Validation
if (x2 < x1) or (y2 < y1): if (x2 < x1) or (y2 < y1):
@ -101,8 +103,6 @@ class Cell:
centre_y = y1 + ((y2 - y1) / 2) centre_y = y1 + ((y2 - y1) / 2)
self._centre = Point(centre_x, centre_y) self._centre = Point(centre_x, centre_y)
self._graphics = graphics
self._visited: Dict[str, bool] = { self._visited: Dict[str, bool] = {
"generator": False, "generator": False,
"solver": False, "solver": False,
@ -143,29 +143,6 @@ class Cell:
) )
return self._walls[wall].wall_up() return self._walls[wall].wall_up()
def draw(self) -> None:
"""
draw draws the cell onto the canvas
"""
if not self._graphics:
return
self._graphics.draw_cell_walls(self._walls)
def draw_move(self, to_cell: 'Cell', undo: bool = False) -> None:
"""
draw_move draws a path between the centre of this cell and
the centre of the given cell.
"""
if not self._graphics:
return
fill_colour = "red"
if undo:
fill_colour = "grey"
line = Line(self.centre(), to_cell.centre())
self._graphics.draw_line(line, fill_colour)
def was_visited_by(self, visitor: str) -> bool: def was_visited_by(self, visitor: str) -> bool:
""" """
returns True if the cell was visited by the returns True if the cell was visited by the
@ -183,3 +160,6 @@ class Cell:
if visitor not in ("solver", "generator"): if visitor not in ("solver", "generator"):
raise ValueError(f"This is an unknown visitor ({visitor})") raise ValueError(f"This is an unknown visitor ({visitor})")
self._visited[visitor] = True self._visited[visitor] = True
def get_walls(self) -> Dict[CellWallLabels, CellWall]:
return self._walls

View file

@ -1,6 +1,7 @@
from typing import Dict from typing import Dict
from time import sleep
from tkinter import Canvas from tkinter import Canvas
from line import Line from line import Line, Point
from cell import CellWallLabels, CellWall from cell import CellWallLabels, CellWall
@ -13,14 +14,15 @@ class Graphics(Canvas):
height=height, height=height,
) )
def redraw(self) -> None: def _redraw(self) -> None:
""" """
redraw redraws all the graphics in the window. redraw redraws all the graphics in the window.
""" """
self.update_idletasks() self.update_idletasks()
self.update() self.update()
sleep(0.05)
def draw_line( def _draw_line(
self, self,
line: Line, line: Line,
fill_colour: str = "black", fill_colour: str = "black",
@ -41,7 +43,25 @@ class Graphics(Canvas):
draws the walls of a cell onto the canvas. draws the walls of a cell onto the canvas.
""" """
for label in CellWallLabels: for label in CellWallLabels:
self.draw_line( self._draw_line(
line=walls[label].get_line(), line=walls[label].get_line(),
fill_colour=walls[label].get_line_colour(), fill_colour=walls[label].get_line_colour(),
) )
self._redraw()
def draw_path(
self,
from_cell_centre: Point,
to_cell_centre: Point,
undo: bool = False
) -> None:
"""
draws a path between the centre of this cell and
the centre of the given cell.
"""
line = Line(from_cell_centre, to_cell_centre)
fill_colour = "red"
if undo:
fill_colour = "grey"
self._draw_line(line, fill_colour)
self._redraw()

10
maze.py
View file

@ -1,5 +1,4 @@
from typing import List from typing import List
from time import sleep
import random import random
from enum import Enum from enum import Enum
from graphics import Graphics from graphics import Graphics
@ -153,7 +152,6 @@ class Maze:
cursor_y, cursor_y,
(cursor_x + self._cell_width), (cursor_x + self._cell_width),
(cursor_y + self._cell_height), (cursor_y + self._cell_height),
self._graphics,
) )
cells[j] = cell cells[j] = cell
if j == self._width - 1: if j == self._width - 1:
@ -283,18 +281,14 @@ class Maze:
draws the cells in an animated way. draws the cells in an animated way.
""" """
self._cell_grid[i][j].draw() self._graphics.draw_cell_walls(self._cell_grid[i][j].get_walls())
self._graphics.redraw()
sleep(0.05)
def _draw_path(self, current_cell: Cell, next_cell: Cell, undo: bool = False) -> None: def _draw_path(self, current_cell: Cell, next_cell: Cell, undo: bool = False) -> None:
""" """
draws a path between two cells in an animated way. draws a path between two cells in an animated way.
""" """
current_cell.draw_move(next_cell, undo) self._graphics.draw_path(current_cell.centre(), next_cell.centre(), undo)
#self._canvas.redraw()
#sleep(0.05)
def mark_cell_as_visited(self, i: int, j: int, visitor: str) -> None: def mark_cell_as_visited(self, i: int, j: int, visitor: str) -> None:
""" """