title: MazeGeneration
tags: default
date: 2019-09-11 10:13:31
迷宫生成
N*N的网格,按照预设的路线,生成仅有此唯一解的迷宫。迷宫可上下左右四个方向移动,每个网格都有颜色,必须按照红-黄-蓝-绿(颜色种类可预设)的顺序走。
网格节点
-
节点的颜色(Type)
-
节点的行列名字(Name), "Mesh_2_1"第2行第1列节点
-
是否被访问过(IsVisited)
-
父节点(MeshNode)
class MeshNode { public int Type { get; set; } public string Name { get; set; } public MeshNode PreNode { get; set; } public bool IsVisited { get; set; } public MeshNode(int type, string name) { Type = type; Name = name; PreNode = null; IsVisited = false; } }
算法实现
-
构建一个N*N的迷宫,随机生成每个网格的Type.
-
修改在预设路径上网格节点的Type.
-
从预设路径的开始节点进行深度优先搜索.
1.判断是否到终点,是则跳出
2.对此节点获取临近节点,筛选临近节点中可以走的节点,没有可以走的就跳出
3.通过筛选的节点,IsVisited设置为true, preNode设置为步骤2的节点,然后进行dfs,跳出dfs后IsVisited设置为false
-
每次搜索到终点时,终点与起点是一条单向链表。将此路径保存起来.
-
所有的路径收集完成后,是一个网格节点的集合。筛选出不在预设路径中的点.
-
修改每个节点的Type.
-
重复进行搜索所有的路径。如果只有一条路径,则跳出。如果还有则继续修改节点Type,重复搜索.
完整代码
using System;
using System.Collections.Generic;
using System.Linq;
class MeshNode
{
public int Type { get; set; }
public string Name { get; set; }
public MeshNode PreNode { get; set; }
public bool IsVisited { get; set; }
public MeshNode(int type, string name)
{
Type = type;
Name = name;
PreNode = null;
IsVisited = false;
}
}
class MazeTools
{
public int MazeSize { get; set; }
public int TypesCount { get; set; }
public List<MeshNode> MazeNodes = new List<MeshNode>();
public MeshNode startMeshNode { get; set; }
public MeshNode endMeshNode { get; set; }
public List<string> AllRouters = new List<string>();
public void initMeshData()
{
var size = MazeSize;
var typesCount = TypesCount;
Random random = new Random();
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
var node = new MeshNode(random.Next(typesCount), "mesh_" + i + "_" + j);
MazeNodes.Add(node);
}
}
modifyPresetMesh();
}
public List<MeshNode> getPresetMeshNodes()
{
string[] array = { "mesh_1_0", "mesh_1_1", "mesh_1_2", "mesh_1_3", "mesh_1_4", "mesh_2_4", "mesh_3_4", "mesh_3_3", "mesh_3_2", "mesh_3_1"};
List<MeshNode> nodes = new List<MeshNode>();
for (int i = 0; i < array.Count(); i++){
nodes.Add(new MeshNode( i%TypesCount,array[i]));
}
return nodes;
}
public void modifyPresetMesh()
{
var mazeNodes = MazeNodes;
var presetMeshNode = getPresetMeshNodes();
foreach (var node in presetMeshNode)
{
var mazeNode = mazeNodes.Find(delegate (MeshNode meshnode)
{
return node.Name == meshnode.Name;
});
if (mazeNode != null)
{
mazeNode.Type = node.Type;
}
}
Console.WriteLine("modifyPresetMesh ok!");
startMeshNode = presetMeshNode.First();
endMeshNode = presetMeshNode.Last();
}
public MeshNode getMeshNodeByName(string name)
{
return MazeNodes.Find(delegate (MeshNode meshnode)
{
return meshnode.Name == name;
});
}
public List<MeshNode> getNeighbors(MeshNode node)
{
var name = node.Name;
var arr = name.Split('_');
int row = int.Parse(arr[1]);
int col = int.Parse(arr[2]);
var leftNode = getMeshNodeByName("mesh_" + row + '_' + (col - 1));
var rightNode = getMeshNodeByName("mesh_" + row + '_' + (col + 1));
var upNode = getMeshNodeByName("mesh_" + (row - 1) + '_' + col);
var downNode = getMeshNodeByName("mesh_" + (row + 1) + '_' + col);
var nodes = new List<MeshNode>();
nodes.Add(leftNode);
nodes.Add(rightNode);
nodes.Add(upNode);
nodes.Add(downNode);
nodes = nodes.Where(n => n != null).ToList();
return nodes;
}
public void getAllRoutes()
{
var node = startMeshNode;
node.IsVisited = true;
dfs(node);
node.IsVisited = false;
if (AllRouters.Count != 1)
{
Console.WriteLine("存在{0}条路径可以到达终点,正在尝试修正!", AllRouters.Count);
reviseRoutes();
resetData();
getAllRoutes();
}
else
{
Console.WriteLine("done!");
}
}
public void resetData()
{
MazeNodes.ForEach(node =>
{
node.IsVisited = false;
});
AllRouters.Clear();
}
public void reviseRoutes()
{
var routes = AllRouters;
var presetMeshnodes = getPresetMeshNodes();
var array = new List<string>();
routes.ForEach(route =>
{
var arr = route.Split('+');
var list =
arr
.Where(name =>
{
return null == presetMeshnodes.Find(delegate (MeshNode n)
{
return n.Name == name;
});
})
.ToList();
array.AddRange(list);
});
array
.Distinct()
.ToList()
.ForEach(name =>
{
var node = getMeshNodeByName(name);
Random random = new Random();
var newType = random.Next(TypesCount);
var oldType = node.Type;
newType = newType != oldType ? newType : getNextType(node);
node.Type = newType;
Console.WriteLine("修正节点{0}Type: from {1} to {2}", node.Name, oldType, newType);
});
Console.WriteLine("修正节点完成,准备进行测试...");
}
public int getNextType(MeshNode node)
{
var type = node.Type;
return (type + 1) % TypesCount;
}
public void addPath(MeshNode node)
{
string route = node.Name;
while (node.PreNode != null)
{
route = route + '+' + node.PreNode.Name;
node = node.PreNode;
}
AllRouters.Add(route);
}
public void dfs(MeshNode node)
{
if (node.Name == endMeshNode.Name)
{
addPath(node);
return;
}
var nextType = getNextType(node);
var neighbors = getNeighbors(node);
neighbors
.Where(neigh => !neigh.IsVisited)
.Where(neigh => neigh.Type == nextType)
.ToList()
.ForEach(neigh =>
{
neigh.IsVisited = true;
neigh.PreNode = node;
dfs(neigh);
neigh.IsVisited = false;
});
}
}