public void TestFindPath() { Pathfinding path = Pathfinding.Singleton(); int[,] res = new int[5, 5] { { 0, 0, 0, 0, 0 }, { 0, 9, 9, 9, 9 }, { 0, 0, 0, 0, 0 }, { 9, 9, 9, 9, 0 }, { 0, 0, 0, 0, 0 } };//[0,4] = 5ieme lement du premier Coordonnees depart = new Coordonnees(0, 4); Coordonnees arrive = new Coordonnees(4, 0); var resultat = path.FindPath(res, depart, arrive); Assert.AreEqual(resultat.Count, 13, "le chemin en serpent est erronné"); res = new int[6, 10] { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {9, 9, 9, 0, 9, 9, 0, 9, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 9, 0, 0}, {0, 9, 9, 9, 9, 9, 9, 9, 9, 9}, {0, 9, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 9, 9, 9, 9, 9, 0, 0} }; resultat = path.FindPath(res, new Coordonnees(0, 0), new Coordonnees(5, 9)); Assert.AreEqual(resultat.Count, 17, "Le chemin trouvé ne correspond pas à la solution 1"); res = new int[6, 10] { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {9, 9, 9, 0, 9, 9, 0, 9, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 9, 0, 0}, {0, 9, 9, 9, 9, 9, 9, 9, 0, 9}, {0, 9, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 9, 9, 9, 9, 9, 0, 0} }; resultat = path.FindPath(res, new Coordonnees(0, 0), new Coordonnees(5, 9)); Assert.AreEqual(resultat.Count, 13, "Le chemin trouvé ne correspond pas au plus court"); }
public void CalculerH(Coordonnees cible, int horizontal, int diagonal) { int h = 0; var diff = (pos - cible).Abs(); if (diagonal < 2 * horizontal) //si diagonal est utile { while (diff.X > 0 && diff.Y > 0) { h += diagonal; diff -= new Coordonnees(1, 1); } while (diff.X + diff.Y > 0) { h += horizontal; diff.X -= 1; } } else //sinon inutile : on compte le nombre de deplacement { while (diff.X + diff.Y > 0) { h += horizontal; diff.X -= 1; } } this._H = h; }
/// <summary> /// REtourne le chemin possible entre le depart et son arrivée /// </summary> /// <param name="tab">Labyrinthe, avec 9 = 0bstacle, int[y,x]</param> /// <param name="depart"></param> /// <param name="arrive"></param> /// <returns></returns> public List<Node> FindPath(int[,] tab, Coordonnees depart, Coordonnees arrive) { var tabNode = PreparerTableau(tab); var result = new List<Node>(); var listeOuverte = new List<Node>(); var listeFerme = new List<Node>(); if (!tabNode[depart.X, depart.Y].Obstacle && !tabNode[arrive.X, arrive.Y].Obstacle) { listeOuverte.Add(tabNode[depart.X, depart.Y]); while (listeOuverte.Count>0 && !listeFerme.Contains(tabNode[arrive.X,arrive.Y])) { //on recupere le plus petit F de la liste ouverte listeOuverte = listeOuverte.OrderBy(cont => cont.F).ToList(); var current = listeOuverte.First(); //on le vire de la liste ouverte listeOuverte.Remove(current); //on ajoute à la liste fermé listeFerme.Add(current); foreach (var node in GetAdjacents(current.pos, tabNode)) { //obstalce ou deja dans liste fermée, ou c'est le depart; on skipe if (node.Obstacle || listeFerme.Contains(node) || node.pos==depart) continue; //si pas dans liste ouverte if (!listeOuverte.Contains(node)) {//on l'ajoute et on indique son parent listeOuverte.Add(node); node.Parent = current; node.CalculerG(this.vertical,this.diag); node.CalculerH(arrive, this.vertical,this.diag); } else if (listeOuverte.Contains(node)) { var newG = node.SimulateCalculerG(current, this.vertical,this.diag); if (newG < node.G && newG > 0) { node.Parent = current; node.CalculerG(this.vertical, this.diag); } } } } } var t = tabNode[arrive.X, arrive.Y]; //si l'arrivée à un parent, le chemin est faisable while(t.Parent!=null) { result.Add(t); t = t.Parent; } if(result.Count>0) result.Add(t); return result; }
static void Main(string[] args) { int[,] res = new int[5, 5] { { 0, 0, 0, 0, 0 }, { 0, 9, 9, 9, 9 }, { 0, 0, 0, 0, 0 }, { 9, 9, 9, 9, 0 }, {0,0,0,0,0}};//[0,4] = 5ieme lement du premier Coordonnees depart = new Coordonnees(0,4); Coordonnees arrive = new Coordonnees(4,0); var resultat = Pathfinding.Singleton().FindPath(res, depart, arrive); resultat.ForEach(x=> Console.WriteLine(x.pos)); Console.ReadLine(); }
public void TestCustomDiag() { Pathfinding path = Pathfinding.Singleton(99, 1000,true); int[,] res = new int[5, 5] { { 0, 0, 0, 0, 0 }, { 0, 9, 9, 9, 9 }, { 0, 0, 0, 0, 0 }, { 9, 9, 9, 9, 0 }, { 0, 0, 0, 0, 0 } };//[0,4] = 5ieme lement du premier Coordonnees depart = new Coordonnees(0, 4); Coordonnees arrive = new Coordonnees(4, 0); var resultat = path.FindPath(res, depart, arrive); Assert.AreEqual(resultat.Count, 17, "le chemin en serpent est erronné"); res = new int[6, 10] { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {9, 9, 9, 0, 9, 9, 0, 9, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 9, 0, 0}, {0, 9, 9, 9, 9, 9, 9, 9, 9, 9}, {0, 9, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 9, 9, 9, 9, 9, 0, 0} }; }
/// <summary> /// Calcule le chemin (prenant en compte les obstacles) pour aller d'un point à un autre /// </summary> /// <param name="oDepart">Coordonnee de depart</param> /// <param name="oArrivee">coordonnee d'arrivee</param> /// <returns>Chemin à emprunter pour y arriver</returns> public Chemin CalculerChemin(Coordonnees oDepart, Coordonnees oArrivee) { var c = new Chemin(); var a = oDepart.X; var b = oArrivee.X; var cpt = oDepart.X; var res = this.GetChemin(oDepart, oArrivee); List<Coordonnees> result = res.Select(t => t.pos).Reverse().ToList(); for (int i = 0; i < result.Count - 1; i++) { var diff = (result[i + 1] - result[i]); c.AddMouvementFin(new Vecteur(diff)); } Console.WriteLine("Chemin calculé pour aller de " + oDepart + " à " + oArrivee + " : "); Console.WriteLine(c.ToString()); return c; }
/// <summary> /// REtourne les coordonnées d'arrivée pour le chemin depuis des coordonnées de depart /// </summary> /// <param name="c"></param> /// <returns></returns> public Coordonnees AppliquerAPosition(Coordonnees c) { Coordonnees res = new Coordonnees(c.X,c.Y); foreach (Vecteur parcour in parcours) { res = res + parcour; } return res; }
public List<Node> GetAdjacents(Coordonnees c, Node[,] table) { List<Node> list = new List<Node>(); bool flagXMin = c.X > 0; bool flagXMax = c.X < table.GetLength(0) - 1; bool flagYMin = c.Y > 0; bool flagYMax = c.Y < table.GetLength(1) - 1; var flagDiagoOk = this.diag < 2*this.vertical; //if (flagXMin) //{ // if (flagYMin) // list.Add(table[c.X - 1, c.Y - 1]); // list.Add(table[c.X - 1, c.Y]); // if (flagYMax) // list.Add(table[c.X - 1, c.Y + 1]); //} //if (flagXMax) //{ // if (flagYMin) // list.Add(table[c.X + 1, c.Y - 1]); // list.Add(table[c.X + 1, c.Y]); // if (flagYMax) // list.Add(table[c.X + 1, c.Y + 1]); //} //if (flagYMin) // list.Add(table[c.X, c.Y - 1]); //if (flagYMax) // list.Add(table[c.X, c.Y + 1]); if (flagXMin) list.Add(table[c.X - 1, c.Y]); if (flagXMax) list.Add(table[c.X + 1, c.Y]); if (flagYMin) list.Add(table[c.X, c.Y - 1]); if (flagYMax) list.Add(table[c.X, c.Y + 1]); var flagUseDiago = list.Where(x => !x.Obstacle).Count() < 2; //necessité utiliser diago pour avancer if(flagDiagoOk || (flagUseDiago)) //si les diago sont ok pour utiliser ou si on a pas le choix { if(flagXMin&&flagYMin) list.Add(table[c.X - 1, c.Y - 1]); if(flagXMin&&flagYMax) list.Add(table[c.X - 1, c.Y + 1]); if(flagXMax&&flagYMin) list.Add(table[c.X + 1, c.Y - 1]); if(flagXMax&&flagYMax) list.Add(table[c.X + 1, c.Y + 1]); } return list; }
private void GererDemandeDeplacementPerso(MouseState ms) { this.CoolDownClick = CoolDownClickValue; var coo = new Coordonnees(ms.X/TailleCaseX, ms.Y/TailleCaseY); var c = this._carteEcran.CalculerChemin(this._personnage.Coordonnees, coo); this._personnage.CheminPerso = c; IMessage m = MessageFactory.GetInstanceOf(TypeMessage.DemandeDeplacement); m.PreparerMessage(new object[] {c}); this._emmeteur.envoyer(m); this._personnage.CoordonneesAvantValidation = this._personnage.Coordonnees; }
private List<Node> GetChemin(Coordonnees depart, Coordonnees arrivee) { //modifier : utiliser une classe pour representer le tableau de cases, qui à un getter en int[,] var temp = new int[this.NombreCasesX,this.NombreCasesY]; for (int i = 0; i < this.NombreCasesX; i++) { for (int j = 0; j < this.NombreCasesY; j++) { temp[i, j] = this._casesContenues[i, j].Franchissable ? 0 : 9; } } var res = Pathfinding.Singleton(100,300,true).FindPath(temp, depart, arrivee); return res; }
public override void Update(GameTime gameTime) { base.Update(gameTime); if (Compteur < 0 && Flagdepl) { Vecteur v; // pour eviter deplacement auto lors de la premiere cases : on ne passe dedans que après un premier compteur déroulé if (this._cheminPrevu.PremierPeekNextFait) { v = this._cheminPrevu.PeekNext(); this.Move(v); this._cheminPrevu.RemoveFirst(); } v = this._cheminPrevu.PeekNext(); this._nextCase = this.Coordonnees + v; if (Flagdepl) //flagdep sera remit à false si pas de chemin dans peeknext { ((Game1)this.Game).DeplacementPerso(v, this); this.Compteur = Game1.NombreTickDeplacement; } } if (Flagdepl && Compteur > -1) Compteur--; if(Flagdepl && this._cheminPrevu!=null) Tick(); #region WIP : gestion de l'arrivée sur une case if (this.Compteur == 0) { var caseCible = ((Game1) this.Game)._carteEcran.GetCase(this._nextCase); var temp = CaseFactory.GetCaseType(caseCible); Console.WriteLine("Case testée : " + this._nextCase + "de type " + temp); Console.WriteLine("********************************************\r\n" + caseCible.OnOver() + "\r\n********************************************\r\n"); if (temp == typeof(CaseTelep)) { var caseTelep = caseCible as CaseTelep; ((Game1) Game).DemanderTeleportation(caseTelep.idTelep); } } #endregion }
public Vecteur(Coordonnees a) : this(a.X,a.Y) { }
public bool DifferenceSurDeuxAxes(Coordonnees c) { var tx = this.X - c.X; var ty = this.Y - c.Y; return Math.Abs(tx + ty) > 1; }
public static Coordonnees FromString(string t) { var temp = t.Split(','); var c = new Coordonnees(Convert.ToInt32(temp[0]), Convert.ToInt32(temp[1])); return c; }
/// <summary> /// Constructeur d'un personnage /// </summary> /// <param name="posX"></param> /// <param name="posY"></param> /// <param name="g">Game </param> public Personnage(int posX, int posY, Game g) : this(g) { this._position = new Coordonnees { X = posX, Y = posY }; this.OffsetCaseDepl = Vecteur.Zero; this.Direction = 2; this.Compteur = -1; // this.compteur = 0; this._cheminPrevu = new Chemin(); this._cfh = this.FinCheminPrevu; this._flagdepl = false; }
public Node(int x, int y, bool ob = false) { this.Parent = null; this.pos = new Coordonnees(x,y); this.Obstacle = ob; }
public CaseBase GetCase(Coordonnees pos) { return this.GetCase(pos.X, pos.Y); }
/// <summary> /// Setter des sprites pour le perso /// </summary> /// <param name="spriteHaut"></param> /// <param name="spriteBas"></param> /// <param name="spriteGauche"></param> /// <param name="spriteDroit"></param> public void SetSprites(AnimatedSprite spriteHaut, AnimatedSprite spriteBas, AnimatedSprite spriteGauche, AnimatedSprite spriteDroit) { this._spritesAnimees = new[] { spriteHaut, spriteDroit, spriteBas, spriteGauche }; for (var i = 0; i < 4; i++) this._spritesAnimees[i].InitialiserAnimation(); this.OffsetCaseSprite = new Coordonnees(((Game1.TailleCaseX - this.GetSprite.Width) / 2), ((Game1.TailleCaseY - this.GetSprite.Height) / 2)); }