import heapq def algorithme_a_star(etat_initial): # File de priorité (tas) pour les nœuds à explorer file_priorite = [] # Ajouter l'état initial dans la file de priorité (f(n), g(n), état) heapq.heappush(file_priorite, (0 + heuristique(etat_initial), 0, etat_initial)) # Dictionnaire pour stocker le coût minimal pour atteindre chaque état cout_minimal = {tuple(etat_initial): 0} # Dictionnaire pour stocker le parent de chaque état (reconstruction du chemin) predecesseurs = {tuple(etat_initial): None} # Ensemble pour stocker les états déjà visités etats_visites = set() while file_priorite: # Extraire l'état avec le plus faible coût estimé f(n) _, cout_actuel, etat_actuel = heapq.heappop(file_priorite) # Convertir l'état en tuple pour le stockage dans les ensembles etat_tuple = tuple(etat_actuel) # Si l'état a déjà été visité, on l'ignore if etat_tuple in etats_visites: continue # Marquer l'état comme visité etats_visites.add(etat_tuple) # Vérifier si l'état actuel est l'état final if est_etat_final(etat_actuel): # Reconstruire le chemin optimal chemin = [] while etat_actuel is not None: chemin.append(etat_actuel) etat_actuel = predecesseurs[tuple(etat_actuel)] chemin.reverse() # On inverse le chemin pour l'avoir dans l'ordre return chemin # Générer tous les mouvements possibles à partir de l'état actuel mouvements_possibles = generer_mouvements(etat_actuel) for nouvel_etat in mouvements_possibles: # Calculer le coût du mouvement (toujours 1 dans notre cas) cout_mouvement_actuel = cout_actuel + cout_mouvement(etat_actuel, nouvel_etat) # Si le nouvel état est rencontré avec un coût inférieur à celui déjà connu etat_tuple_nouveau = tuple(nouvel_etat) # Vérifier si l'état a déjà été visité ou si le coût est inférieur if etat_tuple_nouveau not in etats_visites or cout_mouvement_actuel < cout_minimal.get(etat_tuple_nouveau, float('inf')): cout_minimal[etat_tuple_nouveau] = cout_mouvement_actuel predecesseurs[etat_tuple_nouveau] = etat_actuel # Stocker le parent # Calculer f(n) = g(n) + h(n) f_n = cout_mouvement_actuel + heuristique(nouvel_etat) # Ajouter le nouvel état dans la file de priorité heapq.heappush(file_priorite, (f_n, cout_mouvement_actuel, nouvel_etat)) # Si aucun chemin n'a été trouvé (ce qui ne devrait pas arriver dans le jeu de Nim) return None etat_initial = [3, 4, 5] # Exemple d'état initial # Appel de l'algorithme A* pour trouver le chemin optimal chemin_optimal = algorithme_a_star(etat_initial) # Affichage du chemin for etat in chemin_optimal: print(etat)