规则
黑色为墙, 白色为路
以左下角为起点, 生成路
路能通过上下左右相邻的格子(斜着不能通过)
路不可环形相接
先上图
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();
}
}
}
}
思考
其实是生成了一棵树
可以指定任意位置为起点
也可以指定任意位置为终点
也可以在最后随机加入几个点, 使之形成环路, 但要小心, 这些后加入的点可能是孤立的点, 谁也不相邻