added maze generator
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -58,3 +58,4 @@ docs/_build/
|
|||||||
# PyBuilder
|
# PyBuilder
|
||||||
target/
|
target/
|
||||||
|
|
||||||
|
.idea/
|
||||||
83
game.py
Normal file
83
game.py
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import sys
|
||||||
|
from itertools import product
|
||||||
|
|
||||||
|
import pygame
|
||||||
|
from pygame.locals import *
|
||||||
|
from maze import Maze
|
||||||
|
|
||||||
|
pygame.init()
|
||||||
|
vec = pygame.math.Vector2 # 2 for two dimensional
|
||||||
|
|
||||||
|
HEIGHT = 450
|
||||||
|
WIDTH = 400
|
||||||
|
|
||||||
|
FPS = 60
|
||||||
|
|
||||||
|
FramePerSec = pygame.time.Clock()
|
||||||
|
|
||||||
|
displaysurface = pygame.display.set_mode((WIDTH, HEIGHT))
|
||||||
|
pygame.display.set_caption("Game")
|
||||||
|
|
||||||
|
SCREEN_BUFFER = 10
|
||||||
|
MAZE_SIZE = 15
|
||||||
|
GRID_SIZE = 25
|
||||||
|
|
||||||
|
|
||||||
|
class Player(pygame.sprite.Sprite):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.surf = pygame.Surface((30, 30))
|
||||||
|
self.surf.fill((0, 255, 0))
|
||||||
|
self.rect = self.surf.get_rect(center=(10, 420))
|
||||||
|
|
||||||
|
|
||||||
|
class MazeWall(pygame.sprite.Sprite):
|
||||||
|
def __init__(self, wall):
|
||||||
|
wall_width = 2
|
||||||
|
super().__init__()
|
||||||
|
start_cell, end_cell = wall
|
||||||
|
x,y = start_cell
|
||||||
|
vertical = start_cell[1] == end_cell[1]
|
||||||
|
if vertical:
|
||||||
|
self.surf = pygame.Surface((wall_width, GRID_SIZE))
|
||||||
|
else:
|
||||||
|
self.surf = pygame.Surface((GRID_SIZE, wall_width))
|
||||||
|
self.surf.fill((0, 0, 255))
|
||||||
|
if vertical:
|
||||||
|
self.rect = self.surf.get_rect(midtop=((x+1) * GRID_SIZE + SCREEN_BUFFER, y * GRID_SIZE + SCREEN_BUFFER))
|
||||||
|
else:
|
||||||
|
self.rect = self.surf.get_rect(midleft=(x * GRID_SIZE + SCREEN_BUFFER, (y + 1) * GRID_SIZE + SCREEN_BUFFER))
|
||||||
|
|
||||||
|
|
||||||
|
all_sprites = pygame.sprite.Group()
|
||||||
|
|
||||||
|
|
||||||
|
maze_sprites = pygame.sprite.Group()
|
||||||
|
|
||||||
|
maze = Maze(MAZE_SIZE, MAZE_SIZE)
|
||||||
|
|
||||||
|
for wall in maze.walls:
|
||||||
|
wall_sprite = MazeWall(wall)
|
||||||
|
maze_sprites.add(wall_sprite)
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
for event in pygame.event.get():
|
||||||
|
if event.type == QUIT:
|
||||||
|
pygame.quit()
|
||||||
|
sys.exit()
|
||||||
|
# wipe buffer
|
||||||
|
displaysurface.fill((0, 0, 0))
|
||||||
|
# draw border
|
||||||
|
pygame.draw.rect(displaysurface, (255, 0, 0),
|
||||||
|
pygame.Rect((SCREEN_BUFFER, SCREEN_BUFFER, MAZE_SIZE * GRID_SIZE, MAZE_SIZE * GRID_SIZE)), 2)
|
||||||
|
pygame.draw.circle(displaysurface, (0, 255, 0), (25, 25), GRID_SIZE / 3)
|
||||||
|
|
||||||
|
# for entity in all_sprites:
|
||||||
|
# displaysurface.blit(entity.surf, entity.rect)
|
||||||
|
for entity in maze_sprites:
|
||||||
|
displaysurface.blit(entity.surf, entity.rect)
|
||||||
|
|
||||||
|
|
||||||
|
pygame.display.update()
|
||||||
|
FramePerSec.tick(FPS)
|
||||||
75
maze.py
Normal file
75
maze.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import random
|
||||||
|
from itertools import product
|
||||||
|
from typing import Tuple, Set, Union, Any, List, NamedTuple
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
|
||||||
|
class Cell(NamedTuple):
|
||||||
|
x: int
|
||||||
|
y: int
|
||||||
|
|
||||||
|
|
||||||
|
class Wall(NamedTuple):
|
||||||
|
first_cell: Cell
|
||||||
|
second_cell: Cell
|
||||||
|
|
||||||
|
|
||||||
|
class Maze:
|
||||||
|
def __init__(self, width: int, height: int):
|
||||||
|
self.cells = set(Cell(*c) for c in product(range(width), range(height)))
|
||||||
|
self.maze = dict()
|
||||||
|
for cell in self.cells:
|
||||||
|
self.maze[cell] = self.get_neighbours(cell)
|
||||||
|
self.walls = self.get_walls()
|
||||||
|
self.generate_maze()
|
||||||
|
|
||||||
|
def get_neighbours(self, cell: Cell) -> Set[Cell]:
|
||||||
|
diffs = ((0, 1), (0, -1), (1, 0), (-1, 0))
|
||||||
|
return set(Cell(cell.x + x, cell.y + y) for x, y in diffs if Cell(cell.x + x, cell.y + y) in self.cells)
|
||||||
|
|
||||||
|
def get_walls(self) -> Set[Wall]:
|
||||||
|
walls = set()
|
||||||
|
for cell in self.cells:
|
||||||
|
walls.update(set(Wall(*sorted([cell, c])) for c in self.maze[cell]))
|
||||||
|
return walls
|
||||||
|
|
||||||
|
def generate_maze(self) -> None:
|
||||||
|
visited = set()
|
||||||
|
unvisited = list(self.cells)
|
||||||
|
node = random.choice(unvisited)
|
||||||
|
visited.add(node)
|
||||||
|
unvisited.remove(node)
|
||||||
|
while unvisited:
|
||||||
|
random_neighbour = random.choice(list(self.maze[node]))
|
||||||
|
if random_neighbour not in visited:
|
||||||
|
self.walls.remove(Wall(*sorted([node, random_neighbour])))
|
||||||
|
visited.add(random_neighbour)
|
||||||
|
try:
|
||||||
|
unvisited.remove(random_neighbour)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
node = random_neighbour
|
||||||
|
|
||||||
|
def generate_prim_maze(self) -> None:
|
||||||
|
visited = set()
|
||||||
|
node = random.choice(list(self.cells))
|
||||||
|
visited.add(node)
|
||||||
|
removed_walls = set()
|
||||||
|
wall_list = [w for w in self.walls if node in w]
|
||||||
|
while wall_list:
|
||||||
|
random_wall = random.choice(wall_list)
|
||||||
|
wall_list.remove(random_wall)
|
||||||
|
cell1, cell2 = random_wall
|
||||||
|
if (cell1 in visited) != (cell2 in visited):
|
||||||
|
removed_walls.add(random_wall)
|
||||||
|
self.walls.remove(random_wall)
|
||||||
|
visited.add(cell1)
|
||||||
|
visited.add(cell2)
|
||||||
|
wall_list.extend(
|
||||||
|
set(w for w in self.walls if (cell1 in w) or (cell2 in w)).difference(removed_walls)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
maze = Maze(3, 3)
|
||||||
|
pprint(maze.walls)
|
||||||
Reference in New Issue
Block a user