せっかく経路探索して敵を追いかけるアルゴリズムを書くなら迷路がほしいなと思ったので。
穴掘り法を複数回ループして、分岐を無理やり増やしてるけど袋小路はうまれる。
仕方ないね。
穴掘り法とは
実装
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
public class MakeDungeon : MonoBehaviour
{
public int max = 5;
public GameObject wall;
public GameObject floor;
public GameObject start;
public GameObject goal;
private int[,] walls;
private int[] startPos;
private int[] goalPos;
void Start()
{
walls = new int[max, max];
startPos = GetStartPosition();
goalPos = MakeDungeonMap(startPos);
int[] tmpStart = goalPos;
for (int i = 0; i < max * 5; i++)
{
MakeDungeonMap(tmpStart);
tmpStart = GetStartPosition();
}
BuildDungeon();
GameObject startObj = Instantiate(start, new Vector3(startPos[0], 1, startPos[1]), Quaternion.identity) as GameObject;
GameObject goalObj = Instantiate(goal, new Vector3(goalPos[0], 1, goalPos[1]), Quaternion.identity) as GameObject;
startObj.transform.parent = transform;
goalObj.transform.parent = transform;
}
int[] GetStartPosition()
{
int randx = Random.Range(0, max);
int randy = Random.Range(0, max);
while (randx % 2 != 0 || randy % 2 != 0)
{
randx = Mathf.RoundToInt(Random.Range(0, max));
randy = Mathf.RoundToInt(Random.Range(0, max));
}
return new int[] { randx, randy };
}
int[] MakeDungeonMap(int[] _startPos)
{
int[] tmpStartPos = new int[2];
_startPos.CopyTo(tmpStartPos, 0);
Dictionary<int, int[]> movePos = GetPosition(tmpStartPos);
while (movePos != null)
{
int[] tmpPos = movePos[Random.Range(0, movePos.Count)];
walls[tmpPos[0], tmpPos[1]] = 1;
int xPos = tmpPos[0] + (tmpStartPos[0] - tmpPos[0]) / 2;
int yPos = tmpPos[1] + (tmpStartPos[1] - tmpPos[1]) / 2;
walls[xPos, yPos] = 1;
tmpStartPos = tmpPos;
movePos = GetPosition(tmpStartPos);
}
return tmpStartPos;
}
Dictionary<int, int[]> GetPosition(int[] _startPos)
{
int x = _startPos[0];
int y = _startPos[1];
List<int[]> position = new List<int[]> {
new int[] {x, y + 2},
new int[] {x, y - 2},
new int[] {x + 2, y},
new int[] {x - 2, y}
};
Dictionary<int, int[]> positions = position.Where(p => !isOutOfRange(p[0], p[1]) && walls[p[0], p[1]] == 0)
.Select((p, i) => new { p, i })
.ToDictionary(p => p.i, p => p.p);
return positions.Count() != 0 ? positions : null;
}
bool isOutOfRange(int x, int y)
{
return (x < 0 || y < 0 || x >= max || y >= max);
}
void BuildDungeon()
{
for (int i = -1; i <= max; i++)
{
for (int j = -1; j <= max; j++)
{
if (isOutOfRange(i, j)
|| walls[i, j] == 0)
{
GameObject wallObj = Instantiate(wall, new Vector3(i, 0, j), Quaternion.identity) as GameObject;
wallObj.transform.parent = transform;
}
GameObject floorObj = Instantiate(floor, new Vector3(i, -1, j), Quaternion.identity) as GameObject;
floorObj.transform.parent = transform;
}
}
}
}