import heapq # Fonction heuristique: Somme des objets restants (admissible) def heuristique(etat_jeu): return sum(etat_jeu) # Fonction qui vérifie si l'état est final (tous les tas sont vides) def est_etat_final(etat_jeu): return all(tas == 0 for tas in etat_jeu) # Fonction qui génère tous les mouvements possibles depuis un état donné def generer_mouvements(etat_jeu): mouvements_possibles = [] for i in range(len(etat_jeu)): if etat_jeu[i] > 0: for retirer in range(1, etat_jeu[i] + 1): nouvel_etat = etat_jeu.copy() nouvel_etat[i] -= retirer mouvements_possibles.append(nouvel_etat) return mouvements_possibles # Classe Noeud utilisée pour l'algorithme A* class Noeud: def __init__(self, etat, parent=None, g=0, h=0): self.etat = etat self.parent = parent self.g = g # Coût du chemin (g(n)) self.h = h # Heuristique (h(n)) # Priorité des nœuds basée sur la somme g + h def __lt__(self, other): return (self.g + self.h) < (other.g + other.h) # Algorithme A* pour trouver le chemin optimal vers la victoire def algorithme_a_star(etat_initial): # Initialisation de la file de priorité open_list = [] heapq.heappush(open_list, Noeud(etat_initial, g=0, h=heuristique(etat_initial))) closed_list = set() while open_list: # Récupérer le nœud avec le plus faible f(n) = g(n) + h(n) noeud_courant = heapq.heappop(open_list) # Vérifier si c'est l'état final if est_etat_final(noeud_courant.etat): return reconstruire_chemin(noeud_courant) # Ajouter l'état courant aux états visités closed_list.add(tuple(noeud_courant.etat)) # Générer les mouvements légaux for mouvement in generer_mouvements(noeud_courant.etat): if tuple(mouvement) in closed_list: continue g_nouveau = noeud_courant.g + 1 h_nouveau = heuristique(mouvement) nouveau_noeud = Noeud(mouvement, parent=noeud_courant, g=g_nouveau, h=h_nouveau) heapq.heappush(open_list, nouveau_noeud) return None # Si aucun chemin n'est trouvé # Fonction pour reconstruire le chemin optimal def reconstruire_chemin(noeud_final): chemin = [] noeud_courant = noeud_final while noeud_courant is not None: chemin.append(noeud_courant.etat) noeud_courant = noeud_courant.parent return chemin[::-1] # Retourner le chemin dans l'ordre correct # Test de l'algorithme A* avec l'état initial [3, 4, 5] etat_initial = [3, 4, 5] chemin_optimal = algorithme_a_star(etat_initial) print("Chemin optimal:", chemin_optimal)