unity 使用 随机普里姆算法(Randomized Prim) 生成迷宫

 unity 使用 随机普里姆算法 随机生成迷宫

下午闲着没事,继续上次的迷宫算法,鼓捣了一下Randomized Prim

效果图如下

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

欢迎交流指教。

posted @ 2018-09-10 17:59  黄进钿  阅读(1391)  评论(0编辑  收藏  举报