2026-rff_mp/kornevma/docs/2/maze_generator.py

114 lines
3.4 KiB
Python

import random
from collections import deque
from maze import Maze, Cell
def empty_maze(width, height):
maze = Maze(width, height)
for x in range(width):
for y in range(height):
maze.grid[x][y].isWall = False
maze.start = maze.getCell(0, 0)
maze.start.isStart = True
maze.exit = maze.getCell(width-1, height-1)
maze.exit.isExit = True
return maze
def random_maze(width, height, wall_prob=0.3, ensure_path=True):
while True:
maze = Maze(width, height)
for x in range(width):
for y in range(height):
if random.random() < wall_prob:
maze.grid[x][y].isWall = True
else:
maze.grid[x][y].isWall = False
start_cell = maze.getCell(0, 0)
exit_cell = maze.getCell(width-1, height-1)
start_cell.isWall = False
start_cell.isStart = True
exit_cell.isWall = False
exit_cell.isExit = True
maze.start = start_cell
maze.exit = exit_cell
if not ensure_path:
return maze
if _path_exists(maze, start_cell, exit_cell):
return maze
def no_path_maze(width, height):
maze = empty_maze(width, height)
exit_cell = maze.exit
for dx, dy in [(-1,0),(1,0),(0,-1),(0,1)]:
nx, ny = exit_cell.x + dx, exit_cell.y + dy
neighbor = maze.getCell(nx, ny)
if neighbor:
neighbor.isWall = True
return maze
def recursive_division_maze(width, height):
if width % 2 == 0:
width += 1
if height % 2 == 0:
height += 1
maze = Maze(width, height)
for x in range(width):
for y in range(height):
maze.grid[x][y].isWall = False
maze.start = maze.getCell(0, 0)
maze.start.isStart = True
maze.exit = maze.getCell(width-1, height-1)
maze.exit.isExit = True
for x in range(width):
maze.getCell(x, 0).isWall = True
maze.getCell(x, height-1).isWall = True
for y in range(height):
maze.getCell(0, y).isWall = True
maze.getCell(width-1, y).isWall = True
maze.start.isWall = False
maze.exit.isWall = False
def divide(x1, y1, x2, y2):
if x2 - x1 < 2 or y2 - y1 < 2:
return
vertical = (x2 - x1) > (y2 - y1) and (x2 - x1) >= 2
if vertical:
wall_x = random.randrange(x1 + 1, x2, 2)
hole_y = random.randrange(y1, y2 + 1, 2) if (y2 - y1) > 0 else y1
for y in range(y1, y2 + 1):
if y != hole_y:
maze.getCell(wall_x, y).isWall = True
divide(x1, y1, wall_x - 1, y2)
divide(wall_x + 1, y1, x2, y2)
else:
wall_y = random.randrange(y1 + 1, y2, 2)
hole_x = random.randrange(x1, x2 + 1, 2) if (x2 - x1) > 0 else x1
for x in range(x1, x2 + 1):
if x != hole_x:
maze.getCell(x, wall_y).isWall = True
divide(x1, y1, x2, wall_y - 1)
divide(x1, wall_y + 1, x2, y2)
divide(0, 0, width-1, height-1)
return maze
def _path_exists(maze, start, exit_cell):
visited = set()
queue = deque([start])
visited.add(start)
while queue:
cur = queue.popleft()
if cur == exit_cell:
return True
for n in maze.getNeighbors(cur):
if n not in visited:
visited.add(n)
queue.append(n)
return False