Python Prim 算法 生成迷宫 通过Pygame可视化

前两篇文章,我们使用Prim算法生成了文章,这一次,我们要用Pygame将迷宫的完整生成过程可视化


首先导入模块,这里我们要用到pygame,随机库,sys,time用于减缓速度,threading用于生成迷宫的另一个线程

import pygame
from pygame.locals import *
import random as rd
import sys
import time
import threading

我们用类和对象的形式实现,定义Game类,初始化函数中设置窗口,a和b表示迷宫大小,lineWidth是迷宫墙壁画在窗口中的粗细,创建一个线程,指向createMaze(createMaze的代码下方会补充),然后启动线程

class Game:
    def __init__(self):
        pygame.init()
        self.W,self.H=900,900
        self.screen=pygame.display.set_mode((self.W,self.H),RESIZABLE)

        self.a,self.b=28,39
        self.lineWidth=5
        thread=threading.Thread(target=self.createMaze,args=(self.a,self.b))
        thread.start()

创建listen函数,用于监听事件,refreshWindow函数用于在拖动窗口后可以及时更新绘制迷宫每个块的大小(self.width和self.height)

    def listen(self):
        for event in pygame.event.get():
            if event.type==QUIT:
                sys.exit()
    
    def refreshWindow(self):
        self.W,self.H=self.screen.get_width(),self.screen.get_height()
        self.width=self.W/self.a
        self.height=self.H/self.b

接下来是创建迷宫的代码,在上一篇遍历墙生成迷宫的时候,我们已经将代码完整写出来了,只要修改一小部分内容即可,要修改的地方如下:

在函数参数中添加self

def createMaze(self,a,b):

然后,把函数中的maze全部改为self.maze,直接存入类变量中

这里不再展示代码,需要算法代码的可以查看我的上一篇文章:

Python Prim 算法 生成迷宫_Leleprogrammer的博客-CSDN博客Python Prim算法 通过遍历墙来生成迷宫,快来看看吧!https://blog.csdn.net/leleprogrammer/article/details/125472436?spm=1001.2014.3001.5501或者是在文末的最终代码中复制,要学习算法原理的,查看上一篇文章即可

接下来,draw函数,用于绘制迷宫,这里代码不会太难,就不做太多讲解

    def draw(self):
        self.screen.fill((255,255,255))
        for (n,face),is_wall in self.maze.items():
            if is_wall:
                y=n//self.a
                x=n%self.a
                absX=x*self.width
                absY=y*self.height
                if face=="u":
                    pygame.draw.line(self.screen,(0,0,0),(absX,absY),(absX+self.width,absY),self.lineWidth)
                if face=="d":
                    pygame.draw.line(self.screen,(0,0,0),(absX,absY+self.height),(absX+self.width,absY+self.height),self.lineWidth)
                if face=="l":
                    pygame.draw.line(self.screen,(0,0,0),(absX,absY),(absX,absY+self.height),self.lineWidth)
                if face=="r":
                    pygame.draw.line(self.screen,(0,0,0),(absX+self.width,absY),(absX+self.width,absY+self.height),self.lineWidth)

然后是run函数,主循环

    def run(self):
        while True:
            self.listen()
            self.draw()
            pygame.display.update()

用于显示文字的函数,这里没有用到,可以不加上,这里加上去是为了后续利用此框架编写游戏,这里还是把这个显示文字的函数给大家

    @staticmethod
    def print_text(name,size,text,color):
        font=pygame.font.SysFont(name,size)
        image=font.render(text,True,color)
        return image

最后,添加这段启动的代码

if __name__ == '__main__':
    game=Game()
    game.run()

这样就好啦!

最终代码(可供参考)

import pygame
from pygame.locals import *
import random as rd
import sys
import time
import threading

class Game:
    def __init__(self):
        pygame.init()
        self.W,self.H=900,900
        self.screen=pygame.display.set_mode((self.W,self.H),RESIZABLE)
        pygame.display.set_caption("Find the Way")

        self.a,self.b=28,39
        self.lineWidth=5
        self.refreshWindow()
        thread=threading.Thread(target=self.createMaze,args=(self.a,self.b))
        thread.start()

    def refreshWindow(self):
        self.W,self.H=self.screen.get_width(),self.screen.get_height()
        self.width=self.W/self.a
        self.height=self.H/self.b

    def listen(self):
        for event in pygame.event.get():
            if event.type==QUIT:
                sys.exit()

    def createMaze(self,a,b):
        self.maze={}
        for n in range(a*b):
            for face in ["u","d","l","r"]:
                self.maze[(n,face)]=1
        history=[]
        walls=[]
        block=rd.choice(list(self.maze.keys()))[0]
        history.append(block)
        for face in ["u","d","l","r"]:
            walls.append((block,face))
        while len(walls)!=0:
            time.sleep(0.001)
            wall=rd.choice(walls)
            twoBlocks=[wall[0]]
            faces=[wall[1]]
            if wall[1]=="u":
                if wall[0]-a<0:
                    twoBlocks.append(None)
                else:
                    twoBlocks.append(wall[0]-a)
                    faces.append("d")
            elif wall[1]=="r":
                if (wall[0]+1)%a!=0:
                    twoBlocks.append(wall[0]+1)
                    faces.append("l")
                else:
                    twoBlocks.append(None)
            elif wall[1]=="l":
                if wall[0]%a!=0:
                    twoBlocks.append(wall[0]-1)
                    faces.append("r")
                else:
                    twoBlocks.append(None)
            elif wall[1]=="d":
                if wall[0]+a>len(self.maze)/4-1:
                    twoBlocks.append(None)
                else:
                    twoBlocks.append(wall[0]+a)
                    faces.append("u")
            ins=[]
            infaces=[]
            for i,oneBlock in enumerate(twoBlocks):
                if oneBlock in history:
                    ins.append(oneBlock)
                    infaces.append(faces[i])
            if len(ins)==1:
                mirrorFace=None
                if infaces[0]=="u":
                    mirrorFace="d"
                elif infaces[0]=="d":
                    mirrorFace="u"
                elif infaces[0]=="r":
                    mirrorFace="l"
                elif infaces[0]=="l":
                    mirrorFace="r"
                if not (None in twoBlocks):
                    self.maze[(ins[0],infaces[0])]=0
                    other=None
                    if ins[0]==twoBlocks[0]:
                        other=twoBlocks[1]
                    else:
                        other=twoBlocks[0]
                    self.maze[(other,mirrorFace)]=0
                    walls.remove(wall)
                    history.append(other)
                    for face in ["u","l","r","d"]:
                        if self.maze.get((other,face))==1 and not ((other,face) in walls):
                            walls.append((other,face))
                else:
                    walls.remove(wall)
                    continue
            elif len(ins)==2:
                walls.remove(wall)

    def draw(self):
        self.screen.fill((255,255,255))
        for (n,face),is_wall in self.maze.items():
            if is_wall:
                y=n//self.a
                x=n%self.a
                absX=x*self.width
                absY=y*self.height
                if face=="u":
                    pygame.draw.line(self.screen,(0,0,0),(absX,absY),(absX+self.width,absY),self.lineWidth)
                if face=="d":
                    pygame.draw.line(self.screen,(0,0,0),(absX,absY+self.height),(absX+self.width,absY+self.height),self.lineWidth)
                if face=="l":
                    pygame.draw.line(self.screen,(0,0,0),(absX,absY),(absX,absY+self.height),self.lineWidth)
                if face=="r":
                    pygame.draw.line(self.screen,(0,0,0),(absX+self.width,absY),(absX+self.width,absY+self.height),self.lineWidth)

    def run(self):
        while True:
            self.listen()
            self.draw()
            self.refreshWindow()
            pygame.display.update()

    @staticmethod
    def print_text(name,size,text,color):
        font=pygame.font.SysFont(name,size)
        image=font.render(text,True,color)
        return image

if __name__ == '__main__':
    game=Game()
    game.run()

本次的教学到这里也就结束啦!喜欢我的文章的,别忘了多多点赞关注支持哦!谢谢~

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值