Skip to content

Instantly share code, notes, and snippets.

@danielbreves
Created July 6, 2025 05:10
Show Gist options
  • Select an option

  • Save danielbreves/c46c3e397f54ff2f823997f7c6640500 to your computer and use it in GitHub Desktop.

Select an option

Save danielbreves/c46c3e397f54ff2f823997f7c6640500 to your computer and use it in GitHub Desktop.
from collections import defaultdict, deque
import enum
import os
import random
from time import sleep
VISUALISATION_DELAY = 0.1 # seconds
class MazeEnum(enum.Enum):
WALL = "#"
PATH = " "
POS = "."
class Maze:
def __init__(self, width, height):
self.width = width
self.height = height
self.start = (0, 1)
self.end = (width - 1, height - 2)
self.maze = defaultdict(lambda: MazeEnum.WALL)
def __getitem__(self, pos):
return self.maze[pos]
def __setitem__(self, pos, value):
self.maze[pos] = value
def __str__(self):
return self.to_str()
def to_str(self, pos=None, to_print=False, clear=False, sleep_duration=0.0):
if clear:
os.system('clear')
output = []
for y in range(self.height):
row = []
for x in range(self.width):
if pos and ((x, y) == pos or (x, y) in pos):
row.append(MazeEnum.POS.value)
else:
row.append(self.maze[(x, y)].value)
output.append(' '.join(row))
result = '\n'.join(output)
if to_print:
print(result)
if sleep_duration > 0:
sleep(sleep_duration)
return result
def solve(self, visualize=False):
# queue is a tuple containing a cell's coordinates and the path taken to reach it
queue = deque([(self.start, [self.start])])
visited = set(self.start)
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
while queue:
(x, y), path = queue.popleft()
if (x, y) == self.end:
if visualize:
self.to_str(path, to_print=True, clear=True, sleep_duration=VISUALISATION_DELAY)
return path
for dx, dy in directions:
nx, ny = x + dx, y + dy
if (
0 <= nx < self.width
and 0 <= ny < self.height
and self.maze[(nx, ny)] == MazeEnum.PATH
and (nx, ny) not in visited
):
visited.add((nx, ny))
new_path = list(path) # store the current path to this point
new_path.append((nx, ny))
if visualize:
self.to_str(path, to_print=True, clear=True, sleep_duration=VISUALISATION_DELAY)
queue.append(((nx, ny), new_path))
return None # No path found
def generate(self):
def visit(x, y):
self.maze[(x, y)] = MazeEnum.PATH
directions = [(0, 2), (2, 0), (0, -2), (-2, 0)]
random.shuffle(directions)
for dx, dy in directions:
nx, ny = x + dx, y + dy
if 0 <= nx < self.width and 0 <= ny < self.height and self.maze[(nx, ny)] == MazeEnum.WALL:
self.maze[(x + dx // 2, y + dy // 2)] = MazeEnum.PATH
visit(nx, ny)
visit(1, 1)
self.maze[self.start] = MazeEnum.PATH
self.maze[self.end] = MazeEnum.PATH
return self.maze
def main():
width, height = 31, 31 # Example dimensions, must be odd numbers
maze = Maze(width, height)
maze.generate()
maze.solve(visualize=True)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment