diff --git a/cell.py b/cell.py index 21bae0b..ecdaee1 100644 --- a/cell.py +++ b/cell.py @@ -1,5 +1,18 @@ 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: @@ -26,11 +39,6 @@ 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, @@ -39,13 +47,13 @@ class Cell: ) -> None: # Validation if (x2 < x1) or (y2 < y1): - raise CellInvalidError(x1, y1, x2, y2) + raise errors.CellInvalidError(x1, y1, x2, y2) if (x2 - x1) < 2: - raise CellTooSmallError("horizontal", x2-x1) + raise errors.CellTooSmallError("horizontal", x2-x1) if (y2 - y1) < 2: - raise CellTooSmallError("vertical", y2-y1) + raise errors.CellTooSmallError("vertical", y2-y1) # Define the cell walls top_wall = Line(Point(x1, y1), Point(x2, y1)) @@ -53,11 +61,11 @@ class Cell: left_wall = Line(Point(x1, y1), Point(x1, y2)) right_wall = Line(Point(x2, y1), Point(x2, y2)) - 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), + 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), } # Calculate the cell's central point @@ -80,10 +88,10 @@ class Cell: """ configure_walls configures the existence of the Cell's walls. """ - 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 + self._walls[CellWallLabel.TOP].exists = top + self._walls[CellWallLabel.BOTTOM].exists = bottom + self._walls[CellWallLabel.LEFT].exists = left + self._walls[CellWallLabel.RIGHT].exists = right def centre(self) -> Point: """ @@ -92,8 +100,11 @@ class Cell: return self._centre def wall_exists(self, wall: int) -> bool: + """ + returns True if a given cell wall exists, or false otherwise. + """ if wall not in self._walls: - raise CellInvalidWallError(wall) + raise errors.CellInvalidWallError(wall) return self._walls[wall].exists # def break_walls_r(self, i: int, j: int) -> None: @@ -126,52 +137,3 @@ 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." diff --git a/errors.py b/errors.py new file mode 100644 index 0000000..50a7235 --- /dev/null +++ b/errors.py @@ -0,0 +1,47 @@ +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." diff --git a/maze.py b/maze.py index 3b4def8..917ecbe 100644 --- a/maze.py +++ b/maze.py @@ -39,9 +39,12 @@ 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._break_entrance_and_exit() + self._open_entrance_and_exit() - def _create_cells(self): + def _create_cells(self) -> None: + """ + creates all the cells and draws them. + """ cursor_x = self._x_position cursor_y = self._y_position @@ -66,20 +69,32 @@ class Maze: if self._window: self._draw_cells() - def _break_entrance_and_exit(self): - # break entrance and draw + 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. + """ 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): + def _draw_cells(self) -> None: + """ + draws all the cells on the maze with a short pause between each cell + for animation purposes. + """ 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): + def _animate(self) -> None: + """ + redraws the application and pauses for a short period of time to + provide an animation effect. + """ self._window.redraw() sleep(0.05) diff --git a/tests.py b/tests.py index 1d36a9d..55b8c24 100644 --- a/tests.py +++ b/tests.py @@ -1,7 +1,7 @@ import unittest -import cell -from cell import Cell +from cell import Cell, CellWallLabel 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(Cell.TOP_WALL)) + self.assertFalse(maze._cells[0][0].wall_exists(CellWallLabel.TOP)) self.assertFalse( maze._cells[number_of_cell_rows - 1] - [number_of_cells_per_row - 1].wall_exists(Cell.BOTTOM_WALL) + [number_of_cells_per_row - 1].wall_exists(CellWallLabel.BOTTOM) ) def test_invalid_cell_exception(self): @@ -74,7 +74,7 @@ class Tests(unittest.TestCase): ] for case in cases: - with self.assertRaises(cell.CellInvalidError): + with self.assertRaises(errors.CellInvalidError): _ = Cell( x1=case["x1"], y1=case["y1"], @@ -93,7 +93,7 @@ class Tests(unittest.TestCase): ] for case in cases: - with self.assertRaises(cell.CellTooSmallError): + with self.assertRaises(errors.CellTooSmallError): _ = Cell( x1=case["x1"], y1=case["y1"],