资讯专栏INFORMATION COLUMN

python实现地牢迷宫生成

fantix / 2954人阅读

摘要:实现地牢迷宫生成基本属性生成房间生成墙壁生成门口生成通道基本属性定义当前地牢的等级,地图长宽,房间数量,房间的最小最大长度,如下生成房间编写随机生成房间,限制最多循环次数,为了简单起见,先做一个不会重叠的房间。

基本属性

定义当前地牢的等级,地图长宽,房间数量,房间的最小最大长度,如下

class Map:    def __init__(self):        self.width = 30        self.heigh = 30        self.level = 1        self.roomNum = 5        self.map = np.zeros((self.heigh,self.width))        self.roomMin = 3        self.roomMax = 11

生成房间

编写initRoom()随机生成房间,限制最多循环次数,为了简单起见,先做一个不会重叠的房间。基本思路是:随机房间的中心点,随机房间的长宽,再进行判断房间有无重叠(在后续会生成通道,简单起见在这里也保证房间不会紧贴),若无重叠,房间有效,房间数加1。贴代码

    def initRoom(self):        count = 0        roomCount = 1        while True:            count += 1            if count > 300:                break            if roomCount > self.roomNum:                break            x = random.randint(1,self.width-1)            y = random.randint(1,self.heigh-1)            wd = random.randint(self.roomMin,self.roomMax)            ht = random.randint(self.roomMin, self.roomMax)            r1 = ceil(y - ht/2)            r2 = ceil(y + ht/2)            c1 = ceil(x - wd/2)            c2 = ceil(x + wd/2)            if r1 < 1:                r1 = 1            if r2 >= self.heigh - 1:                r2 = self.heigh - 2            if c1 < 1:                c1 = 1            if c2 >= self.width - 1:                c2 = self.width - 2            w = c2 - c1 + 1            h = r2 - r1 + 1            if h / w >= 3 or w / h >= 3: #保证房间不是细长的                continue            judge = self.isValidRoom(r1,r2,c1,c2)            if judge == 0:                roomCount += 1                self.room.append(Room(r1,r2,c1,c2))                for i in range(r1,r2):                    for j in range(c1,c2):                        self.map[i,j] = 1                            def isValidRoom(self,r1,r2,c1,c2):        #检测有无覆盖        for i in range(r1,r2):            for j in range(c1,c2):                if self.map[i,j] == 1:                    return -1        #检测有无紧贴房间        for i in range(r1,r2):            if self.map[i,c1-1] == 1 or self.map[i,c2+1] == 1:                return 2        for i in range(c1,c2):            if self.map[r1-1,i] == 1 or self.map[r2+1,i] == 1:                return 2        return 0

看一下效果

生成墙壁

编写initTile()生成包围房间和通道的墙壁,直接贴代码

    def initTile(self):        offset = [[-1,0],[0,-1],[1,0],[0,1],[-1,-1],[1,1],[1,-1],[-1,1]]        for i in range(self.heigh):            for j in range(self.width):                if self.map[i,j] == 0:                    tag = 0                    for it in offset:                        if i+it[0] >= self.heigh or j+it[1] >= self.width or i+it[0] < 0 or j+it[1] < 0:                            continue                        if self.map[i+it[0],j+it[1]] != 3 and self.map[i+it[0],j+it[1]] != 4:                            tag += self.map[i+it[0],j+it[1]]                    if tag:                        self.map[i,j] = 3

效果

生成门口

随机选取房间的一个外围点当做房门,思路是在房间的长宽内随机两个数作为偏移量,预定义好四个方向的覆盖模板对偏移量进行加权和偏置,在这里我编写房间的类,加进地图的属性列表里。
除此之外,房间连通的思路是:在所有房间列表中随机抽出两个房间,将这两个房间连通,再随机选一个房间加回原来的房间列表,直至最后列表里只剩下一个房间。那么现在先来生成房门,代码如下

class Room():    def __init__(self,r1,r2,c1,c2):        w = c2 - c1        h = r2 - r1        self.width = w        self.height = h        self.cx = c1 + ceil(w/2)        self.cy = r1 + ceil(h/2)        self.xStart = c1        self.xEnd = c2 - 1        self.yStart = r1        self.yEnd = r2 - 1    def randomTile(self):        direction = random.randint(0,3)        dir = [[0,1,-1,0],[1,0,0,-1],[1,0,0,self.height],[0,1,self.width,0]]        x_off = random.randint(0,self.width-1)        y_off = random.randint(0,self.height-1)        x = self.xStart + x_off*dir[direction][0] + dir[direction][2]        y = self.yStart + y_off*dir[direction][1] + dir[direction][3]        if y == 0 or x == 0:            return self.randomTile()        else:            return [y,x]class Map:    def initPath(self):        #初始化门        rm = self.room.copy()        while len(rm) > 1:            r1 = random.choice(rm)            rm.remove(r1)            r2 = random.choice(rm)            rm.remove(r2)            point0 = r1.randomTile()            while point0[0] == self.heigh-1 or point0[1] == self.width-1:                point0 = r1.randomTile()            self.map[point0[0],point0[1]] = 2            self.door.append(point0)            self.breakTile(point0)            point1 = r2.randomTile()            while point1[0] == self.heigh-1 or point1[1] == self.width-1:                point1 = r2.randomTile()            self.map[point1[0],point1[1]] = 2            self.breakTile(point1)            self.door.append(point1)            rn = random.randint(0,1)            #a*算法寻找从point0到point1的路径            #self.aStar(point0,point1)            if rn == 0:                rm.append(r1)            else:                rm.append(r2)                    def breakTile(self,p):        # 打通堵住的周围的墙壁        if self.map[p[0] - 1, p[1]] == 1 and self.map[p[0] + 1, p[1]] == 3:            self.map[p[0] + 1, p[1]] = 2        elif self.map[p[0], p[1] - 1] == 1 and self.map[p[0], p[1] + 1] == 3:            self.map[p[0], p[1] + 1] = 2        elif self.map[p[0] + 1, p[1]] == 1 and self.map[p[0] - 1, p[1]] == 3:            self.map[p[0] - 1, p[1]] = 2        elif self.map[p[0], p[1] + 1] == 1 and self.map[p[0], p[1] - 1] == 3:            self.map[p[0], p[1] - 1] = 2

看下效果

生成通道

接着完善上述函数,在随机选取房门后,连接两个房门。
在这我选择的是A星算法,打通两个房门,直接上代码

    def aStar(self,p0,p1):        open_list = []        close_list = []        offset = [[-1,0],[0,-1],[1,0],[0,1]]        f = h = abs(p0[0] - p1[0]) * 10 + abs(p0[1] - p1[1]) * 10        g = 0        def isInClose(p):            for it in close_list:                if it.value[3] == p:                    return True            return False        def isInOpen(p):            for it in open_list:                if it.value[3] == p:                    return True            return False        def findFather(p):            for it in close_list:                if it.value[3] == p:                    return it.value[4]            return [-1,-1]        def findInOpen(p):            for it in open_list:                if it.value[3] == p:                    return it            return None        open_list.append(Node([f,g,h,p0,[-1,-1]]))        while open_list:            #for it in open_list:            #    print(it.value)            open_list.sort(key=(lambda x:x.value[0]))            f_min = open_list[0]            close_list.append(f_min)            open_list.remove(f_min)            for it in offset:                p2 = [f_min.value[3][0]+it[0], f_min.value[3][1]+it[1]]                if p2[0] == p1[0] and p2[1] == p1[1]:                    #找到                    close_list.append(Node([f,g,h,p2,f_min]))                    p_father = f_min.value[3]                    while True:                        self.map[p_father[0],p_father[1]] = 2                        p_father = findFather(p_father)                        if p_father[0] == -1:                            break                    self.map[p0[0], p0[1]] = 4                    return                if p2[0] < 0 or p2[0] >= self.heigh or p2[1] < 0 or p2[1] >= self.width:                    continue                if (self.map[p2[0],p2[1]] != 0 and self.map[p2[0],p2[1]] != 2 and self.map[p2[0],p2[1]] != 4) or isInClose(p2):                    continue                h = abs(p2[0] - p1[0]) * 10 + abs(p2[1] - p1[1]) * 10                g = f_min.value[1] + 10                f = h + g                if not isInOpen(p2):                    open_list.append(Node([f,g,h,p2,f_min.value[3]]))                else:                    #比较最小的G 值                    temp = findInOpen(p2)                    if g < temp.value[1]:                        open_list.remove(temp)                        open_list.append(Node([f,g,h,p2,f_min.value[3]]))

效果

这样,一个随机房间的地牢就已经生成,贴上完整代码


                 
               
              

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/121108.html

相关文章

  • Python怎么实现迷宫生成代码是什么

      小编写这篇文章的主要目的,是给大家去做一个相关的介绍,介绍一下关于其怎么才能够实现python迷宫,那么,我们要使用的话,就要去生成代码了,那么,具体的代码有吗?下面就给大家做一个解答。  作为一项古老的智力游戏,千百年来迷宫都散发着迷人的魅力。但是,手工设计迷宫费时又耗(脑)力,于是,我们有必要制作一个程序:迷宫生成器……  好吧,我编不下去了。但是,从上面的文字中,我们可以看出,我们此次的...

    89542767 评论0 收藏0
  • [Leetcode] Dungeon Game 地牢游戏

    摘要:动态规划复杂度时间空间递归栈思路骑士向右或者向下走,如果血量小于就死掉了,这会使得计算变得很复杂。假设表示点和的血量,表示走到和要扣除的血量。最右下角那个节点没有待逆推的节点,所以我们假设其逆推节点的血量为。 Dungeon Game The demons had captured the princess (P) and imprisoned her in the bottom-r...

    taoszu 评论0 收藏0
  • 用并查集(find-union)实现迷宫算法以及最短路径求解

    摘要:本人邮箱欢迎转载转载请注明网址代码已经全部托管有需要的同学自行下载引言迷宫对于大家都不会陌生那么迷宫是怎么生成已经迷宫要如何找到正确的路径呢用代码又怎么实现带着这些问题我们继续往下看并查集朋友圈有一种算法就做并查集什么意思呢比如现在有零 本人邮箱: 欢迎转载,转载请注明网址 http://blog.csdn.net/tianshi_kcogithub: https://github.c...

    xiangchaobin 评论0 收藏0
  • 快速实现一个简单的canvas迷宫游戏

    摘要:所以我先写了一个样例扔在服务器上,大家可以先体验一下效果用成就感作为驱动力哈哈哈点我体验地址正文实现这个小游戏也不难,让我们想想,一个迷宫游戏有哪些基本要素。迷宫地图的生成,可以借助谷歌的一个迷宫在线生成器来获得。 前言 (最近设计模式看的有点头大,一直面对纯js实在是有些枯燥-_-。所以写一点有趣的东西调剂一下)现在canvas已经不算新鲜了,不过由于日常业务中并不常用,所以实践并不...

    wangdai 评论0 收藏0
  • 快速实现一个简单的canvas迷宫游戏

    摘要:所以我先写了一个样例扔在服务器上,大家可以先体验一下效果用成就感作为驱动力哈哈哈点我体验地址正文实现这个小游戏也不难,让我们想想,一个迷宫游戏有哪些基本要素。迷宫地图的生成,可以借助谷歌的一个迷宫在线生成器来获得。 前言 (最近设计模式看的有点头大,一直面对纯js实在是有些枯燥-_-。所以写一点有趣的东西调剂一下)现在canvas已经不算新鲜了,不过由于日常业务中并不常用,所以实践并不...

    Jackwoo 评论0 收藏0

发表评论

0条评论

fantix

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<