生成迷宫的算法

29 篇文章 3 订阅
13 篇文章 0 订阅

规则

黑色为墙, 白色为路
以左下角为起点, 生成路
路能通过上下左右相邻的格子(斜着不能通过)
路不可环形相接

先上图

10X10的:
在这里插入图片描述

20X20的:
在这里插入图片描述

99X99的:
在这里插入图片描述

讲思路

从起点开始
看其上下左右4个邻居能不能变成路

怎么看?
先看能不能往上走:
首先, 上方得有格子,
且上方不是路,
且上上格子也不是路,
且左上格子也不是路,
且右上格子也不是路,
则, 能往上走


依次看上下左右4个格子能不能走, 能走的加入neighbours
随机从neighbours选一个, 把她变成白色的路
再以她为起点, 再看其上下左右能不能走

依次执行

直到, 上下左右都不能走了, 则, 这个点是死路
从之前的活路中随机选一个点, 作为起点, 走

直到, 所有的路全部为死路

贴代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Grid
{
    public int x;
    public int y;
    private bool isRoad;
    public Transform tra;

    public bool IsRoad
    {
        get
        {
            return isRoad;
        }

        set
        {
            isRoad = value;
            if (isRoad)
            {
                tra.GetComponent<Renderer>().material.color = Color.white;
            }
            else
            {
                tra.GetComponent<Renderer>().material.color = Color.black;
            }
        }
    }

    public Grid(int x, int y, Transform tra)
    {
        this.x = x;
        this.y = y;
        this.tra = tra;
    }

}

public class Mgr : MonoBehaviour
{
    public Transform prefab;
    Dictionary<int, Grid> allGrids = new Dictionary<int, Grid>(); //全部格子
    Dictionary<int, Grid> allRoads = new Dictionary<int, Grid>(); //全部路
    List<int> aliveRoads = new List<int>(); //活路
    const int width = 20;
    const int height = 20;
    int curX = 0;
    int curY = 0;
    void Start()
    {
        Init();
    }

    void Init()
    {
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                Transform tra = Instantiate(prefab);
                Vector3 pos = (new Vector2(x, y) - Vector2.one * width / 2) * 0.2f;
                tra.position = pos;
                Grid grid = new Grid(x, y, tra);
                int key = x * 100 + y;
                allGrids.Add(key, grid);
            }
        }
        Begin();
    }

    void Reset()
    {
        allRoads.Clear();
        aliveRoads.Clear();
        foreach (Grid grid in allGrids.Values)
        {
            grid.IsRoad = false;
        }
    }

    void Begin()
    {
        Reset();
        curX = 0;
        curY = 0;
        AddToRoad(0);
    }

    void AddToRoad(int key)
    {
        Grid grid = allGrids[key];
        grid.IsRoad = true;
        allRoads.Add(key, grid);
        aliveRoads.Add(key);
    }

    bool Next()
    {
        int x = curX;
        int y = curY;
        int curKey = x * 100 + y;
        List<int> neighbours = new List<int>();
        int up = GetUp(x, y);
        int down = GetDown(x, y);
        int left = GetLeft(x, y);
        int right = GetRight(x, y);

        bool upLeft = allRoads.ContainsKey(GetUpLeft(x, y));
        bool upRight = allRoads.ContainsKey(GetUpRight(x, y));
        bool downLeft = allRoads.ContainsKey(GetDownLeft(x, y));
        bool downRight = allRoads.ContainsKey(GetDownRight(x, y));
        bool upUp = allRoads.ContainsKey(GetUpUp(x, y));
        bool downDown = allRoads.ContainsKey(GetDownDown(x, y));
        bool leftLeft = allRoads.ContainsKey(GetLeftLeft(x, y));
        bool RightRight = allRoads.ContainsKey(GetRightRight(x, y));
        if (allGrids.ContainsKey(up) && !allRoads.ContainsKey(up))
        {
            if (!upUp && !upLeft && !upRight)
            {
                neighbours.Add(up);
            }
        }
        if (allGrids.ContainsKey(down) && !allRoads.ContainsKey(down))
        {
            if (!downDown && !downLeft && !downRight)
            {
                neighbours.Add(down);
            }
        }
        if (allGrids.ContainsKey(left) && !allRoads.ContainsKey(left))
        {
            if (!leftLeft && !upLeft && !downLeft)
            {
                neighbours.Add(GetLeft(x, y));
            }
        }
        if (allGrids.ContainsKey(right) && !allRoads.ContainsKey(right))
        {
            if (!RightRight && !upRight && !downRight)
            {
                neighbours.Add(GetRight(x, y));
            }
        }
        if (neighbours.Count != 0)
        {
            int index = Random.Range(0, neighbours.Count);
            int key = neighbours[index];
            curX = key / 100;
            curY = key % 100;
            AddToRoad(key);
            return true;
        }
        else
        {
            int cnt = aliveRoads.Count;
            for (int i = 0; i < cnt; i++)
            {
                if (aliveRoads[i] == curKey)
                {
                    aliveRoads.Remove(curKey);
                    break;
                }
            }
            return false;
        }
    }

    void TryNext()
    {
        if (aliveRoads.Count > 0)
        {
            int index = Random.Range(0, aliveRoads.Count);
            int key = aliveRoads[index];
            curX = key / 100;
            curY = key % 100;
            if (Next())
            {

            }
            else
            {
                TryNext();
            }
        }
        else
        {
            print("满了");

        }
    }

    void NextRoad()
    {
        if (Next())
        {

        }
        else
        {
            TryNext();
        }
    }

    int GetUp(int x, int y)
    {
        return (x * 100 + y + 1);
    }
    int GetUpUp(int x, int y)
    {
        return (x * 100 + y + 2);
    }
    int GetDown(int x, int y)
    {
        return (x * 100 + y - 1);
    }
    int GetDownDown(int x, int y)
    {
        return (x * 100 + y - 2);
    }
    int GetLeft(int x, int y)
    {
        return ((x - 1) * 100 + y);
    }
    int GetLeftLeft(int x, int y)
    {
        return ((x - 2) * 100 + y);
    }
    int GetRight(int x, int y)
    {
        return ((x + 1) * 100 + y);
    }
    int GetRightRight(int x, int y)
    {
        return ((x + 2) * 100 + y);
    }
    int GetUpLeft(int x, int y)
    {
        return ((x - 1) * 100 + y + 1);
    }
    int GetUpRight(int x, int y)
    {
        return ((x + 1) * 100 + y + 1);
    }
    int GetDownLeft(int x, int y)
    {
        return ((x - 1) * 100 + y - 1);
    }
    int GetDownRight(int x, int y)
    {
        return ((x + 1) * 100 + y - 1);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.R))
        {
            Begin();
        }
        else if (Input.GetKeyDown(KeyCode.N))
        {
            NextRoad();
        }
        else if (Input.GetKey(KeyCode.Space))
        {
            // 演示时加速用的
            //for (int i = 0; i < 70; i++)
            {
                NextRoad();
            }
        }
        else if (Input.GetKey(KeyCode.A))
        {
            while (aliveRoads.Count > 0)
            {
                NextRoad();
            }
        }
    }
}

思考

其实是生成了一棵树
可以指定任意位置为起点
也可以指定任意位置为终点
也可以在最后随机加入几个点, 使之形成环路, 但要小心, 这些后加入的点可能是孤立的点, 谁也不相邻

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值