checkpoint: visited methods

- Add methods to mark cells as visited and to get results of the visits.
- renamed MazeDirections to MazeDirection
This commit is contained in:
Dan Anglin 2024-02-16 10:36:06 +00:00
parent 5c48f47a0a
commit c809292c04
Signed by: dananglin
GPG key ID: 0C1D44CFBEE68638
4 changed files with 63 additions and 38 deletions

24
cell.py
View file

@ -76,8 +76,10 @@ class Cell:
# A reference to the root Window class for drawing purposes.
self._window = window
self.visited_by_maze_generator = False
self.visited_by_maze_solver = False
self._visited: Dict[str, bool] = {
"generator": False,
"solver": False,
}
def configure_walls(
self,
@ -137,3 +139,21 @@ class Cell:
fill_colour = "grey"
line = Line(self.centre(), to_cell.centre())
self._window.draw_line(line, fill_colour)
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

View file

@ -8,10 +8,10 @@ def main():
game = Maze(
x_position=10,
y_position=10,
num_cell_rows=30,
num_cells_per_row=30,
cell_size_x=20,
cell_size_y=20,
num_cell_rows=16,
num_cells_per_row=16,
cell_size_x=40,
cell_size_y=40,
window=window
)

53
maze.py
View file

@ -6,7 +6,7 @@ from graphics import Window
from cell import Cell, CellWallLabels
class MazeDirections(Enum):
class MazeDirection(Enum):
"""
MazeDirection represents the directions you can
take in the maze.
@ -35,35 +35,35 @@ class MazePosition:
def get_adjacent_position(
self,
direction: MazeDirections
direction: MazeDirection
) -> 'MazePosition':
if direction not in MazeDirections:
if direction not in MazeDirection:
raise TypeError(
"The argument does not appear to be a valid maze direction."
)
if direction is MazeDirections.ABOVE and (self.i-1 >= 0):
if direction is MazeDirection.ABOVE and (self.i-1 >= 0):
return MazePosition(
i=self.i-1,
j=self.j,
max_i=self.max_i,
max_j=self.max_j,
)
if direction is MazeDirections.BELOW and (self.i+1 <= self.max_i):
if direction is MazeDirection.BELOW and (self.i+1 <= self.max_i):
return MazePosition(
i=self.i+1,
j=self.j,
max_i=self.max_i,
max_j=self.max_j,
)
if direction is MazeDirections.LEFT and (self.j-1 >= 0):
if direction is MazeDirection.LEFT and (self.j-1 >= 0):
return MazePosition(
i=self.i,
j=self.j-1,
max_i=self.max_i,
max_j=self.max_j,
)
if direction is MazeDirections.RIGHT and (self.j+1 <= self.max_j):
if direction is MazeDirection.RIGHT and (self.j+1 <= self.max_j):
return MazePosition(
i=self.i,
j=self.j+1,
@ -179,19 +179,21 @@ class Maze:
cells and randomly knocking down the walls to create the maze's paths.
"""
generator = "generator"
current_cell = self._cells[current_position.i][current_position.j]
current_cell.visited_by_maze_generator = True
current_cell.mark_as_visited_by(generator)
while True:
possible_directions: List[MazeDirections] = []
possible_directions: List[MazeDirection] = []
for direction in MazeDirections:
for direction in MazeDirection:
adjacent_position = current_position.get_adjacent_position(
direction)
if adjacent_position is None:
continue
adjacent_cell = self._cells[adjacent_position.i][adjacent_position.j]
if adjacent_cell.visited_by_maze_generator:
if adjacent_cell.was_visited_by(generator):
continue
possible_directions.append(direction)
@ -205,16 +207,16 @@ class Maze:
chosen_direction)
next_cell = self._cells[next_position.i][next_position.j]
if chosen_direction is MazeDirections.ABOVE:
if chosen_direction is MazeDirection.ABOVE:
current_cell.configure_walls(top=False)
next_cell.configure_walls(bottom=False)
elif chosen_direction is MazeDirections.BELOW:
elif chosen_direction is MazeDirection.BELOW:
current_cell.configure_walls(bottom=False)
next_cell.configure_walls(top=False)
elif chosen_direction is MazeDirections.LEFT:
elif chosen_direction is MazeDirection.LEFT:
current_cell.configure_walls(left=False)
next_cell.configure_walls(right=False)
elif chosen_direction is MazeDirections.RIGHT:
elif chosen_direction is MazeDirection.RIGHT:
current_cell.configure_walls(right=False)
next_cell.configure_walls(left=False)
@ -248,25 +250,28 @@ class Maze:
current_position: MazePosition,
end_position: MazePosition,
) -> bool:
solver = "solver"
if current_position == end_position:
return True
current_cell = self._cells[current_position.i][current_position.j]
current_cell.visited_by_maze_solver = True
current_cell.mark_as_visited_by(solver)
wall_map: Dict[MazeDirections, CellWallLabels] = {
MazeDirections.ABOVE: CellWallLabels.BOTTOM,
MazeDirections.BELOW: CellWallLabels.TOP,
MazeDirections.LEFT: CellWallLabels.RIGHT,
MazeDirections.RIGHT: CellWallLabels.LEFT,
wall_map: Dict[MazeDirection, CellWallLabels] = {
MazeDirection.ABOVE: CellWallLabels.BOTTOM,
MazeDirection.BELOW: CellWallLabels.TOP,
MazeDirection.LEFT: CellWallLabels.RIGHT,
MazeDirection.RIGHT: CellWallLabels.LEFT,
}
for direction in MazeDirections:
for direction in MazeDirection:
adjacent_position = current_position.get_adjacent_position(
direction)
direction
)
if adjacent_position is None:
continue
adjacent_cell = self._cells[adjacent_position.i][adjacent_position.j]
if adjacent_cell.visited_by_maze_solver or adjacent_cell.wall_exists(wall_map[direction]):
if adjacent_cell.was_visited_by(solver) or adjacent_cell.wall_exists(wall_map[direction]):
continue
self._draw_path(current_cell, adjacent_cell)
result = self._solve_r(adjacent_position, end_position)

View file

@ -131,42 +131,42 @@ class Tests(unittest.TestCase):
cases = [
{
"position": maze.MazePosition(i=3, j=4, max_i=10, max_j=10),
"direction": maze.MazeDirections.ABOVE,
"direction": maze.MazeDirection.ABOVE,
"expected": maze.MazePosition(i=2, j=4, max_i=10, max_j=10),
},
{
"position": maze.MazePosition(i=9, j=4, max_i=10, max_j=10),
"direction": maze.MazeDirections.BELOW,
"direction": maze.MazeDirection.BELOW,
"expected": maze.MazePosition(i=10, j=4, max_i=10, max_j=10),
},
{
"position": maze.MazePosition(i=1, j=1, max_i=10, max_j=10),
"direction": maze.MazeDirections.LEFT,
"direction": maze.MazeDirection.LEFT,
"expected": maze.MazePosition(i=1, j=0, max_i=10, max_j=10),
},
{
"position": maze.MazePosition(i=3, j=9, max_i=10, max_j=10),
"direction": maze.MazeDirections.RIGHT,
"direction": maze.MazeDirection.RIGHT,
"expected": maze.MazePosition(i=3, j=10, max_i=10, max_j=10),
},
{
"position": maze.MazePosition(i=0, j=4, max_i=10, max_j=10),
"direction": maze.MazeDirections.ABOVE,
"direction": maze.MazeDirection.ABOVE,
"expected": None,
},
{
"position": maze.MazePosition(i=10, j=4, max_i=10, max_j=10),
"direction": maze.MazeDirections.BELOW,
"direction": maze.MazeDirection.BELOW,
"expected": None,
},
{
"position": maze.MazePosition(i=1, j=0, max_i=10, max_j=10),
"direction": maze.MazeDirections.LEFT,
"direction": maze.MazeDirection.LEFT,
"expected": None,
},
{
"position": maze.MazePosition(i=3, j=10, max_i=10, max_j=10),
"direction": maze.MazeDirections.RIGHT,
"direction": maze.MazeDirection.RIGHT,
"expected": None,
},
]