maze-solver/cell.py

178 lines
5 KiB
Python
Raw Normal View History

2024-02-13 21:13:15 +00:00
from typing import Dict
from graphics import Window, Point, Line
class CellWall:
"""
A CellWall represents the existence (or non-existence) of
a Cell's wall.
"""
def __init__(self, line: Line, window: Window) -> None:
self.exists = True
self.line = line
self._window = window
def draw(self):
fill_colour = self._window.cell_grid_colour
if not self.exists:
fill_colour = self._window.background_colour
self._window.draw_line(self.line, fill_colour=fill_colour)
class Cell:
"""
A Cell represents a grid on the maze.
"""
2024-02-13 21:13:15 +00:00
TOP_WALL = 0
BOTTOM_WALL = 1
LEFT_WALL = 2
RIGHT_WALL = 4
def __init__(
self,
x1: int, y1: int,
x2: int, y2: int,
window: Window = None,
) -> None:
# Validation
if (x2 < x1) or (y2 < y1):
raise CellInvalidError(x1, y1, x2, y2)
if (x2 - x1) < 2:
raise CellTooSmallError("horizontal", x2-x1)
if (y2 - y1) < 2:
raise CellTooSmallError("vertical", y2-y1)
# Define the cell walls
top_wall = Line(Point(x1, y1), Point(x2, y1))
bottom_wall = Line(Point(x1, y2), Point(x2, y2))
left_wall = Line(Point(x1, y1), Point(x1, y2))
right_wall = Line(Point(x2, y1), Point(x2, y2))
2024-02-13 21:13:15 +00:00
self._walls: Dict[int, CellWall] = {
Cell.TOP_WALL: CellWall(top_wall, window),
Cell.BOTTOM_WALL: CellWall(bottom_wall, window),
Cell.LEFT_WALL: CellWall(left_wall, window),
Cell.RIGHT_WALL: CellWall(right_wall, window),
2024-02-13 21:13:15 +00:00
}
# Calculate the cell's central point
centre_x = x1 + ((x2 - x1) / 2)
centre_y = y1 + ((y2 - y1) / 2)
self._centre = Point(centre_x, centre_y)
# A reference to the root Window class for drawing purposes.
self._window = window
self.visited = False
def configure_walls(
self,
top: bool = True,
bottom: bool = True,
left: bool = True,
right: bool = True,
) -> None:
"""
configure_walls configures the existence of the Cell's walls.
"""
2024-02-13 21:13:15 +00:00
self._walls[Cell.TOP_WALL].exists = top
self._walls[Cell.BOTTOM_WALL].exists = bottom
self._walls[Cell.LEFT_WALL].exists = left
self._walls[Cell.RIGHT_WALL].exists = right
def centre(self) -> Point:
"""
centre returns the Cell's central point
"""
return self._centre
2024-02-13 21:13:15 +00:00
def wall_exists(self, wall: int) -> bool:
if wall not in self._walls:
raise CellInvalidWallError(wall)
2024-02-13 21:13:15 +00:00
return self._walls[wall].exists
# def break_walls_r(self, i: int, j: int) -> None:
# self.visited = True
# while True:
# list_i = []
# list_j = []
# break
def draw(self) -> None:
"""
draw draws the cell onto the canvas
"""
if not self._window:
return
for _, wall in self._walls.items():
wall.draw()
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._window:
return
fill_colour = "red"
if undo:
fill_colour = "grey"
line = Line(self.centre(), to_cell.centre())
self._window.draw_line(line, fill_colour)
class CellInvalidWallError(Exception):
"""
CellInvalidWallError is raised when the program tries to specify a Cell's
Wall that does not exist.
"""
def __init__(self, wall: int, *args):
super().__init__(args)
self.wall = wall
def __str__(self):
return f"Invalid Cell Wall (wall int: {self.wall}) specified."
class CellInvalidError(Exception):
"""
2024-02-13 21:13:15 +00:00
CellInvalidError is raised when the program tries to create a Cell whose
values are invalid. The values are invalid when x2 is smaller than x1
and/or y2 is smaller than y1. When creating a Cell the x and y values
2024-02-13 21:13:15 +00:00
should always represent the top left and the bottom right corners of
the cell (i.e. x1 < x2 and y1 < y2).
"""
def __init__(self, x1: int, y1: int, x2: int, y2: int, *args):
super().__init__(args)
self.x1 = x1
self.x2 = x2
self.y1 = y1
self.y2 = y2
def __str__(self):
return f"Invalid Cell values received. Please ensure that both: x1 ({self.x1}) < x2 ({self.x2}), and y1 ({self.y1}) < y2 ({self.y2})"
class CellTooSmallError(Exception):
"""
2024-02-13 21:13:15 +00:00
CellTooSmallError is raised when the program tries to create a Cell
which is too small to correctly draw it's central point.
"""
def __init__(self, size_type: str, size: int, *args):
super().__init__(args)
self.size_type = size_type
self.size = size
def __str__(self):
return f"The {self.size_type} size of the cell ({self.size}) is too small."