zoukankan      html  css  js  c++  java
  • unity使用深度优先搜索算法自动生成随机迷宫

    unity使用深度优先搜索算法自动生成随机迷宫

    关键词:unity C# 随机生成迷宫 深度优先搜索算法 迷宫算法

    最近有空,研究了一下深度优先搜索算法,并做成一个生成迷宫的例子。

    参考的是:

    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 WorldBehaviour : MonoBehaviour
      7 {
      8     public struct MapPointState
      9     {
     10         public int x;
     11         public int y;
     12 
     13         public bool isVisit;
     14         public int state;
     15 
     16         public List<int> direction;
     17 
     18         public MapPointState(int x, int y, bool isVisit, int state)
     19         {
     20             this.x = x;
     21             this.y = y;
     22             this.isVisit = isVisit;
     23             this.state = state;
     24             direction = new List<int>();
     25         }
     26     }
     27 
     28     public RectTransform mainCanvas;
     29     public Image image;
     30 
     31     public int worldWidth;
     32     public int worldHeight;
     33 
     34     private Image[,] pathImages;
     35 
     36     private MapPointState[,] mapPointStates;
     37 
     38     private Queue<MapPointState> mapQueue;
     39 
     40     private Stack<MapPointState> pathStack;
     41 
     42     private int currentVisits;
     43 
     44     private bool isReadyStop;
     45     private Coroutine coroutine;
     46     // Use this for initialization
     47     void Start()
     48     {
     49         pathImages = new Image[worldHeight, worldWidth];
     50         mapQueue = new Queue<MapPointState>();
     51 
     52         coroutine = StartCoroutine(WaitAndShow());
     53 
     54         CreateAllPath();
     55         InitDepthFirstSearch();
     56         StartDepthFirstSearch();
     57     }
     58     /// <summary>
     59     /// 初始化
     60     /// </summary>
     61     private void InitDepthFirstSearch()
     62     {
     63         mapPointStates = new MapPointState[worldHeight, worldWidth];
     64         pathStack = new Stack<MapPointState>();
     65 
     66         int[] a = { 0, 1, 2, 3 };//0Up 1Down 2Left 3Right
     67 
     68         for (int i = 0; i < worldWidth; i++)
     69         {
     70             for (int j = 0; j < worldHeight; j++)
     71             {
     72                 mapPointStates[i, j] = new MapPointState(i, j, false, 0);
     73                 mapPointStates[i, j].direction.AddRange(a);
     74             }
     75         }
     76     }
     77     /// <summary>
     78     /// 开始
     79     /// </summary>
     80     private void StartDepthFirstSearch()
     81     {
     82         DepthFirstSearch(Random.Range(0, worldHeight), Random.Range(0, worldWidth), -1);
     83 
     84         print(currentVisits);
     85         isReadyStop = true;
     86     }
     87     /// <summary>
     88     /// 搜索
     89     /// </summary>
     90     /// <param name="x">当前所在x</param>
     91     /// <param name="y">当前所在y</param>
     92     /// <param name="direction">来时的方向</param>
     93     private void DepthFirstSearch(int x, int y, int direction)//抽象坐标轴x↑y→
     94     {
     95         //若超过边界
     96         if (x < 0 || x >= worldHeight || y < 0 || y >= worldWidth)
     97         {
     98             if (pathStack.Count > 0)
     99                 DepthFirstSearch(pathStack.Peek().x, pathStack.Peek().y, -1);
    100             return;
    101         }
    102         //若剩余方向为0
    103         if (mapPointStates[x, y].direction.Count == 0)
    104         {
    105             if (pathStack.Contains(mapPointStates[x, y]))
    106             {
    107                 pathStack.Pop();
    108                 mapPointStates[x, y].isVisit = true;
    109                 mapQueue.Enqueue(mapPointStates[x, y]);
    110             }
    111             if (pathStack.Count > 0)
    112                 DepthFirstSearch(pathStack.Peek().x, pathStack.Peek().y, -1);
    113             return;
    114         }
    115         //移除来时方向
    116         if (mapPointStates[x, y].direction.Contains(direction))
    117         {
    118             mapPointStates[x, y].direction.Remove(direction);
    119         }
    120 
    121         currentVisits++;
    122 
    123         //随机下一个方向
    124         int nextDirection = mapPointStates[x, y].direction[Random.Range(0, mapPointStates[x, y].direction.Count)];
    125         mapPointStates[x, y].direction.Remove(nextDirection);
    126 
    127         int newX = -1, newY = -1;
    128 
    129         ProcessNextPosition(x, y, nextDirection, ref newX, ref newY);
    130 
    131         //搜索下一个方向
    132         if (newX != -1 && newY != -1)
    133         {
    134             AddNewPointInMap(x, y);
    135 
    136             switch (nextDirection)
    137             {
    138                 case 0:
    139                     nextDirection = 1;
    140                     break;
    141                 case 1:
    142                     nextDirection = 0;
    143                     break;
    144                 case 2:
    145                     nextDirection = 3;
    146                     break;
    147                 case 3:
    148                     nextDirection = 2;
    149                     break;
    150             }
    151 
    152             DepthFirstSearch(newX, newY, nextDirection);
    153 
    154             return;
    155         }
    156         //回溯
    157         if (mapPointStates[x, y].direction.Count > 0)
    158         {
    159             DepthFirstSearch(x, y, -1);
    160         }
    161         else if (pathStack.Count > 0)
    162         {
    163             DepthFirstSearch(pathStack.Peek().x, pathStack.Peek().y, -1);
    164         }
    165     }
    166     /// <summary>
    167     /// 计算下一个坐标
    168     /// </summary>
    169     /// <param name="x">当前x</param>
    170     /// <param name="y">当前y</param>
    171     /// <param name="nextDirection">下一个方向</param>
    172     /// <param name="newX">新x</param>
    173     /// <param name="newY">新y</param>
    174     private void ProcessNextPosition(int x, int y, int nextDirection, ref int newX, ref int newY)
    175     {
    176         switch (nextDirection)
    177         {
    178             case 0:
    179                 if (x + 1 < worldHeight && mapPointStates[x + 1, y].state != 1)
    180                 {
    181                     if ((y - 1 >= 0 && mapPointStates[x + 1, y - 1].state == 1) || (y + 1 < worldWidth && mapPointStates[x + 1, y + 1].state == 1))
    182                     {
    183                         break;
    184                     }
    185 
    186                     if (x + 2 < worldHeight && mapPointStates[x + 2, y].state == 1)
    187                     {
    188                         AddNewPointInMap(x, y);
    189                         break;
    190                     }
    191 
    192                     newX = x + 1;
    193                     newY = y;
    194                 }
    195                 break;
    196             case 1:
    197                 if (x - 1 >= 0 && mapPointStates[x - 1, y].state != 1)
    198                 {
    199                     if ((y - 1 >= 0 && mapPointStates[x - 1, y - 1].state == 1) || (y + 1 < worldWidth && mapPointStates[x - 1, y + 1].state == 1))
    200                     {
    201                         break;
    202                     }
    203 
    204                     if (x - 2 >= 0 && mapPointStates[x - 2, y].state == 1)
    205                     {
    206                         AddNewPointInMap(x, y);
    207                         break;
    208                     }
    209 
    210                     newX = x - 1;
    211                     newY = y;
    212                 }
    213                 break;
    214             case 2:
    215                 if (y - 1 >= 0 && mapPointStates[x, y - 1].state != 1)
    216                 {
    217                     if ((x + 1 < worldHeight && mapPointStates[x + 1, y - 1].state == 1) || (x - 1 >= 0 && mapPointStates[x - 1, y - 1].state == 1))
    218                     {
    219                         break;
    220                     }
    221 
    222                     if (y - 2 >= 0 && mapPointStates[x, y - 2].state == 1)
    223                     {
    224                         AddNewPointInMap(x, y);
    225                         break;
    226                     }
    227 
    228                     newX = x;
    229                     newY = y - 1;
    230                 }
    231                 break;
    232             case 3:
    233                 if (y + 1 < worldWidth && mapPointStates[x, y + 1].state != 1)
    234                 {
    235                     if ((x + 1 < worldHeight && mapPointStates[x + 1, y + 1].state == 1) || (x - 1 >= 0 && mapPointStates[x - 1, y + 1].state == 1))
    236                     {
    237                         break;
    238                     }
    239 
    240                     if (y + 2 < worldWidth && mapPointStates[x, y + 2].state == 1)
    241                     {
    242                         AddNewPointInMap(x, y);
    243                         break;
    244                     }
    245 
    246                     newX = x;
    247                     newY = y + 1;
    248                 }
    249                 break;
    250         }
    251     }
    252 
    253     /// <summary>
    254     /// 增加新点进地图
    255     /// </summary>
    256     /// <param name="x"></param>
    257     /// <param name="y"></param>
    258     private void AddNewPointInMap(int x, int y)
    259     {
    260         mapPointStates[x, y].state = 1;
    261 
    262         if (!mapQueue.Contains(mapPointStates[x, y]))
    263         {
    264             mapQueue.Enqueue(mapPointStates[x, y]);
    265         }
    266 
    267         if (!pathStack.Contains(mapPointStates[x, y]))
    268         {
    269             pathStack.Push(mapPointStates[x, y]);
    270         }
    271     }
    272     /// <summary>
    273     /// 创建所有路径
    274     /// </summary>
    275     private void CreateAllPath()
    276     {
    277         for (int i = 0; i < worldHeight; i++)
    278         {
    279             for (int j = 0; j < worldWidth; j++)
    280             {
    281                 pathImages[i, j] = Instantiate(image, new Vector3(i * 32, j * 32, 0), Quaternion.identity, mainCanvas);
    282             }
    283         }
    284     }
    285     /// <summary>
    286     /// 设置路径颜色
    287     /// </summary>
    288     /// <param name="mapPointState"></param>
    289     private void SetPathColor(MapPointState mapPointState)
    290     {
    291         if (mapPointState.isVisit)
    292             pathImages[mapPointState.x, mapPointState.y].color = new Color(0, 1, 0, 1);
    293         else
    294             pathImages[mapPointState.x, mapPointState.y].color = new Color(1, 1, 1, 1);
    295     }
    296     /// <summary>
    297     /// 等待显示
    298     /// </summary>
    299     /// <returns></returns>
    300     private IEnumerator WaitAndShow()
    301     {
    302         while (true)
    303         {
    304             yield return new WaitForSeconds(0.1f);
    305 
    306             if (mapQueue.Count > 0)
    307             {
    308                 SetPathColor(mapQueue.Peek());
    309                 mapQueue.Dequeue();
    310             }
    311 
    312             if (isReadyStop && mapQueue.Count == 0)
    313             {
    314                 print("End");
    315                 StopCoroutine(coroutine);
    316             }
    317         }
    318     }
    319 }

    另附上工程文件:

    https://files.cnblogs.com/files/JinT-Hwang/NewUnityProject1.7z

    欢迎交流指教:)

  • 相关阅读:
    6、UITableView表的分割线左对齐
    5、清理mac缓存和关闭后台运行程序
    1、iOS9 HTTP 不能正常使用的解决办法
    在ios下提示“@synthesize of ‘weak’ property is only allowed in ARC or GC mode”
    java中的String类
    java思考题
    java思考
    java动手动脑思考
    大道至简第二章读后感
    JAVA训练参数求和
  • 原文地址:https://www.cnblogs.com/JinT-Hwang/p/9599913.html
Copyright © 2011-2022 走看看