2024-02-12 23:48:41 +00:00
|
|
|
from graphics import Window, Point, Line
|
|
|
|
|
|
|
|
|
2024-02-13 15:52:28 +00:00
|
|
|
class CellWall:
|
|
|
|
"""
|
|
|
|
A CellWall represents the existence (or non-existence) of
|
|
|
|
a Cell's wall.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self, line: Line) -> None:
|
|
|
|
self.exists = True
|
|
|
|
self.line = line
|
|
|
|
|
|
|
|
|
2024-02-12 23:48:41 +00:00
|
|
|
class Cell:
|
|
|
|
"""
|
|
|
|
A Cell represents a grid on the maze.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
x1: int, y1: int,
|
|
|
|
x2: int, y2: int,
|
2024-02-13 13:39:25 +00:00
|
|
|
window: Window = None,
|
2024-02-13 10:59:47 +00:00
|
|
|
) -> None:
|
2024-02-13 18:54:58 +00:00
|
|
|
# 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)
|
|
|
|
|
2024-02-13 10:48:26 +00:00
|
|
|
# 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 13:39:25 +00:00
|
|
|
self._top_wall = CellWall(top_wall)
|
|
|
|
self._bottom_wall = CellWall(bottom_wall)
|
|
|
|
self._left_wall = CellWall(left_wall)
|
|
|
|
self._right_wall = CellWall(right_wall)
|
2024-02-13 10:48:26 +00:00
|
|
|
|
|
|
|
# Calculate the cell's central point
|
|
|
|
centre_x = x1 + ((x2 - x1) / 2)
|
|
|
|
centre_y = y1 + ((y2 - y1) / 2)
|
2024-02-13 13:39:25 +00:00
|
|
|
self._centre = Point(centre_x, centre_y)
|
2024-02-13 10:48:26 +00:00
|
|
|
|
|
|
|
# A reference to the root Window class for drawing purposes.
|
2024-02-13 13:39:25 +00:00
|
|
|
self._window = window
|
2024-02-12 23:48:41 +00:00
|
|
|
|
2024-02-13 18:06:46 +00:00
|
|
|
self.visited = False
|
|
|
|
|
2024-02-13 01:15:19 +00:00
|
|
|
def configure_walls(
|
|
|
|
self,
|
|
|
|
top: bool = True,
|
|
|
|
bottom: bool = True,
|
|
|
|
left: bool = True,
|
|
|
|
right: bool = True,
|
2024-02-13 10:59:47 +00:00
|
|
|
) -> None:
|
2024-02-13 01:15:19 +00:00
|
|
|
"""
|
|
|
|
configure_walls configures the existence of the Cell's walls.
|
|
|
|
"""
|
2024-02-13 13:39:25 +00:00
|
|
|
self._top_wall.exists = top
|
|
|
|
self._bottom_wall.exists = bottom
|
|
|
|
self._left_wall.exists = left
|
|
|
|
self._right_wall.exists = right
|
2024-02-12 23:48:41 +00:00
|
|
|
|
2024-02-13 10:48:26 +00:00
|
|
|
def centre(self) -> Point:
|
|
|
|
"""
|
|
|
|
centre returns the Cell's central point
|
|
|
|
"""
|
2024-02-13 13:39:25 +00:00
|
|
|
return self._centre
|
2024-02-13 10:48:26 +00:00
|
|
|
|
2024-02-13 18:06:46 +00:00
|
|
|
#def break_walls_r(self, i: int, j: int) -> None:
|
|
|
|
# self.visited = True
|
|
|
|
# while True:
|
|
|
|
# list_i = []
|
|
|
|
# list_j = []
|
|
|
|
# break
|
|
|
|
|
2024-02-13 10:59:47 +00:00
|
|
|
def draw(self) -> None:
|
2024-02-13 01:15:19 +00:00
|
|
|
"""
|
|
|
|
draw draws the cell onto the canvas
|
|
|
|
"""
|
2024-02-13 15:52:28 +00:00
|
|
|
if not self._window:
|
|
|
|
return
|
|
|
|
|
|
|
|
if self._top_wall.exists:
|
2024-02-13 18:06:46 +00:00
|
|
|
self._window.draw_line(
|
|
|
|
self._top_wall.line,
|
|
|
|
fill_colour=self._window.cell_grid_colour,
|
|
|
|
)
|
2024-02-13 15:52:28 +00:00
|
|
|
else:
|
2024-02-13 18:06:46 +00:00
|
|
|
self._window.draw_line(
|
|
|
|
self._top_wall.line,
|
|
|
|
fill_colour=self._window.background_colour,
|
|
|
|
)
|
2024-02-13 15:52:28 +00:00
|
|
|
|
|
|
|
if self._bottom_wall.exists:
|
2024-02-13 18:06:46 +00:00
|
|
|
self._window.draw_line(
|
|
|
|
self._bottom_wall.line,
|
|
|
|
fill_colour=self._window.cell_grid_colour,
|
|
|
|
)
|
2024-02-13 15:52:28 +00:00
|
|
|
else:
|
2024-02-13 18:06:46 +00:00
|
|
|
self._window.draw_line(
|
|
|
|
self._bottom_wall.line,
|
|
|
|
fill_colour=self._window.background_colour,
|
|
|
|
)
|
2024-02-13 15:52:28 +00:00
|
|
|
|
|
|
|
if self._left_wall.exists:
|
2024-02-13 18:06:46 +00:00
|
|
|
self._window.draw_line(
|
|
|
|
self._left_wall.line,
|
|
|
|
fill_colour=self._window.cell_grid_colour,
|
|
|
|
)
|
2024-02-13 15:52:28 +00:00
|
|
|
else:
|
2024-02-13 18:06:46 +00:00
|
|
|
self._window.draw_line(
|
|
|
|
self._left_wall.line,
|
|
|
|
fill_colour=self._window.background_colour,
|
|
|
|
)
|
2024-02-13 15:52:28 +00:00
|
|
|
|
|
|
|
if self._right_wall.exists:
|
2024-02-13 18:06:46 +00:00
|
|
|
self._window.draw_line(
|
|
|
|
self._right_wall.line,
|
|
|
|
fill_colour=self._window.cell_grid_colour,
|
|
|
|
)
|
2024-02-13 15:52:28 +00:00
|
|
|
else:
|
2024-02-13 18:06:46 +00:00
|
|
|
self._window.draw_line(
|
|
|
|
self._right_wall.line,
|
|
|
|
fill_colour=self._window.background_colour,
|
|
|
|
)
|
2024-02-13 01:15:19 +00:00
|
|
|
|
2024-02-13 10:59:47 +00:00
|
|
|
def draw_move(self, to_cell: 'Cell', undo: bool = False) -> None:
|
2024-02-13 10:48:26 +00:00
|
|
|
"""
|
|
|
|
draw_move draws a path between the centre of this cell and
|
|
|
|
the centre of the given cell.
|
|
|
|
"""
|
2024-02-13 15:52:28 +00:00
|
|
|
if not self._window:
|
|
|
|
return
|
2024-02-13 01:15:19 +00:00
|
|
|
|
2024-02-13 15:52:28 +00:00
|
|
|
fill_colour = "red"
|
|
|
|
if undo:
|
|
|
|
fill_colour = "grey"
|
|
|
|
line = Line(self.centre(), to_cell.centre())
|
|
|
|
self._window.draw_line(line, fill_colour)
|
2024-02-13 18:54:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
class CellInvalidError(Exception):
|
|
|
|
"""
|
|
|
|
CellInvalidError is returned 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
|
|
|
|
should always represent the top left and the bottom right of the cell's
|
|
|
|
walls (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):
|
|
|
|
"""
|
|
|
|
CellTooSmallError is returned 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."
|