python pygame 游戏实战:Maze 迷宫生成,显示和游戏(附全部代码)

2023-11-07

生成迷宫(maze)的算法有很多种,论坛上有很多这方面的资料可以参考。  这里使用回溯法(backtracking),主要参考Build a 2-player maze game with Python Part 4 - Coding TidBits 

用的是迭代函数(recursive function): 不断寻找周边没有走过的网格(cell), 并随机打通任一边的”墙(wall)".  如果设定SHOW_DRAW = True的话, 可以图像显示整个回溯法过程。 迷宫生成结束后, 图像显示, 并加上一个红球代表玩家, 红球可以走过整个迷宫, 玩法方面, 可以计算红球通过整个迷宫的时间。迷宫的复杂程度可以通过设定其行和列数, 如MAZE_COLS=15, MAZE_ROWS=13

 

全部代码如下:

import random
import pygame
import numpy as np

#Ref;http://www.danduda.com/blog/2018/11/18/Build-a-2-player-maze-game-with-Python-Part-4/
UP,DOWN=-1,1
LEFT,RIGHT=-2,2

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600

MAZE_COLS=15
MAZE_ROWS=13
WALL_SIZE = int(120/max(MAZE_COLS,MAZE_ROWS))  # Pixel size/Wall thickness
WT=WALL_SIZE #used in pygame.time.wait(WT)
CELL_SIZE=4*WALL_SIZE #a cell has only 2 walls: DOWN, RIGHT
MAZE_WIDTH =CELL_SIZE * MAZE_COLS +WALL_SIZE  
MAZE_HEIGHT = CELL_SIZE *MAZE_ROWS+ WALL_SIZE

TOPLEFT_X,TOPLEFT_Y = (SCREEN_WIDTH // 2 - MAZE_WIDTH // 2, SCREEN_HEIGHT // 2 - MAZE_HEIGHT // 2)
x_offset = TOPLEFT_X + WALL_SIZE
y_offset = TOPLEFT_Y + WALL_SIZE   

WALL_COLOR = (18, 94, 32)
MAZE_COLOR = (255, 255, 255)
UNVISITED_COLOR = (0, 0, 0)
PLAYER_COLOR = (255, 0, 0)

SHOW_DRAW = True

class Cell():
    def __init__(self,r,c):
        self.r=r
        self.c=c
        self.visited=False    #True-just visited, not open any wall
        self.walls={UP:False,DOWN:False,LEFT:False,RIGHT:False}
 
class Maze():
    def __init__(self,row=MAZE_ROWS,col=MAZE_COLS):
        self.row=row
        self.col=col
        self.maze= [[Cell(r,c) for c in range(col)] for r in range(row)]
        self.make()       
        self.player= Player(PLAYER_COLOR, (WALL_SIZE * 3) // 2 )                                     
        self.player_sprite = pygame.sprite.RenderPlain(self.player)                    
    def make(self,r0=0,c0=0):    
        direction = {UP: (-1, 0),DOWN: (1, 0),LEFT:(0, -1),RIGHT:(0, 1)}
        current_cell=self.maze[r0][c0]        
        current_cell.visited=True 
        visited_stack=[current_cell]        
        while visited_stack:
            current_cell=visited_stack[-1]  
            un_visited=[]   #unvisited neighbours
            for d, (dr, dc) in direction.items():
                r, c = current_cell.r + dr, current_cell.c + dc
                if (0 <= r < self.row) and (0 <= c < self.col):
                    cell = self.maze[r][c]
                    if not cell.visited:   
                        un_visited.append((d,cell))                     
            if un_visited:                              
                dc,nc=random.choice(un_visited)
                current_cell.walls[dc]=True  #this direction is open
                nc.visited=True
                nc.walls[-dc]=True  
                visited_stack.append(nc)           
            elif len(visited_stack):
                visited_stack.pop()
                
            if SHOW_DRAW:
                self.draw_maze()
                pygame.display.update()
                pygame.time.wait(WT)
                pygame.event.pump()       
              
        #self.maze[0][0].walls[LEFT]=True
        #self.maze[self.row-1][self.col-1].walls[RIGHT] = True 
     
    def draw_maze(self):        
        screen.fill('black')
        pygame.draw.rect(screen, WALL_COLOR, (TOPLEFT_X, TOPLEFT_Y, MAZE_WIDTH, MAZE_HEIGHT))                                        
        for c in range(MAZE_COLS):      #colums 5 x-c
            for r in range(MAZE_ROWS):  # rows 3 y-r
                cell=self.maze[r][c]    
                x=c*CELL_SIZE+ x_offset
                y=r*CELL_SIZE + y_offset
                if cell.visited:                    
                     pygame.draw.rect(screen, MAZE_COLOR, (x, y,3*WALL_SIZE, 3*WALL_SIZE))                                           
                else:                             
                     pygame.draw.rect(screen, UNVISITED_COLOR,(x, y,3*WALL_SIZE, 3*WALL_SIZE)) 
                if cell.walls[DOWN]:
                     pygame.draw.rect(screen, MAZE_COLOR, (x, y+3*WALL_SIZE ,3*WALL_SIZE, WALL_SIZE))                         
                if cell.walls[RIGHT]:
                     pygame.draw.rect(screen, MAZE_COLOR, (x+3*WALL_SIZE, y, WALL_SIZE, 3*WALL_SIZE))
                                 
                                
            
    def can_move(self, direction):
        c=self.player.c
        r=self.player.r
        return self.maze[r][c].walls[direction]        
    def move_up(self):
        if self.can_move(UP):
            self.player.r-=1
    def move_right(self):
        if self.can_move(RIGHT):
            self.player.c+=1
    def move_down(self):
        if self.can_move(DOWN):
            self.player.r+=1
    def move_left(self):
        if self.can_move(LEFT): 
            self.player.c-=1    
 
    def checkEvents(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()   
            keys = pygame.key.get_pressed()
            if keys[pygame.K_LEFT]:
                self.move_left()
            if keys[pygame.K_RIGHT]:
                self.move_right()
            if keys[pygame.K_UP]:
                self.move_up()
            if keys[pygame.K_DOWN]:
                self.move_down()                
    def update(self):
        self.draw_maze()     
        #self.draw_grid()
        self.player.update()
        self.player_sprite.draw(screen)                              

class Player(pygame.sprite.Sprite):
    def __init__(self, color, radius, r=0, c=0):
        # Call the parent class (Sprite) constructor
        super().__init__()
        self.r = r
        self.c = c
        self.image = pygame.Surface([radius * 2, radius * 2])
        self.image.fill(MAZE_COLOR)
        self.image.set_colorkey(MAZE_COLOR)
        pygame.draw.circle(self.image, color, (radius, radius), radius)                  
        self.rect = self.image.get_rect()
        self.update() 
    def update(self):
        self.rect.x = x_offset+self.c*CELL_SIZE
        self.rect.y = y_offset+self.r*CELL_SIZE
            
pygame.init()
screen=pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
A=Maze()
while 1:
    screen.fill((0,0,0))
    A.checkEvents()
    A.update()
    pygame.display.update()

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python pygame 游戏实战:Maze 迷宫生成,显示和游戏(附全部代码) 的相关文章

随机推荐

  • 【业务功能篇36】Springboot+activiti7 工作流引擎

    业务场景 前段时间总结的有一个告警工单流程 我们都是直接自己建表 状态节点 操作节点 都是自定义设计的 而到后面会有很多的工单流程 比如创建一个遗留问题电子流 指定处理人进行分析闭环 等等多种电子流 后期重复的开发工作以及维护工作会越来越多
  • C语言 递归实现汉诺塔问题 【图文讲解、简单易懂】

    汉诺塔问题是我们在学习函数递归时常遇见的一类问题 那么如何用简单易懂的思路来解决汉诺塔问题呢 下面我会为大家进行讲解 目录 汉诺塔是什么 汉诺塔的来源 用C语言实现汉诺塔 汉诺塔问题分析思路 用代码实现汉诺塔问题 总结 汉诺塔是什么 汉诺塔
  • 1 ubuntu18 docker配置与安装 镜像加速配置

    0 背景 搭建环境到创建第一个容器 1 搭建环境 需求 1 安装docker环境 2 镜像加速站 3 多台主机安装docker 1 1 docker环境 电脑为老联想电脑 cpu 2 7ghz 内存12GB 用vmware搞了两个ubunt
  • NOIP2014 Day2 模拟赛赛后总结&题解

    考试时的心态 还能有什么心态 考炸了嘛 题解 第一题 无线电通讯 水题 直接模拟 就不多说了 第二题 图论水题 其实也挺水的 只要倒着来广搜一遍 把能到达的边标记一下就可以了 接下来从起点出发BFS一遍就可以了 但是我考试的时候没有想那么多
  • 现在网红里骗子占一半。

    大家好 我是北妈 0 每天和身边朋友还有读者交流 打工没有出路 几乎成为打工人的普遍共识 也有越来越多人尝试或已经在实践打造个人 IP 超级个体品牌这条路 我的星球桃花岛 还有群也很多人每天在交流怎么做个人ip或者视频自媒体 大家都很想破圈
  • C++ STL::list常用操作及底层实现(中2)——实现list常用操作之删除(erase、remove、pop_front、pop_back、clear)

    list 常用操作及自底层实现 1 erase 按链表迭代器删除 1 1函数格式1 iterator erase iterator position 1 2函数格式2 iterator erase iterator first iterat
  • 用TensorFlow编写训练模型的程序——快速导读

    1 训练模型是怎么回事 训练模型是指 通过程序的反复迭代来修正神经网络中各个节点的值 从而实现具有一定拟合效果的算法 在训练神经网络的过程中 数据流有两个方向 正向和反向 正向负责预测生成结果 沿着网络节点的运算方向一层层计算下去 反向负责
  • 如何高速安装jetson-inference,一步到位,避免踩坑!

    踩了很长时间的坑 终于弄明白怎么高速下载jetson inference 来源 安装jetson inference 自动下载模型 满速下载起飞 解决下载模型被墙问题 奈流云何的博客 CSDN博客 需要将Github的仓库复制到Gitee上
  • 使用stm32的ADC得到准确的电压

    一 引脚多一点的stm32单片机存在VREF 和VREF 引脚 由上面的供电图知道 如果存在VREF 和VREF 引脚 那么ADC是由这两个引脚供电的 ADC的采集电压范围为 VREF
  • 理解Vue插槽

    引言 在Vue开发中 我们多采用组件化开发 组件化开发最大特点就是对页面结构化划分 组件的复用 而在实际中 页面对组件的需求或许也稍有不同 那么就需要一种需求 为页面定制组件 解决的方式便是通过插槽 实例
  • Java动态执行计算表达式利器 -- ScriptEngine

    在通过配置文件对系统进行参数配置时 有时需要更好的理解参数值的具体意义 往往采用计算表达式的方式设置 例如1天换成秒数为86400 如果写成24 60 60就很清晰的表达是一天的秒数 但是这个表达式通过properties的方式获取为字符串
  • Celery ValueError: not enough values to unpack (expected 3, got 0)

    目录 1 Celery ValueError not enough values to unpack expected 3 got 0 2 AttributeError async 1 Celery ValueError not enoug
  • 使用CUDA实现零拷贝技术

    使用CUDA实现零拷贝技术 零拷贝技术是指在内存和设备之间传输数据时 不需要显式地将数据从内存复制到设备的过程 从而提高数据传输效率 本文将介绍如何使用CUDA实现零拷贝技术 并提供示例代码 在使用CUDA进行图像处理时 通常需要将数据从主
  • 【计算机视觉

    文章目录 一 SqueezeNet 二 Inception v3 三 Visual Geometry Group 19 Layer CNN 四 MobileNetV1 五 Data efficient Image Transformer 六
  • 【CentOS7】开机自启动三种方法

    有个需求 比如说我想要执行开机杀毒程序 就需要去做开机自启动相关操作 准备工作 在 usr local目录下建立killviruses sh 前提 安装病毒库 vi killviruses sh 键入以下内容 前提 已安装ClamAV cl
  • js纯ajax,纯js 的Ajax 请求

    纯js 的Ajax 请求 2018 02 24 126 var XMLHttpReq function createXMLHttpRequest try XMLHttpReq new ActiveXObject Msxml2 XMLHTTP
  • 深度学习优化算法大全系列3:NAG(Nesterov Acceleration Gradient)

    1 NAG与SGD M的区别 NAG全称为Nesterov Accelerated Gradient 是在SGD Momentum基础进一步优化所得 前面的文章我们提到过 SGD M主要是利用历史累积动量来代替当前梯度从而达到减小震荡 加速
  • python自定义assert抛出的异常

    方法一 常用于assert失败后的提示用语 assert 1 gt 4 what 异常为 AssertionError what 方法二 常用于assert失败后推断导致的报错 try assert 1 gt 4 except Except
  • 前端实现导出Excel

    一 准备文件 1 创建excel文件夹 excel Blob js Export2Excel js 2 Blob js文件夹内容 eslint disable Blob js global self unescape jslint bitw
  • python pygame 游戏实战:Maze 迷宫生成,显示和游戏(附全部代码)

    生成迷宫 maze 的算法有很多种 论坛上有很多这方面的资料可以参考 这里使用回溯法 backtracking 主要参考Build a 2 player maze game with Python Part 4 Coding TidBits