Queue <CellCoord> MakeShortestPath(CellCoord start, CellCoord end) { // breadth first search Queue <CellCoord> open_q = new Queue <CellCoord>(); // node 2 distanceandparentmap cell coord and how I got there Dictionary <CellCoord, DistanceAndParent> visited = new Dictionary <CellCoord, DistanceAndParent>(); open_q.Enqueue(start); visited[start] = new DistanceAndParent(0, start); CellCoord current = new CellCoord(); while (open_q.Count > 0) { current = open_q.Dequeue(); if (current == end) { break; } // otherwise walk each neighbor and add any accessible ones int current_distance = visited[current].distance; List <CellCoord> connected = GetConnectedList(current); foreach (CellCoord tentative in connected) { if (!visited.ContainsKey(tentative) && AreConnected(current, tentative)) { visited[tentative] = new DistanceAndParent(current_distance + 1, current); open_q.Enqueue(tentative); } } } if (current == end) { // todo: make path Stack <CellCoord> backwards_path = new Stack <CellCoord>(); backwards_path.Push(end); DistanceAndParent cur = visited[end]; while (cur.distance > 1) { backwards_path.Push(cur.parent); cur = visited[cur.parent]; } return(new Queue <CellCoord>(backwards_path.ToArray())); } else { return(null); } }
public DistanceAndParent(int distance, DistanceAndParent parent) { this.distance = distance; this.parent = parent; }
public void SetParent(DistanceAndParent parent) { this.parent = parent; }
/// <summary> /// Fonction permettant de trouver et afficher un chemin d'un point A à un point B /// Seuls les cases sur lesquelles on est sûrs de pouvoir aller sont ajoutées /// <param name="deplacement">Valeur de déplacement d'un personnage</param> /// <param name="saut">Valeur de saut d'un personnage</param> /// <param name="positionBloc">Position du bloc de départ, c'est à dire celui SOUS le personnage</param> /// <returns>Retourne une grille qui permet d'avoir les positions de chacun des blocs du chemin, c'est à dire les blocs appartenant au SOL. Le personnage se déplacera une case au dessus</returns> /// </summary> public DistanceAndParent[,,] CanGo(LivingPlaceable livingPlaceable, int saut, Vector3Int positionBloc) { int deplacement = livingPlaceable.PmActuels; for (int x = 0; x < sizeX; x++) { for (int y = 0; y < sizeY; y++) { for (int z = 0; z < sizeZ; z++) { gridBool[x, y, z] = new DistanceAndParent(x, y, z); } } } Queue <Vector3Int> queue = new Queue <Vector3Int>(); queue.Enqueue(positionBloc); DistanceAndParent parent = null; gridBool[positionBloc.x, positionBloc.y, positionBloc.z].SetDistance(0); while (parent == null || ((parent.GetDistance() <= deplacement) && queue.Count != 0)) { //On mets ceux à coté, ceux au dessus accessibles ou ceux en dessous accessibles //coté Vector3Int posBlocActuel = queue.Dequeue(); parent = gridBool[posBlocActuel.x, posBlocActuel.y, posBlocActuel.z]; if (parent.GetDistance() <= deplacement) { Placeable testa = Grid[posBlocActuel.x, posBlocActuel.y, posBlocActuel.z]; if (testa.gameObject.GetComponent <Renderer>() != null) { //On envoie plutot l'id parce que rien n'assure que les blocs soient a la bonne position coté client gameManager.PlayingPlaceable.Joueur.RpcMakeCubeBlue(testa.netId); } //là mettre l'affichage du bloc en bleu for (int yactuel = -saut + 1; yactuel < saut; yactuel++) { if (posBlocActuel.y + yactuel >= 0 && posBlocActuel.y + yactuel < sizeY && posBlocActuel.x < sizeX - 1 && //au dessus de 0, en dessous du max, dans le terrain en x gridBool[posBlocActuel.x + 1, posBlocActuel.y + yactuel, posBlocActuel.z].GetDistance() == -1 && //si on l'a pas dejà vu Grid[posBlocActuel.x + 1, posBlocActuel.y + yactuel, posBlocActuel.z] != null && // et si le bloc existe (Grid[posBlocActuel.x + 1, posBlocActuel.y + yactuel + 1, posBlocActuel.z] == null || //si le bloc au dessus est vide Grid[posBlocActuel.x + 1, posBlocActuel.y + yactuel + 1, posBlocActuel.z].TraversableChar == TraversableType.ALLTHROUGH || //ou traversable en général Grid[posBlocActuel.x + 1, posBlocActuel.y + yactuel + 1, posBlocActuel.z].TraversableChar == TraversableType.ALLIESTHROUGH && //ou seulement par un allié Grid[posBlocActuel.x + 1, posBlocActuel.y + yactuel + 1, posBlocActuel.z].Joueur == livingPlaceable.Joueur) && //si on est l'allié Grid[posBlocActuel.x + 1, posBlocActuel.y + yactuel, posBlocActuel.z].Walkable ) {//si le sommet n'est pas marqué et qu'il existe, et qu'il n'y a rien au dessus ou que celui du dessus est traversable, que le bloc est walkable queue.Enqueue(new Vector3Int(posBlocActuel.x + 1, posBlocActuel.y + yactuel, posBlocActuel.z)); gridBool[posBlocActuel.x + 1, posBlocActuel.y + yactuel, posBlocActuel.z].SetDistance( parent.GetDistance() + 1); gridBool[posBlocActuel.x + 1, posBlocActuel.y + yactuel, posBlocActuel.z].SetParent(parent); } if (posBlocActuel.y + yactuel >= 0 && posBlocActuel.y + yactuel < sizeY && posBlocActuel.x > 0 && gridBool[posBlocActuel.x - 1, posBlocActuel.y + yactuel, posBlocActuel.z].GetDistance() == -1 && Grid[posBlocActuel.x - 1, posBlocActuel.y + yactuel, posBlocActuel.z] != null && (Grid[posBlocActuel.x - 1, posBlocActuel.y + yactuel + 1, posBlocActuel.z] == null || Grid[posBlocActuel.x - 1, posBlocActuel.y + yactuel + 1, posBlocActuel.z].TraversableChar == TraversableType.ALLTHROUGH || Grid[posBlocActuel.x - 1, posBlocActuel.y + yactuel + 1, posBlocActuel.z].TraversableChar == TraversableType.ALLIESTHROUGH && Grid[posBlocActuel.x - 1, posBlocActuel.y + yactuel + 1, posBlocActuel.z].Joueur == livingPlaceable.Joueur) && Grid[posBlocActuel.x - 1, posBlocActuel.y + yactuel, posBlocActuel.z].Walkable) {//si le sommet n'est pas marqué et qu'il existe, et qu'il n'y a rien au dessus queue.Enqueue(new Vector3Int(posBlocActuel.x - 1, posBlocActuel.y + yactuel, posBlocActuel.z)); gridBool[posBlocActuel.x - 1, posBlocActuel.y + yactuel, posBlocActuel.z].SetDistance( parent.GetDistance() + 1); gridBool[posBlocActuel.x - 1, posBlocActuel.y + yactuel, posBlocActuel.z].SetParent(parent); } if (posBlocActuel.y + yactuel >= 0 && posBlocActuel.y + yactuel < sizeY && posBlocActuel.z < sizeZ - 1 && gridBool[posBlocActuel.x, posBlocActuel.y + yactuel, posBlocActuel.z + 1].GetDistance() == -1 && Grid[posBlocActuel.x, posBlocActuel.y + yactuel, posBlocActuel.z + 1] != null && (Grid[posBlocActuel.x, posBlocActuel.y + yactuel + 1, posBlocActuel.z + 1] == null || Grid[posBlocActuel.x, posBlocActuel.y + yactuel + 1, posBlocActuel.z + 1].TraversableChar == TraversableType.ALLTHROUGH || Grid[posBlocActuel.x, posBlocActuel.y + yactuel + 1, posBlocActuel.z + 1].TraversableChar == TraversableType.ALLIESTHROUGH && Grid[posBlocActuel.x, posBlocActuel.y + yactuel + 1, posBlocActuel.z + 1].Joueur == livingPlaceable.Joueur) && Grid[posBlocActuel.x, posBlocActuel.y + yactuel, posBlocActuel.z + 1].Walkable) {//si le sommet n'est pas marqué et qu'il existe et qu'il n'y a rien au dessus queue.Enqueue(new Vector3Int(posBlocActuel.x, posBlocActuel.y + yactuel, posBlocActuel.z + 1)); gridBool[posBlocActuel.x, posBlocActuel.y + yactuel, posBlocActuel.z + 1].SetDistance( parent.GetDistance() + 1); gridBool[posBlocActuel.x, posBlocActuel.y + yactuel, posBlocActuel.z + 1].SetParent(parent); } if (posBlocActuel.y + yactuel >= 0 && posBlocActuel.y + yactuel < sizeY && posBlocActuel.z > 0 && gridBool[posBlocActuel.x, posBlocActuel.y + yactuel, posBlocActuel.z - 1].GetDistance() == -1 && Grid[posBlocActuel.x, posBlocActuel.y + yactuel, posBlocActuel.z - 1] != null && (Grid[posBlocActuel.x, posBlocActuel.y + yactuel + 1, posBlocActuel.z - 1] == null || Grid[posBlocActuel.x, posBlocActuel.y + yactuel + 1, posBlocActuel.z - 1].TraversableChar == TraversableType.ALLTHROUGH || Grid[posBlocActuel.x, posBlocActuel.y + yactuel + 1, posBlocActuel.z - 1].TraversableChar == TraversableType.ALLIESTHROUGH && Grid[posBlocActuel.x, posBlocActuel.y + yactuel + 1, posBlocActuel.z - 1].Joueur == livingPlaceable.Joueur) && Grid[posBlocActuel.x, posBlocActuel.y + yactuel, posBlocActuel.z - 1].Walkable) {//si le sommet n'est pas marqué et qu'il existe, et qu'il n'y a rien au dessus queue.Enqueue(new Vector3Int(posBlocActuel.x, posBlocActuel.y + yactuel, posBlocActuel.z - 1)); gridBool[posBlocActuel.x, posBlocActuel.y + yactuel, posBlocActuel.z - 1].SetDistance( parent.GetDistance() + 1); gridBool[posBlocActuel.x, posBlocActuel.y + yactuel, posBlocActuel.z - 1].SetParent(parent); } } } } return(gridBool); }