python/heur.py

111 lines
3.4 KiB
Python
Raw Permalink Normal View History

2024-10-23 11:57:12 +02:00
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
2024-10-23 15:43:09 +02:00
# Fonction pour appliquer un mouvement à l'état du jeu
def appliquer_mouvement(etat_jeu, tas_index, nb_objets):
if tas_index < 0 or tas_index >= len(etat_jeu):
raise ValueError("Index du tas invalide.")
if nb_objets <= 0:
raise ValueError("Le nombre d'objets à retirer doit être supérieur à 0.")
if nb_objets > etat_jeu[tas_index]:
raise ValueError(f"Le tas {tas_index + 1} ne contient pas suffisamment d'objets pour retirer {nb_objets} objets.")
nouvel_etat = etat_jeu.copy()
nouvel_etat[tas_index] -= nb_objets
return nouvel_etat
2024-10-23 11:57:12 +02:00
# 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
2024-10-23 15:43:09 +02:00
self.g = g
self.h = h
2024-10-23 11:57:12 +02:00
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):
2024-10-23 15:43:09 +02:00
2024-10-23 11:57:12 +02:00
open_list = []
heapq.heappush(open_list, Noeud(etat_initial, g=0, h=heuristique(etat_initial)))
closed_list = set()
while open_list:
2024-10-23 15:43:09 +02:00
2024-10-23 11:57:12 +02:00
noeud_courant = heapq.heappop(open_list)
2024-10-23 15:43:09 +02:00
2024-10-23 11:57:12 +02:00
if est_etat_final(noeud_courant.etat):
return reconstruire_chemin(noeud_courant)
closed_list.add(tuple(noeud_courant.etat))
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)
2024-10-23 15:43:09 +02:00
return None
2024-10-23 11:57:12 +02:00
# 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
2024-10-23 15:43:09 +02:00
return chemin[::-1]
2024-10-23 11:57:12 +02:00
etat_initial = [3, 4, 5]
chemin_optimal = algorithme_a_star(etat_initial)
print("Chemin optimal:", chemin_optimal)
2024-10-23 15:43:09 +02:00
etat_jeu = [3, 4, 5]
nouvel_etat_1 = appliquer_mouvement(etat_jeu, 0, 2)
print("Nouvel état après retrait de 2 objets du tas 1:", nouvel_etat_1)
nouvel_etat_2 = appliquer_mouvement(etat_jeu, 2, 3)
print("Nouvel état après retrait de 3 objets du tas 3:", nouvel_etat_2)
try:
nouvel_etat_3 = appliquer_mouvement(etat_jeu, 5, 2)
except ValueError as e:
print(e)
try:
nouvel_etat_4 = appliquer_mouvement(etat_jeu, 1, 5)
except ValueError as e:
print(e)
try:
nouvel_etat_5 = appliquer_mouvement(etat_jeu, 0, 0)
except ValueError as e:
print(e)