目录
一、基本类的创建
在一个标准的迷宫中,需要有三个主要的东西,人物、墙以及出口,其中墙和出口构成了主要的迷宫。下面,依次展示三个类的构建
import pygame
class Wall(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.image.load('wall.png').convert_alpha()
self.CELL_SIZE = 20 #图片的大小
self.rect = self.image.get_rect()
self.rect.x = x * self.CELL_SIZE
self.rect.y = y * self.CELL_SIZE
为了更好地展示效果,引入了pygame库,顺手搞了个游戏。下面就是迷宫的墙所用的图片,大小为20*20
墙是不用动的,所以我们不用加入移动的相关属性。
接下来是终点类的创建
import pygame
class End(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.image.load('exit.png').convert_alpha()
self.CELL_SIZE = 20 # 图片的大小
self.rect = self.image.get_rect()
self.rect.x = x * self.CELL_SIZE
self.rect.y = y * self.CELL_SIZE
def draw(self, screen):
screen.blit(self.image, self.rect)
终点类和墙类其实是差不多的,属性也基本一致,图片如下(终点图片有所借鉴):
接下来是人物
import pygame
from Maze_settings import Maze
Maze = Maze()
WIDTH, HEIGHT = Maze.WIDTH, Maze.HEIGHT
class player(pygame.sprite.Sprite):
CELL_SIZE = 20
def __init__(self, x, y):
super().__init__()
self.image = pygame.image.load('man.png').convert_alpha()
self.rect = self.image.get_rect()
self.rect.x = x * self.CELL_SIZE
self.rect.y = y * self.CELL_SIZE
def move(self, dx, dy, maze):
new_x = self.rect.x + dx * self.CELL_SIZE
new_y = self.rect.y + dy * self.CELL_SIZE
if 0 <= new_x < WIDTH and 0 <= new_y < HEIGHT and maze[new_y // self.CELL_SIZE][new_x // self.CELL_SIZE] == 0 :
self.rect.x = new_x
self.rect.y = new_y
def move_pc(self, go_x, go_y):
self.rect.x = go_x
self.rect.y = go_y
def draw(self, screen):
screen.blit(self.image, self.rect)
人物类除了一些和图像有关的基本属性之外,还多了移动的属性,这里的move函数用于玩家控制下的人物移动,move_pc用于电脑控制。人物图片如下:
那么,基本类的创建就完成了。
二、随机迷宫生成
然而,为了实现每次迷宫的创建都是随机的,我们不能将墙创建在固定的地方,下面引入一个迷宫设置类,实现用数组来确定墙的位置。
import pygame
import random
class Maze:
CELL_SIZE = 20
WIDTH = 800
HEIGHT = 600
def __init__(self):
pass
def generate_maze(self):
width = self.WIDTH // self.CELL_SIZE
height = self.HEIGHT // self.CELL_SIZE
maze = [[1] * width for _ in range(height)]
start_x, start_y = 1, 1
end_x, end_y = width - 2, height - 2
def visit(x, y):
maze[y][x] = 0
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
random.shuffle(directions)
for dx, dy in directions:
new_x, new_y = x + 2 * dx, y + 2 * dy
if 0 <= new_x < width and 0 <= new_y < height and maze[new_y][new_x] == 1:
maze[y + dy][x + dx] = 0
visit(new_x, new_y)
visit(start_x, start_y)
maze[start_y][start_x] = 0
maze[end_y][end_x] = 0
return maze
这个类用于迷宫的初始化,主要用于获取墙数组,确定墙创建时的位置。visit函数用深度优先的方式访问了迷宫,将访问过的点置零代表过道,每次跳跃访问,目的是给墙留出创建的空间。
三、最后效果实现
我们最后在display下实现所有效果
# 导入库
import pygame
import sys
import random
import time
import copy
from end import End
from wall import Wall
from Player import player
from Maze_settings import Maze
WIDTH = Maze.WIDTH
HEIGHT = Maze.HEIGHT
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
CELL_SIZE = player.CELL_SIZE
Maze = Maze()
# 游戏循环类
class MazeGame:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('迷宫游戏')
self.clock = pygame.time.Clock()
self.maze = Maze.generate_maze()
self.maze_book = copy.deepcopy(self.maze)
self.maze_book[1][1] = 1
self.directions = [(1, 0), (0, -1), (-1, 0), (0, 1)]
self.player = player(1, 1)
self.walls = pygame.sprite.Group()
self.end = End((WIDTH // CELL_SIZE) - 2, (HEIGHT // CELL_SIZE) - 2)
self.create_walls()
self.start_time = pygame.time.get_ticks()
#self.run_game_player()
#self.run_game_pc(20, 20)
def create_walls(self):
for y in range(len(self.maze)):
for x in range(len(self.maze[y])):
if self.maze[y][x] == 1 :
wall = Wall(x, y)
self.walls.add(wall)
def handle_events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
self.player.move(0, -1, self.maze)
elif event.key == pygame.K_DOWN:
self.player.move(0, 1, self.maze)
elif event.key == pygame.K_LEFT:
self.player.move(-1, 0, self.maze)
elif event.key == pygame.K_RIGHT:
self.player.move(1, 0, self.maze)
def check_win(self):
if pygame.sprite.collide_rect(self.player, self.end):
end_time = pygame.time.get_ticks()
elapsed_time = (end_time - self.start_time) // 1000
print(f'You win! Time taken: {elapsed_time} seconds')
pygame.quit()
sys.exit()
def draw(self):
self.screen.fill(BLACK)
self.walls.draw(self.screen)
self.end.draw(self.screen)
self.player.draw(self.screen)
pygame.display.flip()
def run_game_player(self):
while True:
self.handle_events()
self.check_win()
self.clock.tick(60)
self.draw()
def run_game_pc(self, start_x, start_y):
stack = [[start_x, start_y, 0]]
while stack:
now_x, now_y, now_di = stack.pop()
self.player.move_pc(now_x, now_y)
self.draw()
time.sleep(0.08)
while now_di < 4:
go_x, go_y = now_x + self.directions[now_di][1] * CELL_SIZE, now_y + self.directions[now_di][0] * CELL_SIZE
if 0 <= go_x < WIDTH and 0 <= go_y < HEIGHT and self.maze_book[go_y // CELL_SIZE][go_x // CELL_SIZE] == 0:
stack.append([go_x, go_y, 0])
print(stack)
now_x, now_y = go_x, go_y
self.maze_book[now_y // CELL_SIZE][now_x // CELL_SIZE] = 1
self.player.move_pc(now_x, now_y)
now_di = 0
self.draw()
self.check_win()
time.sleep(0.03)
else :
now_di += 1
if __name__ == '__main__':
game = MazeGame()
其中电脑运行游戏的部分用于展示深度优先遍历迷宫的效果,不用进行操作,到达终点会自己退出,将函数放在类的初始化中,就不用另外调用了,当对象被创建时就会自动运行。
最后一句话的意思是,如果该文件直接被运行的话,就创建这个对象(实现所有效果)。