/* Obtenir la séquence d'actions à partir d'un noeud */ public Queue SequenceActions(Noeud n) { var actions = new Stack(); while (n.Parent != null) { actions.Push(n.ActionParent); n = n.Parent; } var sequence = new Queue(); foreach (Action a in actions) { sequence.Enqueue(a); } return(sequence); }
private int CalculHeuristique(Noeud noeud) { int min = 200; foreach (int x in noeud.EtatNoeud.ListePoussiere) { int distance = DistanceManhattan(noeud.EtatNoeud.Position, x); if (distance < min) { min = distance; } } if (noeud.ActionParent == Action.ASPIRER) { min = 0; } return(min + noeud.EtatNoeud.ListePoussiere.Count + noeud.EtatNoeud.ListeBijoux.Count); }
// Fonction générique d'exploration // Retourne null en cas d'erreur public Queue Explorer(Etat etatInitial, int nbAction, Func <Etat, Etat, bool> testBut) { /* Création du graphe */ Graphe arbreRecherche = new Graphe(etatInitial); /* Initialisation de la frange */ List <Noeud> frange = new List <Noeud> { arbreRecherche.Racine }; /* Boucle de construction de la frange */ // En cas d'échec, retourne un plan d'action vide while (true) { // Cas d'échec if (frange.Count == 0) { return(null); } // Test de but Noeud noeud = frange.First(); frange.RemoveAt(0); if (testBut(noeud.EtatNoeud, etatInitial) || noeud.Profondeur == nbAction) { return(arbreRecherche.SequenceActions(noeud)); } // Expansion du noeud DejaVisites.Add(noeud.EtatNoeud); foreach (Noeud n in noeud.FonctionSuccession()) { frange = InsererNoeud(frange, n); noeud.AjouterEnfant(n); } } }
/* Constructeur du noeud : correspond à MAKE-NODE(..) */ // Le noeud parent est null pour le noeud racine // Parent : le noeud parent // Action : l'action effectuée par le parent public Noeud(Etat e, Noeud parent, Action action) { if (e == null) { throw new ArgumentNullException("e"); } EtatNoeud = e; Parent = parent; _listeEnfants = new List <Noeud>(); ActionParent = action; Heuristique = -1; if (parent != null) { Profondeur = Parent.Profondeur + 1; CoutChemin = Parent.CoutChemin + 1; // Une action = 1 unité d'énergie } // Cas de la racine else { Profondeur = 0; CoutChemin = 0; } }
// Insère le noeud dans la frange, représentée sous forme de liste protected abstract List <Noeud> InsererNoeud(List <Noeud> frange, Noeud noeud);
/* Constructeur du graphe */ // Prend en paramètre l'état initial pour l'exploration et l'ensemble de la grille public Graphe(Etat etatInitial) { Racine = new Noeud(etatInitial, null, Action.RIEN); }
// Fonction de succession des états /* En considérant le couple (position x, état de la pièce) : * - <(x, BIJOU), RAMASSER> -> (x, VIDE) * - <(x, POUSSIEREBIJOU), RAMASSER> -> (x, POUSSIERE) * - <(x, POUSSIERE), ASPIRER> -> (x, VIDE) * - <(x, VIDE), HAUT> -> (x-10, ObjetCase[x-10]) * - <(x, VIDE), BAS> -> (x+10, ObjetCase[x+10]) * - <(x, VIDE), GAUCHE> -> (x-1, ObjetCase[x-1]) * - <(x, VIDE), DROITE> -> (x+1, ObjetCase[x+1]) * Les autres possibilités sont illégales. */ public List <Noeud> FonctionSuccession() { List <Noeud> successeurs = new List <Noeud>(); Etat etat; Noeud noeud; switch (EtatNoeud.EtatPiece) { case ObjetCase.BIJOUX: { List <int> listeBijoux = new List <int>(EtatNoeud.ListeBijoux); listeBijoux.Remove(EtatNoeud.Position); etat = new Etat(EtatNoeud.Position, ObjetCase.VIDE, EtatNoeud.ListePoussiere, listeBijoux); noeud = new Noeud(etat, this, Action.RAMASSER); successeurs.Add(noeud); break; } case ObjetCase.POUSSIEREBIJOUX: { List <int> listeBijoux = new List <int>(EtatNoeud.ListeBijoux); listeBijoux.Remove(EtatNoeud.Position); etat = new Etat(EtatNoeud.Position, ObjetCase.POUSSIERE, EtatNoeud.ListePoussiere, listeBijoux); noeud = new Noeud(etat, this, Action.RAMASSER); successeurs.Add(noeud); break; } case ObjetCase.POUSSIERE: { List <int> listePoussiere = new List <int>(EtatNoeud.ListePoussiere); listePoussiere.Remove(EtatNoeud.Position); etat = new Etat(EtatNoeud.Position, ObjetCase.VIDE, listePoussiere, EtatNoeud.ListeBijoux); noeud = new Noeud(etat, this, Action.ASPIRER); successeurs.Add(noeud); break; } case ObjetCase.VIDE: { // Haut if (EtatNoeud.Position >= 10) { int pos = EtatNoeud.Position - 10; ObjetCase piece = ObjetCase.VIDE; if (EtatNoeud.ListePoussiere.Exists(x => x == pos) && EtatNoeud.ListeBijoux.Exists(x => x == pos)) { piece = ObjetCase.POUSSIEREBIJOUX; } else if (EtatNoeud.ListePoussiere.Exists(x => x == pos)) { piece = ObjetCase.POUSSIERE; } else if (EtatNoeud.ListeBijoux.Exists(x => x == pos)) { piece = ObjetCase.BIJOUX; } etat = new Etat(pos, piece, EtatNoeud.ListePoussiere, EtatNoeud.ListeBijoux); noeud = new Noeud(etat, this, Action.HAUT); successeurs.Add(noeud); } // Bas if (EtatNoeud.Position < 90) { int pos = EtatNoeud.Position + 10; ObjetCase piece = ObjetCase.VIDE; if (EtatNoeud.ListePoussiere.Exists(x => x == pos) && EtatNoeud.ListeBijoux.Exists(x => x == pos)) { piece = ObjetCase.POUSSIEREBIJOUX; } else if (EtatNoeud.ListePoussiere.Exists(x => x == pos)) { piece = ObjetCase.POUSSIERE; } else if (EtatNoeud.ListeBijoux.Exists(x => x == pos)) { piece = ObjetCase.BIJOUX; } etat = new Etat(pos, piece, EtatNoeud.ListePoussiere, EtatNoeud.ListeBijoux); noeud = new Noeud(etat, this, Action.BAS); successeurs.Add(noeud); } // Gauche if ((EtatNoeud.Position % 10) != 0) { int pos = EtatNoeud.Position - 1; ObjetCase piece = ObjetCase.VIDE; if (EtatNoeud.ListePoussiere.Exists(x => x == pos) && EtatNoeud.ListeBijoux.Exists(x => x == pos)) { piece = ObjetCase.POUSSIEREBIJOUX; } else if (EtatNoeud.ListePoussiere.Exists(x => x == pos)) { piece = ObjetCase.POUSSIERE; } else if (EtatNoeud.ListeBijoux.Exists(x => x == pos)) { piece = ObjetCase.BIJOUX; } etat = new Etat(pos, piece, EtatNoeud.ListePoussiere, EtatNoeud.ListeBijoux); noeud = new Noeud(etat, this, Action.GAUCHE); successeurs.Add(noeud); } // Droite if (((EtatNoeud.Position + 1) % 10) != 0) { int pos = EtatNoeud.Position + 1; ObjetCase piece = ObjetCase.VIDE; if (EtatNoeud.ListePoussiere.Exists(x => x == pos) && EtatNoeud.ListeBijoux.Exists(x => x == pos)) { piece = ObjetCase.POUSSIEREBIJOUX; } else if (EtatNoeud.ListePoussiere.Exists(x => x == pos)) { piece = ObjetCase.POUSSIERE; } else if (EtatNoeud.ListeBijoux.Exists(x => x == pos)) { piece = ObjetCase.BIJOUX; } etat = new Etat(pos, piece, EtatNoeud.ListePoussiere, EtatNoeud.ListeBijoux); noeud = new Noeud(etat, this, Action.DROITE); successeurs.Add(noeud); } break; } } return(successeurs); }