114 lines
3.4 KiB
Python
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 |