亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

python實(shí)現(xiàn)地牢迷宮生成的完整步驟

 更新時(shí)間:2021年09月26日 15:56:58   作者:揉揉漆  
這篇文章主要給大家介紹了關(guān)于python實(shí)現(xiàn)地牢迷宮生成的相關(guān)資料,文中通過(guò)示例代碼將實(shí)現(xiàn)的過(guò)程一步步介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

基本屬性

定義當(dāng)前地牢的等級(jí),地圖長(zhǎng)寬,房間數(shù)量,房間的最小最大長(zhǎng)度,如下

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

生成房間

編寫(xiě)initRoom()隨機(jī)生成房間,限制最多循環(huán)次數(shù),為了簡(jiǎn)單起見(jiàn),先做一個(gè)不會(huì)重疊的房間?;舅悸肥牵弘S機(jī)房間的中心點(diǎn),隨機(jī)房間的長(zhǎng)寬,再進(jìn)行判斷房間有無(wú)重疊(在后續(xù)會(huì)生成通道,簡(jiǎn)單起見(jiàn)在這里也保證房間不會(huì)緊貼),若無(wú)重疊,房間有效,房間數(shù)加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: #保證房間不是細(xì)長(zhǎng)的
                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):
        #檢測(cè)有無(wú)覆蓋
        for i in range(r1,r2):
            for j in range(c1,c2):
                if self.map[i,j] == 1:
                    return -1
        #檢測(cè)有無(wú)緊貼房間
        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

看一下效果

生成五個(gè)房間

生成墻壁

編寫(xiě)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

效果

有墻壁的房間

生成門(mén)口

隨機(jī)選取房間的一個(gè)外圍點(diǎn)當(dāng)做房門(mén),思路是在房間的長(zhǎng)寬內(nèi)隨機(jī)兩個(gè)數(shù)作為偏移量,預(yù)定義好四個(gè)方向的覆蓋模板對(duì)偏移量進(jìn)行加權(quán)和偏置,在這里我編寫(xiě)房間的類,加進(jìn)地圖的屬性列表里。

除此之外,房間連通的思路是:在所有房間列表中隨機(jī)抽出兩個(gè)房間,將這兩個(gè)房間連通,再隨機(jī)選一個(gè)房間加回原來(lái)的房間列表,直至最后列表里只剩下一個(gè)房間。那么現(xiàn)在先來(lái)生成房門(mén),代碼如下

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):
        #初始化門(mén)
        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

看下效果

有房門(mén)的房間

生成通道

接著完善上述函數(shù),在隨機(jī)選取房門(mén)后,連接兩個(gè)房門(mén)。

在這我選擇的是A星算法,打通兩個(gè)房門(mén),直接上代碼

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

效果

這樣,一個(gè)隨機(jī)房間的地牢就已經(jīng)生成,貼上完整代碼

import random
import numpy as np
from math import ceil

class Node():
    def __init__(self, val=None):
        if val is None:
            val = [0, 0, 0, [-1, -1], [-1, -1]]
        self.value = val

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 info(self):
        print('r1 c1 r2 c2:  ',self.yStart,self.xStart,self.yEnd,self.xEnd)
        print('cx    cy:     ',self.cx,self.cy)
        print('width height: ',self.width,self.height)

    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 __init__(self):
        self.width = 30
        self.heigh = 30
        self.level = 1
        self.roomNum = 5
        #0 is null, 1 is room, 2 is path, 3 is wall, 4 is door, 5 is up stair, 6 is downstair
        self.map = np.zeros((self.width,self.heigh))
        self.roomMin = 3
        self.roomMax = 11
        self.room = []
        self.door = []

        self.initRoom()
        self.initTile()
        self.initPath()
        #self.initTile()
        #self.initDoor()

    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)
            if wd % 2 == 0:
                wd += 1
            ht = random.randint(self.roomMin, self.roomMax)
            if ht % 2 == 0:
                ht += 1
            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 w == 0:
                continue
            if h == 0:
                continue
            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 initPath(self):
        #初始化門(mén)
        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 initDoor(self):
        for it in self.door:
            self.map[it[0],it[1]] = 4

    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

    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

    def isValidRoom(self,r1,r2,c1,c2):
        #檢測(cè)有無(wú)覆蓋
        for i in range(r1,r2):
            for j in range(c1,c2):
                if self.map[i,j] == 1:
                    return -1
        #檢測(cè)有無(wú)緊貼房間
        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

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

    def printMap(self):
        for i in range(self.heigh):
            for j in range(self.width):
                print(int(self.map[i,j]),end='')
            print()

    def printRoom(self):
        for r in self.room:
            r.info()

if __name__ == '__main__':
    map = Map()
    map.printMap()

可視化一下

地牢

總結(jié) 

到此這篇關(guān)于python實(shí)現(xiàn)地牢迷宮生成的文章就介紹到這了,更多相關(guān)python地牢迷宮生成內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python數(shù)據(jù)可視化圖實(shí)現(xiàn)過(guò)程詳解

    Python數(shù)據(jù)可視化圖實(shí)現(xiàn)過(guò)程詳解

    這篇文章主要介紹了Python數(shù)據(jù)可視化圖實(shí)現(xiàn)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • 使用Python實(shí)現(xiàn)繪制發(fā)散條形圖

    使用Python實(shí)現(xiàn)繪制發(fā)散條形圖

    發(fā)散條形圖用于簡(jiǎn)化多個(gè)組的比較,它許我們比較各組中的數(shù)值,還幫助我們快速地想象出有利的和不利的或積極的和消極的反應(yīng),下面我們就來(lái)看看如何使用Python繪制發(fā)散條形圖吧
    2024-04-04
  • 解決python 執(zhí)行shell命令無(wú)法獲取返回值的問(wèn)題

    解決python 執(zhí)行shell命令無(wú)法獲取返回值的問(wèn)題

    這篇文章主要介紹了解決python 執(zhí)行shell命令無(wú)法獲取返回值的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • Python3爬蟲(chóng)中pyspider的安裝步驟

    Python3爬蟲(chóng)中pyspider的安裝步驟

    在本篇內(nèi)容里小編給大家整理的是一篇關(guān)于Python3爬蟲(chóng)中pyspider的安裝步驟,需要的朋友們可以學(xué)習(xí)參考下。
    2020-07-07
  • Python通過(guò)len函數(shù)返回對(duì)象長(zhǎng)度

    Python通過(guò)len函數(shù)返回對(duì)象長(zhǎng)度

    這篇文章主要介紹了Python通過(guò)len函數(shù)返回對(duì)象長(zhǎng)度,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • python字典setdefault方法和get方法使用實(shí)例

    python字典setdefault方法和get方法使用實(shí)例

    這篇文章主要介紹了python字典setdefault方法和get方法使用實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • python查詢mysql,返回json的實(shí)例

    python查詢mysql,返回json的實(shí)例

    下面小編就為大家分享一篇python查詢mysql,返回json的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • Python 格式化輸出_String Formatting_控制小數(shù)點(diǎn)位數(shù)的實(shí)例詳解

    Python 格式化輸出_String Formatting_控制小數(shù)點(diǎn)位數(shù)的實(shí)例詳解

    在本篇文章里小編給大家整理了關(guān)于Python 格式化輸出_String Formatting_控制小數(shù)點(diǎn)位數(shù)的實(shí)例內(nèi)容,需要的朋友們參考下。
    2020-02-02
  • Pandas分組聚合之groupby()、agg()方法的使用教程

    Pandas分組聚合之groupby()、agg()方法的使用教程

    今天看到pandas的聚合函數(shù)agg,比較陌生,平時(shí)的工作中處理數(shù)據(jù)的時(shí)候使用的也比較少,為了加深印象,總結(jié)一下使用的方法,下面這篇文章主要給大家介紹了關(guān)于Pandas分組聚合之groupby()、agg()方法的使用教程,需要的朋友可以參考下
    2023-01-01
  • python列表切片和嵌套列表取值操作詳解

    python列表切片和嵌套列表取值操作詳解

    今天小編就為大家分享一篇python列表切片和嵌套列表取值操作詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-02-02

最新評(píng)論