unity 使用 随机普里姆算法 随机生成迷宫
下午闲着没事,继续上次的迷宫算法,鼓捣了一下Randomized Prim
效果图如下
参考如下文献:
https://en.wikipedia.org/wiki/Maze_generation_algorithm
话不多说,直接贴代码。
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 using UnityEngine.UI; 5 6 public class RandomizedPrimBehaviour : MonoBehaviour 7 { 8 public struct Cell 9 { 10 public int x; 11 public int y; 12 public int direction; 13 14 public bool isVisited; 15 } 16 17 public int mapWidth; 18 public int mapHeight; 19 public Image imagePrefab; 20 public Color bodyColor; 21 public Color headColor; 22 23 private Cell[,] cells; 24 private Image[,] images; 25 26 private List<Cell> cellList; 27 private Queue<Cell> cellQueue; 28 29 private Coroutine coroutine; 30 // Use this for initialization 31 void Start() 32 { 33 cellList = new List<Cell>(); 34 cellQueue = new Queue<Cell>(); 35 36 CreateAndInit(); 37 DoRandomizedPrim(); 38 } 39 /// <summary> 40 /// 创建和初始化 41 /// </summary> 42 private void CreateAndInit() 43 { 44 images = new Image[mapWidth, mapHeight]; 45 cells = new Cell[mapWidth, mapHeight]; 46 47 for (int i = 0; i < mapWidth; i++) 48 { 49 for (int j = 0; j < mapHeight; j++) 50 { 51 images[i, j] = Instantiate(imagePrefab, transform); 52 images[i, j].rectTransform.anchoredPosition = new Vector2(i * imagePrefab.rectTransform.sizeDelta.x, j * imagePrefab.rectTransform.sizeDelta.y); 53 54 cells[i, j].x = i; 55 cells[i, j].y = j; 56 cells[i, j].direction = -1; 57 cells[i, j].isVisited = false; 58 } 59 } 60 } 61 /// <summary> 62 /// Randomized Prim 63 /// </summary> 64 private void DoRandomizedPrim() 65 { 66 int times = 0; 67 68 int x = Random.Range(0, mapWidth); 69 int y = Random.Range(0, mapHeight); 70 71 cells[x, y].isVisited = true; 72 73 AddNewCellsToList(x, y); 74 75 cellQueue.Enqueue(cells[x, y]); 76 77 while (cellList.Count > 0) 78 { 79 int listIndex = Random.Range(0, cellList.Count); 80 81 int newX = -1, newY = -1; 82 switch (cellList[listIndex].direction) 83 { 84 case 0: 85 if (cellList[listIndex].y + 1 < mapHeight && !cells[cellList[listIndex].x, cellList[listIndex].y + 1].isVisited) 86 { 87 newX = cellList[listIndex].x; 88 newY = cellList[listIndex].y + 1; 89 } 90 break; 91 case 1: 92 if (cellList[listIndex].y - 1 >= 0 && !cells[cellList[listIndex].x, cellList[listIndex].y - 1].isVisited) 93 { 94 newX = cellList[listIndex].x; 95 newY = cellList[listIndex].y - 1; 96 } 97 break; 98 case 2: 99 if (cellList[listIndex].x - 1 >= 0 && !cells[cellList[listIndex].x - 1, cellList[listIndex].y].isVisited) 100 { 101 newX = cellList[listIndex].x - 1; 102 newY = cellList[listIndex].y; 103 } 104 break; 105 case 3: 106 if (cellList[listIndex].x + 1 < mapWidth && !cells[cellList[listIndex].x + 1, cellList[listIndex].y].isVisited) 107 { 108 newX = cellList[listIndex].x + 1; 109 newY = cellList[listIndex].y; 110 } 111 break; 112 default: 113 print(cellList[listIndex].x + "_" + cellList[listIndex].y + " Fail"); 114 break; 115 } 116 117 if (newX != -1 && newY != -1) 118 { 119 times++; 120 121 AddNewCellsToList(newX, newY); 122 123 cellQueue.Enqueue(cells[cellList[listIndex].x, cellList[listIndex].y]); 124 cellQueue.Enqueue(cells[newX, newY]); 125 126 cells[cellList[listIndex].x, cellList[listIndex].y].isVisited = true; 127 cells[newX, newY].isVisited = true; 128 } 129 130 cellList.RemoveAt(listIndex); 131 } 132 print("times:" + times); 133 coroutine = StartCoroutine(SlowShow()); 134 } 135 /// <summary> 136 /// 增加新cell进列表 137 /// </summary> 138 /// <param name="x"></param> 139 /// <param name="y"></param> 140 private void AddNewCellsToList(int x, int y) 141 { 142 if (y + 1 < mapHeight && !cells[x, y + 1].isVisited) 143 { 144 cells[x, y + 1].direction = 0; 145 cellList.Add(cells[x, y + 1]); 146 } 147 148 if (y - 1 >= 0 && !cells[x, y - 1].isVisited) 149 { 150 cells[x, y - 1].direction = 1; 151 cellList.Add(cells[x, y - 1]); 152 } 153 154 if (x - 1 >= 0 && !cells[x - 1, y].isVisited) 155 { 156 cells[x - 1, y].direction = 2; 157 cellList.Add(cells[x - 1, y]); 158 } 159 160 if (x + 1 < mapWidth && !cells[x + 1, y].isVisited) 161 { 162 cells[x + 1, y].direction = 3; 163 cellList.Add(cells[x + 1, y]); 164 } 165 } 166 /// <summary> 167 /// 延时显示 168 /// </summary> 169 /// <returns></returns> 170 private IEnumerator SlowShow() 171 { 172 print("cellQueue.Count:" + cellQueue.Count); 173 174 int lastX = -1, lastY = -1; 175 176 while (cellQueue.Count > 0) 177 { 178 yield return new WaitForSecondsRealtime(0.1f); 179 180 if (lastX != -1 && lastY != -1) 181 { 182 images[lastX, lastY].color = bodyColor; 183 } 184 185 Cell cell = cellQueue.Dequeue(); 186 images[cell.x, cell.y].color = headColor; 187 188 lastX = cell.x; 189 lastY = cell.y; 190 } 191 192 images[lastX, lastY].color = bodyColor; 193 194 print("End"); 195 StopCoroutine(coroutine); 196 } 197 }
工程文件如下:
https://files.cnblogs.com/files/JinT-Hwang/RandomizedPrim.7z
欢迎交流指教。