一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - python實現地牢迷宮生成的完整步驟

python實現地牢迷宮生成的完整步驟

2022-01-12 00:04揉揉漆 Python

這篇文章主要給大家介紹了關于python實現地牢迷宮生成的相關資料,文中通過示例代碼將實現的過程一步步介紹的非常詳細,對大家學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

基本屬性

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

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

看一下效果

python實現地牢迷宮生成的完整步驟

 

生成墻壁

編寫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

效果

python實現地牢迷宮生成的完整步驟

 

生成門口

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

除此之外,房間連通的思路是:在所有房間列表中隨機抽出兩個房間,將這兩個房間連通,再隨機選一個房間加回原來的房間列表,直至最后列表里只剩下一個房間。那么現在先來生成房門,代碼如下

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

看下效果

python實現地牢迷宮生成的完整步驟

 

生成通道

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

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

效果

python實現地牢迷宮生成的完整步驟

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

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:
                          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):
      #檢測有無覆蓋
      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]] = 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()

可視化一下

python實現地牢迷宮生成的完整步驟

 

總結

到此這篇關于python實現地牢迷宮生成的文章就介紹到這了,更多相關python地牢迷宮生成內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/weixin_44715221/article/details/120458006

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 美女尿口羞羞视频 | 国内精品免费一区二区三区 | 天天色天天综合网 | 欧美透逼视频 | 国产一二在线观看视频网站 | 四虎新网址 | 久久人妻无码毛片A片麻豆 久久热这里只有 精品 | 日韩风月片 | 粉嫩极品国产在线观看免费 | 久久伊人影院 | 欧美破处女视频 | 久久日本片精品AAAAA国产 | 亚洲男人天堂a | 男人天堂亚洲 | 91影视在线看免费观看 | 国产精品第一区揄拍 | 高中生放荡日记高h娜娜 | 美女精品永久福利在线 | 丝袜捆绑调教视频免费区 | 国产爽视频| 午夜精品久久久内射近拍高清 | 99re在线精品视频免费 | 欧美一级激情 | 男同互操 | 天天爱天天做天天爽天天躁 | 欧美乱妇高清无乱码视频在线 | 婷婷久久热99在线精品 | 日本高清在线精品一区二区三区 | 韩国三级大全 | 日本成人免费在线视频 | 毛片a区| 毛片免费网站 | 欧美一级特黄特色大片 | 第一次破女视频国产一级 | 国产麻豆剧果冻传媒观看免费视频 | 亚洲视频在线看 | 拔插拔插成人 | 桃乃木香奈作品在线观看 | 国产99区| 互换身体全集免费观看 | 免费看日本 |