Dan Anglin
1b0f044834
Some checks failed
test / test (pull_request) Failing after 6s
This commit adds a simple side panel to allow users to interact with the application. The side panel allows the user to: - Generate and regenerate mazes - Choose between the searching algorithms - Choose whether or not to add randomness to the algorithm - Run and re-run the simulation
177 lines
4.7 KiB
Python
177 lines
4.7 KiB
Python
from typing import Dict
|
|
from enum import Enum
|
|
from line import Point, Line
|
|
import errors
|
|
|
|
|
|
class CellWallLabels(Enum):
|
|
"""
|
|
CellWallLabel is used to label a CellWall
|
|
"""
|
|
|
|
TOP = 0
|
|
BOTTOM = 1
|
|
LEFT = 2
|
|
RIGHT = 3
|
|
|
|
|
|
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
|
|
self._line_colour = "black"
|
|
|
|
def configure(self, build: bool) -> None:
|
|
"""
|
|
builds or destroys the cell wall.
|
|
"""
|
|
if build:
|
|
self._build_wall()
|
|
else:
|
|
self._destroy_wall()
|
|
|
|
def _build_wall(self) -> None:
|
|
"""
|
|
builds the cell wall
|
|
"""
|
|
self._exists = True
|
|
self._line_colour = "black"
|
|
|
|
def _destroy_wall(self) -> None:
|
|
"""
|
|
destroys the cell wall
|
|
"""
|
|
self._exists = False
|
|
self._line_colour = "white"
|
|
|
|
def wall_up(self) -> bool:
|
|
"""
|
|
returns true if the cell wall is up.
|
|
"""
|
|
return self._exists
|
|
|
|
def get_line(self) -> Line:
|
|
return self._line
|
|
|
|
def get_line_colour(self) -> str:
|
|
"""
|
|
returns the line colour of the wall.
|
|
"""
|
|
return self._line_colour
|
|
|
|
|
|
class Cell:
|
|
"""
|
|
A Cell represents a grid on the maze.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
x1: int, y1: int,
|
|
x2: int, y2: int,
|
|
) -> None:
|
|
# Validation
|
|
if (x2 < x1) or (y2 < y1):
|
|
raise errors.CellInvalidError(x1, y1, x2, y2)
|
|
|
|
if (x2 - x1) < 2:
|
|
raise errors.CellTooSmallError("horizontal", x2-x1)
|
|
|
|
if (y2 - y1) < 2:
|
|
raise errors.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))
|
|
|
|
self._walls: Dict[CellWallLabels, CellWall] = {
|
|
CellWallLabels.TOP: CellWall(top_wall),
|
|
CellWallLabels.BOTTOM: CellWall(bottom_wall),
|
|
CellWallLabels.LEFT: CellWall(left_wall),
|
|
CellWallLabels.RIGHT: CellWall(right_wall),
|
|
}
|
|
|
|
# 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)
|
|
|
|
self._visited: Dict[str, bool] = {
|
|
"generator": False,
|
|
"solver": False,
|
|
}
|
|
|
|
def configure_walls(
|
|
self,
|
|
top: bool = None,
|
|
bottom: bool = None,
|
|
left: bool = None,
|
|
right: bool = None,
|
|
) -> None:
|
|
"""
|
|
configure_walls configures the existence of the Cell's walls.
|
|
"""
|
|
if top is not None:
|
|
self._walls[CellWallLabels.TOP].configure(top)
|
|
if bottom is not None:
|
|
self._walls[CellWallLabels.BOTTOM].configure(bottom)
|
|
if left is not None:
|
|
self._walls[CellWallLabels.LEFT].configure(left)
|
|
if right is not None:
|
|
self._walls[CellWallLabels.RIGHT].configure(right)
|
|
|
|
def centre(self) -> Point:
|
|
"""
|
|
centre returns the Cell's central point
|
|
"""
|
|
return self._centre
|
|
|
|
def wall_exists(self, wall: CellWallLabels) -> bool:
|
|
"""
|
|
returns True if a given cell wall exists, or false otherwise.
|
|
"""
|
|
if wall not in CellWallLabels:
|
|
raise TypeError(
|
|
"The argument does not appear to be a valid cell wall."
|
|
)
|
|
return self._walls[wall].wall_up()
|
|
|
|
def was_visited_by(self, visitor: str) -> bool:
|
|
"""
|
|
returns True if the cell was visited by the
|
|
specified visitor.
|
|
"""
|
|
if visitor not in ("solver", "generator"):
|
|
raise ValueError(f"This is an unknown visitor ({visitor})")
|
|
|
|
return self._visited[visitor]
|
|
|
|
def mark_as_visited_by(self, visitor: str) -> None:
|
|
"""
|
|
marks the cell as visited by the specified visitor.
|
|
"""
|
|
if visitor not in ("solver", "generator"):
|
|
raise ValueError(f"This is an unknown visitor ({visitor})")
|
|
self._visited[visitor] = True
|
|
|
|
def unmark_visited(self, visitor: str) -> None:
|
|
"""
|
|
unmarks the cell as visited by the specified visitor.
|
|
"""
|
|
self._visited[visitor] = False
|
|
|
|
def reset(self) -> None:
|
|
for label in CellWallLabels:
|
|
self._walls[label].configure(True)
|
|
for k in self._visited:
|
|
self._visited[k] = False
|
|
|
|
def get_walls(self) -> Dict[CellWallLabels, CellWall]:
|
|
return self._walls
|