feat: add the Randomised DST search algorithm
Implement a variation to the DST search algorithm to the Solver class. In this variation, the solver randomly chooses the next direction when it reaches a fork in its path.
This commit is contained in:
parent
a091f0a68d
commit
8466500092
2 changed files with 72 additions and 10 deletions
6
main.py
6
main.py
|
@ -9,8 +9,8 @@ def main():
|
||||||
game = Maze(
|
game = Maze(
|
||||||
x_position=10,
|
x_position=10,
|
||||||
y_position=10,
|
y_position=10,
|
||||||
height=16,
|
height=19,
|
||||||
width=16,
|
width=19,
|
||||||
cell_height=40,
|
cell_height=40,
|
||||||
cell_width=40,
|
cell_width=40,
|
||||||
window=window
|
window=window
|
||||||
|
@ -18,7 +18,7 @@ def main():
|
||||||
|
|
||||||
solver = Solver(game)
|
solver = Solver(game)
|
||||||
|
|
||||||
if solver.solve():
|
if solver.solve(solver.solve_with_randomised_dst_r):
|
||||||
print("Maze solved successfully :)")
|
print("Maze solved successfully :)")
|
||||||
else:
|
else:
|
||||||
print("I'm unable to solve the maze :(")
|
print("I'm unable to solve the maze :(")
|
||||||
|
|
76
solver.py
76
solver.py
|
@ -1,4 +1,5 @@
|
||||||
from typing import Dict
|
from typing import Dict, Callable, List
|
||||||
|
import random
|
||||||
from maze import Maze, MazeDirection, MazePosition
|
from maze import Maze, MazeDirection, MazePosition
|
||||||
from cell import CellWallLabels
|
from cell import CellWallLabels
|
||||||
|
|
||||||
|
@ -20,7 +21,10 @@ class Solver:
|
||||||
MazeDirection.RIGHT: CellWallLabels.LEFT,
|
MazeDirection.RIGHT: CellWallLabels.LEFT,
|
||||||
}
|
}
|
||||||
|
|
||||||
def solve(self) -> bool:
|
def solve(
|
||||||
|
self,
|
||||||
|
solve_method: Callable[[MazePosition, MazePosition], bool],
|
||||||
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
solve attempts to solve the generated maze.
|
solve attempts to solve the generated maze.
|
||||||
"""
|
"""
|
||||||
|
@ -38,9 +42,9 @@ class Solver:
|
||||||
last_j=self._game.get_last_j(),
|
last_j=self._game.get_last_j(),
|
||||||
)
|
)
|
||||||
|
|
||||||
return self._solve_r(start_position, end_position)
|
return solve_method(start_position, end_position)
|
||||||
|
|
||||||
def _solve_r(
|
def solve_with_dst_r(
|
||||||
self,
|
self,
|
||||||
current_position: MazePosition,
|
current_position: MazePosition,
|
||||||
end_position: MazePosition,
|
end_position: MazePosition,
|
||||||
|
@ -73,9 +77,67 @@ class Solver:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self._game.draw_path_between(current_position, adjacent_position)
|
self._game.draw_path_between(current_position, adjacent_position)
|
||||||
result = self._solve_r(adjacent_position, end_position)
|
solved = self.solve_with_dst_r(adjacent_position, end_position)
|
||||||
if result is True:
|
if solved:
|
||||||
return True
|
return True
|
||||||
self._game.draw_path_between(current_position, adjacent_position, undo=True)
|
self._game.draw_path_between(
|
||||||
|
current_position, adjacent_position, undo=True)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def solve_with_randomised_dst_r(
|
||||||
|
self,
|
||||||
|
current_position: MazePosition,
|
||||||
|
end_position: MazePosition,
|
||||||
|
) -> bool:
|
||||||
|
if current_position == end_position:
|
||||||
|
return True
|
||||||
|
|
||||||
|
self._game.mark_cell_as_visited(
|
||||||
|
i=current_position.i,
|
||||||
|
j=current_position.j,
|
||||||
|
visitor=self._solver,
|
||||||
|
)
|
||||||
|
|
||||||
|
random.seed()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
possible_directions: List[MazeDirection] = []
|
||||||
|
for direction in MazeDirection:
|
||||||
|
adjacent_position = current_position.get_adjacent_position(
|
||||||
|
direction)
|
||||||
|
if adjacent_position is None:
|
||||||
|
continue
|
||||||
|
if self._game.cell_was_visited_by(
|
||||||
|
i=adjacent_position.i,
|
||||||
|
j=adjacent_position.j,
|
||||||
|
visitor=self._solver,
|
||||||
|
) or self._game.cell_wall_exists(
|
||||||
|
i=adjacent_position.i,
|
||||||
|
j=adjacent_position.j,
|
||||||
|
wall=self._wall_map[direction],
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
possible_directions.append(direction)
|
||||||
|
if len(possible_directions) == 0:
|
||||||
|
break
|
||||||
|
chosen_direction = None
|
||||||
|
if len(possible_directions) == 1:
|
||||||
|
chosen_direction = possible_directions[0]
|
||||||
|
else:
|
||||||
|
chosen_direction = random.choice(possible_directions)
|
||||||
|
next_position = current_position.get_adjacent_position(
|
||||||
|
chosen_direction,
|
||||||
|
)
|
||||||
|
self._game.draw_path_between(current_position, next_position)
|
||||||
|
solved = self.solve_with_randomised_dst_r(
|
||||||
|
next_position, end_position)
|
||||||
|
if solved:
|
||||||
|
return True
|
||||||
|
self._game.draw_path_between(
|
||||||
|
current_position,
|
||||||
|
next_position,
|
||||||
|
undo=True
|
||||||
|
)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
Loading…
Reference in a new issue