日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python实现地牢迷宫生成

發布時間:2024/7/23 python 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python实现地牢迷宫生成 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

python實現地牢迷宮生成

  • 基本屬性
  • 生成房間
  • 生成墻壁
  • 生成門口
  • 生成通道

基本屬性

定義當前地牢的等級,地圖長寬,房間數量,房間的最小最大長度,如下

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

生成房間

編寫initRoom()隨機生成房間,限制最多循環次數,為了簡單起見,先做一個不會重疊的房間。基本思路是:隨機房間的中心點,隨機房間的長寬,再進行判斷房間有無重疊(在后續會生成通道,簡單起見在這里也保證房間不會緊貼),若無重疊,房間有效,房間數加1。貼代碼

def initRoom(self):count = 0roomCount = 1while True:count += 1if count > 300:breakif roomCount > self.roomNum:breakx = 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 = 1if r2 >= self.heigh - 1:r2 = self.heigh - 2if c1 < 1:c1 = 1if c2 >= self.width - 1:c2 = self.width - 2w = c2 - c1 + 1h = r2 - r1 + 1if h / w >= 3 or w / h >= 3: #保證房間不是細長的continuejudge = self.isValidRoom(r1,r2,c1,c2)if judge == 0:roomCount += 1self.room.append(Room(r1,r2,c1,c2))for i in range(r1,r2):for j in range(c1,c2):self.map[i,j] = 1def 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 2for i in range(c1,c2):if self.map[r1-1,i] == 1 or self.map[r2+1,i] == 1:return 2return 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 = 0for 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:continueif 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 - c1h = r2 - r1self.width = wself.height = hself.cx = c1 + ceil(w/2)self.cy = r1 + ceil(h/2)self.xStart = c1self.xEnd = c2 - 1self.yStart = r1self.yEnd = r2 - 1def 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]] = 2self.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]] = 2self.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]] = 2elif self.map[p[0], p[1] - 1] == 1 and self.map[p[0], p[1] + 1] == 3:self.map[p[0], p[1] + 1] = 2elif self.map[p[0] + 1, p[1]] == 1 and self.map[p[0] - 1, p[1]] == 3:self.map[p[0] - 1, p[1]] = 2elif 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]) * 10g = 0def isInClose(p):for it in close_list:if it.value[3] == p:return Truereturn Falsedef isInOpen(p):for it in open_list:if it.value[3] == p:return Truereturn Falsedef 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 itreturn Noneopen_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]] = 2p_father = findFather(p_father)if p_father[0] == -1:breakself.map[p0[0], p0[1]] = 4returnif p2[0] < 0 or p2[0] >= self.heigh or p2[1] < 0 or p2[1] >= self.width:continueif (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):continueh = abs(p2[0] - p1[0]) * 10 + abs(p2[1] - p1[1]) * 10g = f_min.value[1] + 10f = h + gif 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]]))

效果

這樣,一個隨機房間的地牢就已經生成,貼上完整代碼

import random import numpy as np from math import ceilclass Node():def __init__(self, val=None):if val is None:val = [0, 0, 0, [-1, -1], [-1, -1]]self.value = valclass Room():def __init__(self,r1,r2,c1,c2):w = c2 - c1h = r2 - r1self.width = wself.height = hself.cx = c1 + ceil(w/2)self.cy = r1 + ceil(h/2)self.xStart = c1self.xEnd = c2 - 1self.yStart = r1self.yEnd = r2 - 1def 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 = 30self.heigh = 30self.level = 1self.roomNum = 5#0 is null, 1 is room, 2 is path, 3 is wall, 4 is door, 5 is up stair, 6 is downstairself.map = np.zeros((self.width,self.heigh))self.roomMin = 3self.roomMax = 11self.room = []self.door = []self.initRoom()self.initTile()self.initPath()#self.initTile()#self.initDoor()def initRoom(self):count = 0roomCount = 1while True:count += 1if count > 300:breakif roomCount > self.roomNum:breakx = 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 += 1ht = random.randint(self.roomMin, self.roomMax)if ht % 2 == 0:ht += 1r1 = ceil(y - ht/2)r2 = ceil(y + ht/2)c1 = ceil(x - wd/2)c2 = ceil(x + wd/2)if r1 < 1:r1 = 1if r2 >= self.heigh - 1:r2 = self.heigh - 2if c1 < 1:c1 = 1if c2 >= self.width - 1:c2 = self.width - 2w = c2 - c1 + 1h = r2 - r1 + 1if w == 0:continueif h == 0:continueif h / w >= 3 or w / h >= 3:continuejudge = self.isValidRoom(r1,r2,c1,c2)if judge == 0:roomCount += 1self.room.append(Room(r1,r2,c1,c2))for i in range(r1,r2):for j in range(c1,c2):self.map[i,j] = 1def 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]] = 2self.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]] = 2self.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]] = 4def 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]] = 2elif self.map[p[0], p[1] - 1] == 1 and self.map[p[0], p[1] + 1] == 3:self.map[p[0], p[1] + 1] = 2elif self.map[p[0] + 1, p[1]] == 1 and self.map[p[0] - 1, p[1]] == 3:self.map[p[0] - 1, p[1]] = 2elif self.map[p[0], p[1] + 1] == 1 and self.map[p[0], p[1] - 1] == 3:self.map[p[0], p[1] - 1] = 2def 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 = 0for 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:continueif 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] = 3def 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 2for i in range(c1,c2):if self.map[r1-1,i] == 1 or self.map[r2+1,i] == 1:return 2return 0def 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]) * 10g = 0def isInClose(p):for it in close_list:if it.value[3] == p:return Truereturn Falsedef isInOpen(p):for it in open_list:if it.value[3] == p:return Truereturn Falsedef 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 itreturn Noneopen_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]] = 2p_father = findFather(p_father)if p_father[0] == -1:breakself.map[p0[0], p0[1]] = 4returnif p2[0] < 0 or p2[0] >= self.heigh or p2[1] < 0 or p2[1] >= self.width:continueif (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):continueh = abs(p2[0] - p1[0]) * 10 + abs(p2[1] - p1[1]) * 10g = f_min.value[1] + 10f = h + gif 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()

可視化一下

總結

以上是生活随笔為你收集整理的python实现地牢迷宫生成的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。