迷宫游戏(深度优先搜索展示)

目录

一、基本类的创建

二、随机迷宫生成

三、最后效果实现


一、基本类的创建

在一个标准的迷宫中,需要有三个主要的东西,人物、墙以及出口,其中墙和出口构成了主要的迷宫。下面,依次展示三个类的构建

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()

其中电脑运行游戏的部分用于展示深度优先遍历迷宫的效果,不用进行操作,到达终点会自己退出,将函数放在类的初始化中,就不用另外调用了,当对象被创建时就会自动运行。

最后一句话的意思是,如果该文件直接被运行的话,就创建这个对象(实现所有效果)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值