protected override IEnumerator Generate() { links = linkGenerator.Generate(grid.rows, grid.cols); pick = new List <MazeLink>(grid.cellCount); MazeCell current = RandomCell(); AddLinks(current); SetFocus(current); yield return(OnYield(2)); while (pick.Count > 0) { MazeLink link = PickLink(); MazeCell from = grid[link.row + 1, link.col + 1]; MazeCell to = from.next[link.dir]; if (from.isLocked || to.isLocked) { current = (from.isLocked) ? from : to; from[link.dir] = true; AddLinks(current); SetFocus(current); yield return(OnYield()); } } SetComplete(); }
/* Construa uma SPANNING TREE com o nó raiz indicado KRUSKAL ALGORIGHT/* * O algoritmo de Kruskal é um algoritmo de amplitude mínima que encontra uma borda com o menor peso possível que conecta quaisquer duas árvores na floresta. * É um algoritmo guloso na teoria dos grafos , pois encontra uma árvore geradora mínima para um grafo ponderado conectado, adicionando arcos de custo crescente em cada etapa. * Isso significa que ele encontra um subconjunto das arestas que formam uma árvore que inclui todos os vértices , onde o peso total de todas as arestas da árvore é minimizado. * Se o gráfico não estiver conectado, ele encontrará uma floresta de extensão mínima(uma árvore de abrangência mínima para cada componente conectado. * Esse algoritmo apareceu pela primeira vez em Proceedings ofthe American Mathematical Society, pp. 48-50 em 1956, e foi escrito por Joseph Kruskal.*/ public static void FindSpanningTree(ref MazeNode root) { Random rand = new Random(); // Defina o predecessor do nó raiz para que saibamos que ele está na árvore. root.Predecessor = root; List <MazeLink> links = new List <MazeLink>(); foreach (MazeNode neighbor in root.Neighbors) { if (neighbor != null) { links.Add(new MazeLink(root, neighbor)); } } // Adiciona os outros nós à árvore. while (links.Count > 0) { // Escolha um link aleatório. int link_num = rand.Next(0, links.Count); MazeLink link = links[link_num]; links.RemoveAt(link_num); // Adicione este link à árvore. MazeNode to_node = link.ToNode; link.ToNode.Predecessor = link.FromNode; // Remove quaisquer links da lista desse ponto for (int i = links.Count - 1; i >= 0; i--) { if (links[i].ToNode.Predecessor != null) { links.RemoveAt(i); } } // Adiciona os links do to_node à lista foreach (MazeNode neighbor in to_node.Neighbors) { if ((neighbor != null) && (neighbor.Predecessor == null)) { links.Add(new MazeLink(to_node, neighbor)); } } } }
protected MazeLink PickLink() { foreach (MazeLink link in pick) { link.weight += decay; } pick.Sort((a, b) => (a.weight.CompareTo(b.weight))); MazeLink result = pick[0]; pick.RemoveAt(0); return(result); }
private void Visit(MazeCell cell, bool[,] visited) { visited[cell.X, cell.Y] = true; while (true) { List <MazeLink> potentials = new List <MazeLink>( from dir in Direction.Values where cell[dir].OtherSide != null && !visited[cell[dir].OtherSide.X, cell[dir].OtherSide.Y] orderby Guid.NewGuid() select cell[dir] ); if (potentials.Count == 0) { return; } MazeLink link = potentials[0]; link.Wall = false; Visit(link.OtherSide, visited); } }
void SetExit() { int x; int z; MazeNode.Direction d; if (Random.value >= .5f) { //Use Z Axis z = Random.Range(0, nodeHeight - 1); if (Random.value >= .5f) { //Left x = 0; d = MazeNode.Direction.left; } else { //Right x = nodeWidth - 1; d = MazeNode.Direction.right; } } else { //Use X Axis x = Random.Range(0, nodeWidth - 1); if (Random.value >= .5f) { //Top z = 0; d = MazeNode.Direction.up; } else { //Bottom z = nodeHeight - 1; d = MazeNode.Direction.down; } } exitNode = mazeNodes[x][z]; exit = exitNode.links[MazeNode.DirectionToIndex(d)]; startNode = mazeNodes[nodeWidth - 1 - x][nodeHeight - 1 - z]; playerNode = startNode; if (debugColors) { exitNode.floorRenderer.material = debugGreen; exit.cubeRenderer.material = debugBlack; startNode.floorRenderer.material = debugWhite; } }
public void AddLink(Direction direction, MazeLink link) { links[DirectionToIndex(direction)] = link; }