Compare commits

...

4 commits

Author SHA1 Message Date
2d1124cee1
ci: add workflow for forgejo actions 2024-02-13 22:08:56 +00:00
d87df48df2
refactor: add a draw method in CellWall
Add a draw() method in the CellWall class to reduce repeated code in the
Cell class.

Updated test case.
2024-02-13 21:40:56 +00:00
808e1cee53
make cell wall statuses public 2024-02-13 21:13:15 +00:00
19a29bbb5b
checkpoint: setting up breaking of walls 2024-02-13 19:00:07 +00:00
4 changed files with 93 additions and 35 deletions

View file

@ -0,0 +1,22 @@
---
name: test
on:
pull_request:
types:
- opened
- reopened
- synchronize
jobs:
test:
runs-on: docker
steps:
- name: Checkout Repository
uses: https://code.forgejo.org/actions/checkout@v3
- name: Install Python 3
uses: https://github.com/actions/setup-python@v5
with:
python-version: '3.12'
- name: Test Code
run: python tests.py

91
cell.py
View file

@ -1,3 +1,4 @@
from typing import Dict
from graphics import Window, Point, Line from graphics import Window, Point, Line
@ -7,9 +8,17 @@ class CellWall:
a Cell's wall. a Cell's wall.
""" """
def __init__(self, line: Line) -> None: def __init__(self, line: Line, window: Window) -> None:
self.exists = True self.exists = True
self.line = line 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: class Cell:
@ -17,6 +26,11 @@ class Cell:
A Cell represents a grid on the maze. A Cell represents a grid on the maze.
""" """
TOP_WALL = 0
BOTTOM_WALL = 1
LEFT_WALL = 2
RIGHT_WALL = 4
def __init__( def __init__(
self, self,
x1: int, y1: int, x1: int, y1: int,
@ -39,10 +53,12 @@ class Cell:
left_wall = Line(Point(x1, y1), Point(x1, y2)) left_wall = Line(Point(x1, y1), Point(x1, y2))
right_wall = Line(Point(x2, y1), Point(x2, y2)) right_wall = Line(Point(x2, y1), Point(x2, y2))
self._top_wall = CellWall(top_wall) self._walls: Dict[int, CellWall] = {
self._bottom_wall = CellWall(bottom_wall) Cell.TOP_WALL: CellWall(top_wall, window),
self._left_wall = CellWall(left_wall) Cell.BOTTOM_WALL: CellWall(bottom_wall, window),
self._right_wall = CellWall(right_wall) Cell.LEFT_WALL: CellWall(left_wall, window),
Cell.RIGHT_WALL: CellWall(right_wall, window),
}
# Calculate the cell's central point # Calculate the cell's central point
centre_x = x1 + ((x2 - x1) / 2) centre_x = x1 + ((x2 - x1) / 2)
@ -52,6 +68,8 @@ class Cell:
# A reference to the root Window class for drawing purposes. # A reference to the root Window class for drawing purposes.
self._window = window self._window = window
self.visited = False
def configure_walls( def configure_walls(
self, self,
top: bool = True, top: bool = True,
@ -62,10 +80,10 @@ class Cell:
""" """
configure_walls configures the existence of the Cell's walls. configure_walls configures the existence of the Cell's walls.
""" """
self._top_wall.exists = top self._walls[Cell.TOP_WALL].exists = top
self._bottom_wall.exists = bottom self._walls[Cell.BOTTOM_WALL].exists = bottom
self._left_wall.exists = left self._walls[Cell.LEFT_WALL].exists = left
self._right_wall.exists = right self._walls[Cell.RIGHT_WALL].exists = right
def centre(self) -> Point: def centre(self) -> Point:
""" """
@ -73,6 +91,18 @@ class Cell:
""" """
return self._centre return self._centre
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:
# self.visited = True
# while True:
# list_i = []
# list_j = []
# break
def draw(self) -> None: def draw(self) -> None:
""" """
draw draws the cell onto the canvas draw draws the cell onto the canvas
@ -80,25 +110,8 @@ class Cell:
if not self._window: if not self._window:
return return
if self._top_wall.exists: for _, wall in self._walls.items():
self._window.draw_line(self._top_wall.line, fill_colour=self._window.cell_grid_colour) wall.draw()
else:
self._window.draw_line(self._top_wall.line, fill_colour=self._window.background_colour)
if self._bottom_wall.exists:
self._window.draw_line(self._bottom_wall.line, fill_colour=self._window.cell_grid_colour)
else:
self._window.draw_line(self._bottom_wall.line, fill_colour=self._window.background_colour)
if self._left_wall.exists:
self._window.draw_line(self._left_wall.line, fill_colour=self._window.cell_grid_colour)
else:
self._window.draw_line(self._left_wall.line, fill_colour=self._window.background_colour)
if self._right_wall.exists:
self._window.draw_line(self._right_wall.line, fill_colour=self._window.cell_grid_colour)
else:
self._window.draw_line(self._right_wall.line, fill_colour=self._window.background_colour)
def draw_move(self, to_cell: 'Cell', undo: bool = False) -> None: def draw_move(self, to_cell: 'Cell', undo: bool = False) -> None:
""" """
@ -115,13 +128,27 @@ class Cell:
self._window.draw_line(line, fill_colour) 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): class CellInvalidError(Exception):
""" """
CellInvalidError is returned when the program tries to create a Cell whose 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 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 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 should always represent the top left and the bottom right corners of
walls (i.e. x1 < x2 and y1 < y2). the cell (i.e. x1 < x2 and y1 < y2).
""" """
def __init__(self, x1: int, y1: int, x2: int, y2: int, *args): def __init__(self, x1: int, y1: int, x2: int, y2: int, *args):
@ -137,7 +164,7 @@ class CellInvalidError(Exception):
class CellTooSmallError(Exception): class CellTooSmallError(Exception):
""" """
CellTooSmallError is returned when the program tries to create a Cell CellTooSmallError is raised when the program tries to create a Cell
which is too small to correctly draw it's central point. which is too small to correctly draw it's central point.
""" """

View file

@ -1,5 +1,6 @@
from typing import List from typing import List
from time import sleep from time import sleep
import random
from graphics import Window from graphics import Window
from cell import Cell from cell import Cell
@ -18,6 +19,7 @@ class Maze:
cell_size_x: int, cell_size_x: int,
cell_size_y: int, cell_size_y: int,
window: Window = None, window: Window = None,
seed=None,
) -> None: ) -> None:
self._x_position = x_position self._x_position = x_position
self._y_position = y_position self._y_position = y_position
@ -26,6 +28,13 @@ class Maze:
self._cell_size_x = cell_size_x self._cell_size_x = cell_size_x
self._cell_size_y = cell_size_y self._cell_size_y = cell_size_y
self._window = window self._window = window
self._seed = None
# Generate the seed if it does not exist
if seed:
self._seed = seed
else:
random.seed(self._seed)
# Create the Maze's cells # Create the Maze's cells
self._cells: List[List[Cell]] = [None for i in range(self._num_cell_rows)] self._cells: List[List[Cell]] = [None for i in range(self._num_cell_rows)]

View file

@ -1,5 +1,6 @@
import unittest import unittest
from maze import Maze from maze import Maze
from cell import Cell
class Tests(unittest.TestCase): class Tests(unittest.TestCase):
@ -55,9 +56,8 @@ class Tests(unittest.TestCase):
2, 2,
2, 2,
) )
self.assertFalse(maze._cells[0][0]._top_wall.exists) self.assertFalse(maze._cells[0][0].wall_exists(Cell.TOP_WALL))
self.assertFalse( self.assertFalse(maze._cells[number_of_cell_rows - 1][number_of_cells_per_row - 1].wall_exists(Cell.BOTTOM_WALL))
maze._cells[number_of_cell_rows - 1][number_of_cells_per_row - 1]._bottom_wall.exists)
if __name__ == "__main__": if __name__ == "__main__":