人妖在线一区,国产日韩欧美一区二区综合在线,国产啪精品视频网站免费,欧美内射深插日本少妇

新聞動態(tài)

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

發(fā)布日期:2021-12-31 16:44 | 文章來源:源碼之家

基本屬性

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

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()隨機生成房間,限制最多循環(huán)次數(shù),為了簡單起見,先做一個不會重疊的房間。基本思路是:隨機房間的中心點,隨機房間的長寬,再進行判斷房間有無重疊(在后續(xù)會生成通道,簡單起見在這里也保證房間不會緊貼),若無重疊,房間有效,房間數(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: #保證房間不是細長的
 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:
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

效果

生成門口

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

除此之外,房間連通的思路是:在所有房間列表中隨機抽出兩個房間,將這兩個房間連通,再隨機選一個房間加回原來的房間列表,直至最后列表里只剩下一個房間。那么現(xià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):
  #初始化門
  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

看下效果

生成通道

接著完善上述函數(shù),在隨機選取房門后,連接兩個房門。

在這我選擇的是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]] = 2p_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]]))

效果

這樣,一個隨機房間的地牢就已經(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):
  #初始化門
  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:
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
 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
 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]] = 2p_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實現(xiàn)地牢迷宮生成的文章就介紹到這了,更多相關(guān)python地牢迷宮生成內(nèi)容請搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!

版權(quán)聲明:本站文章來源標注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。

相關(guān)文章

實時開通

自選配置、實時開通

免備案

全球線路精選!

全天候客戶服務(wù)

7x24全年不間斷在線

專屬顧問服務(wù)

1對1客戶咨詢顧問

在線
客服

在線客服:7*24小時在線

客服
熱線

400-630-3752
7*24小時客服服務(wù)熱線

關(guān)注
微信

關(guān)注官方微信
頂部