public void RechercheSolutionAEtoile() { int numEtape = 1; Sommet s = SommetInitial; SommetsOuverts.Add(s); EtatsSuccessifsOuverts.Add(DeepCopy(SommetsOuverts)); EtatsSuccessifsFermes.Add(DeepCopy(SommetsFermes)); // tant que le noeud n'est pas terminal et que ouverts n'est pas vide while (SommetsOuverts.Count != 0 && s.EndState() == false) { // Le meilleur noeud des ouverts est supposé placé en tête de liste // On le place dans les fermés SommetsOuverts.Remove(s); SommetsFermes.Add(s); // Il faut trouver les noeuds successeurs de s MAJSuccesseurs(s, numEtape); // Inutile de retrier car les insertions ont été faites en respectant l'ordre // On prend le meilleur, donc celui en position 0, pour continuer à explorer les états // A condition qu'il existe bien sûr if (SommetsOuverts.Count > 0) { s = SommetsOuverts.First(); } else { s = null; } EtatsSuccessifsOuverts.Add(DeepCopy(SommetsOuverts)); EtatsSuccessifsFermes.Add(DeepCopy(SommetsFermes)); numEtape++; } SommetsOuverts.Remove(SommetFinal); SommetsFermes.Add(SommetFinal); EtatsSuccessifsOuverts.Add(SommetsOuverts); EtatsSuccessifsFermes.Add(SommetsFermes); // A* terminé // On retourne le chemin qui va du noeud initial au noeud final sous forme de liste // Le chemin est retrouvé en partant du noeud final et en accédant aux parents de manière // itérative jusqu'à ce qu'on tombe sur le noeud initial if (s != null) { PlusCourtChemin.Add(s); CoutPlusCourtChemin = s.CoutTotal; while (!s.IsEqual(SommetInitial)) { s = s.SommetParent; PlusCourtChemin.Insert(0, s); // On insère en position 1 } } }
private void MAJSuccesseurs(Sommet s, int numEtape) { // On fait appel à GetListSucc, méthode abstraite qu'on doit réécrire pour chaque // problème. Elle doit retourner la liste complète des noeuds successeurs de s. List <Sommet> listsucc = s.GetSuccesseurs(); foreach (Sommet succ in listsucc) { // succ est-il une copie d'un nœud déjà vu et placé dans la liste des fermés ? Sommet succBis = SommetsFermes.Find(x => x.IsEqual(succ)); if (succBis == null) { // Rien dans les fermés. Est-il dans les ouverts ? succBis = SommetsOuverts.Find(x => x.IsEqual(succ)); if (succBis != null) { // Il existe, donc on l'a déjà vu, succ n'est qu'une copie de N2Bis // Le nouveau chemin passant par s est-il meilleur ? if (s.CoutCumule + RetrouveArete(s, succ).Cout < succBis.CoutCumule) { // Mise à jour de succBis succBis.CoutCumule = s.CoutCumule + RetrouveArete(s, succ).Cout; // HCost pas recalculé car toujours bon succBis.RecalculeCoutTotal(); // somme de CoutCumule et CoutHeuristique // Mise à jour de la famille .... succBis.SupprimeLienParent(); succBis.SommetParent = s; // Mise à jour des ouverts SommetsOuverts.Remove(succBis); InsertNewNodeInOpenList(succBis, numEtape); } // else on ne fait rien, car le nouveau chemin est moins bon } else { // succ est nouveau, MAJ et insertion dans les ouverts succ.CoutCumule = s.CoutCumule + RetrouveArete(s, succ).Cout; succ.SommetParent = s; succ.CalculCoutTotal(); // somme de GCost et HCost InsertNewNodeInOpenList(succ, numEtape); } } // else il est dans les fermés donc on ne fait rien, // car on a déjà trouvé le plus court chemin pour aller en succ } }