Compare commits

..

No commits in common. "609ae4fae9ae81b2082574b9db443e3ba525c3d1" and "79d972727344aad46a5a9e29522026677ce8c1a0" have entirely different histories.

4 changed files with 84 additions and 92 deletions

102
cell.py
View file

@ -1,18 +1,5 @@
from typing import Dict
from enum import Enum
from graphics import Window, Point, Line
import errors
class CellWallLabel(Enum):
"""
CellWallLabel is used to label a CellWall
"""
TOP = 0
BOTTOM = 1
LEFT = 2
RIGHT = 3
class CellWall:
@ -39,6 +26,11 @@ class Cell:
A Cell represents a grid on the maze.
"""
TOP_WALL = 0
BOTTOM_WALL = 1
LEFT_WALL = 2
RIGHT_WALL = 3
def __init__(
self,
x1: int, y1: int,
@ -47,13 +39,13 @@ class Cell:
) -> None:
# Validation
if (x2 < x1) or (y2 < y1):
raise errors.CellInvalidError(x1, y1, x2, y2)
raise CellInvalidError(x1, y1, x2, y2)
if (x2 - x1) < 2:
raise errors.CellTooSmallError("horizontal", x2-x1)
raise CellTooSmallError("horizontal", x2-x1)
if (y2 - y1) < 2:
raise errors.CellTooSmallError("vertical", y2-y1)
raise CellTooSmallError("vertical", y2-y1)
# Define the cell walls
top_wall = Line(Point(x1, y1), Point(x2, y1))
@ -61,11 +53,11 @@ class Cell:
left_wall = Line(Point(x1, y1), Point(x1, y2))
right_wall = Line(Point(x2, y1), Point(x2, y2))
self._walls: Dict[CellWallLabel, CellWall] = {
CellWallLabel.TOP: CellWall(top_wall, window),
CellWallLabel.BOTTOM: CellWall(bottom_wall, window),
CellWallLabel.LEFT: CellWall(left_wall, window),
CellWallLabel.RIGHT: CellWall(right_wall, window),
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),
}
# Calculate the cell's central point
@ -88,10 +80,10 @@ class Cell:
"""
configure_walls configures the existence of the Cell's walls.
"""
self._walls[CellWallLabel.TOP].exists = top
self._walls[CellWallLabel.BOTTOM].exists = bottom
self._walls[CellWallLabel.LEFT].exists = left
self._walls[CellWallLabel.RIGHT].exists = right
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:
"""
@ -99,10 +91,9 @@ class Cell:
"""
return self._centre
def wall_exists(self, wall: CellWallLabel) -> bool:
"""
returns True if a given cell wall exists, or false otherwise.
"""
def wall_exists(self, wall: int) -> bool:
if wall not in self._walls:
raise CellInvalidWallError(wall)
return self._walls[wall].exists
# def break_walls_r(self, i: int, j: int) -> None:
@ -119,8 +110,8 @@ class Cell:
if not self._window:
return
for label in CellWallLabel:
self._walls[label].draw()
for _, wall in self._walls.items():
wall.draw()
def draw_move(self, to_cell: 'Cell', undo: bool = False) -> None:
"""
@ -135,3 +126,52 @@ class Cell:
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):
"""
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
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):
"""
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."

View file

@ -1,33 +0,0 @@
class CellInvalidError(Exception):
"""
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
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):
"""
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."

29
maze.py
View file

@ -39,12 +39,9 @@ class Maze:
# Create the Maze's cells
self._cells: List[List[Cell]] = [None for i in range(self._num_cell_rows)]
self._create_cells()
self._open_entrance_and_exit()
self._break_entrance_and_exit()
def _create_cells(self) -> None:
"""
creates all the cells and draws them.
"""
def _create_cells(self):
cursor_x = self._x_position
cursor_y = self._y_position
@ -69,32 +66,20 @@ class Maze:
if self._window:
self._draw_cells()
def _open_entrance_and_exit(self) -> None:
"""
opens the maze's entrance and exit cells by breaking their respective
walls. The entrance is located at the top left and the exit is located
at the bottom right of the maze.
"""
def _break_entrance_and_exit(self):
# break entrance and draw
self._cells[0][0].configure_walls(top=False)
self._cells[0][0].draw()
# break exit and draw
self._cells[self._num_cell_rows - 1][self._num_cells_per_row - 1].configure_walls(bottom=False)
self._cells[self._num_cell_rows - 1][self._num_cells_per_row - 1].draw()
def _draw_cells(self) -> None:
"""
draws all the cells on the maze with a short pause between each cell
for animation purposes.
"""
def _draw_cells(self):
for i in range(self._num_cell_rows):
for j in range(self._num_cells_per_row):
self._cells[i][j].draw()
self._animate()
def _animate(self) -> None:
"""
redraws the application and pauses for a short period of time to
provide an animation effect.
"""
def _animate(self):
self._window.redraw()
sleep(0.05)

View file

@ -1,7 +1,7 @@
import unittest
from cell import Cell, CellWallLabel
import cell
from cell import Cell
from maze import Maze
import errors
class Tests(unittest.TestCase):
@ -57,10 +57,10 @@ class Tests(unittest.TestCase):
2,
2,
)
self.assertFalse(maze._cells[0][0].wall_exists(CellWallLabel.TOP))
self.assertFalse(maze._cells[0][0].wall_exists(Cell.TOP_WALL))
self.assertFalse(
maze._cells[number_of_cell_rows - 1]
[number_of_cells_per_row - 1].wall_exists(CellWallLabel.BOTTOM)
[number_of_cells_per_row - 1].wall_exists(Cell.BOTTOM_WALL)
)
def test_invalid_cell_exception(self):
@ -74,7 +74,7 @@ class Tests(unittest.TestCase):
]
for case in cases:
with self.assertRaises(errors.CellInvalidError):
with self.assertRaises(cell.CellInvalidError):
_ = Cell(
x1=case["x1"],
y1=case["y1"],
@ -93,7 +93,7 @@ class Tests(unittest.TestCase):
]
for case in cases:
with self.assertRaises(errors.CellTooSmallError):
with self.assertRaises(cell.CellTooSmallError):
_ = Cell(
x1=case["x1"],
y1=case["y1"],