first commit
This commit is contained in:
197
TP01/code.py
Normal file
197
TP01/code.py
Normal file
@@ -0,0 +1,197 @@
|
||||
import heapq
|
||||
import random
|
||||
|
||||
class Noeud:
|
||||
def __init__(self, etat, parent, cout, heuristique):
|
||||
self.etat = etat
|
||||
self.parent = parent
|
||||
self.cout = cout
|
||||
self.heuristique = heuristique
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.cout + self.heuristique < other.cout + other.heuristique
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.etat == other.etat
|
||||
|
||||
def __hash__(self):
|
||||
return hash(tuple(self.etat))
|
||||
|
||||
def __str__(self):
|
||||
return str(self.etat)
|
||||
|
||||
def afficher_etat(etat_jeu) :
|
||||
print(etat_jeu)
|
||||
|
||||
def xor_etat(etat_jeu):
|
||||
xor_total = 0
|
||||
for nb_objets in etat_jeu:
|
||||
xor_total ^= nb_objets
|
||||
return xor_total
|
||||
|
||||
def heuristique(etat_jeu):
|
||||
xor_valeur = xor_etat(etat_jeu)
|
||||
if xor_valeur == 0:
|
||||
# Position désavantageuse (perdante)
|
||||
return 100 + sum(etat_jeu) # Pénalité
|
||||
else:
|
||||
# Position avantageuse (gagnante)
|
||||
return sum(etat_jeu) # Heuristique standard
|
||||
|
||||
def appliquer_mouvement(etat_jeu, tas_index, nombre_objets) :
|
||||
if nombre_objets > etat_jeu[tas_index] :
|
||||
print("Erreur : nombre d'objets à retirer supérieur au nombre d'objets dans le tas.")
|
||||
return etat_jeu
|
||||
else :
|
||||
etat_jeu[tas_index] -= nombre_objets
|
||||
return etat_jeu
|
||||
|
||||
def cout_transition(etat_courant, etat_suivant):
|
||||
return 1
|
||||
|
||||
|
||||
def est_etat_final(etat):
|
||||
return all(pile == 0 for pile in etat)
|
||||
|
||||
def generer_successeurs(etat):
|
||||
successeurs = []
|
||||
for i in range(len(etat)):
|
||||
if etat[i] > 0:
|
||||
for j in range(1, etat[i] + 1):
|
||||
nouvel_etat = etat[:]
|
||||
nouvel_etat[i] -= j
|
||||
successeurs.append(nouvel_etat)
|
||||
return successeurs
|
||||
|
||||
def algorithme_a_star(etat_initial):
|
||||
noeud_initial = Noeud(etat_initial, None, 0, heuristique(etat_initial))
|
||||
frontiere = []
|
||||
heapq.heappush(frontiere, noeud_initial)
|
||||
visites = set()
|
||||
|
||||
while frontiere:
|
||||
noeud_courant = heapq.heappop(frontiere)
|
||||
|
||||
if est_etat_final(noeud_courant.etat):
|
||||
chemin = []
|
||||
while noeud_courant:
|
||||
chemin.append(noeud_courant.etat)
|
||||
noeud_courant = noeud_courant.parent
|
||||
return chemin[::-1]
|
||||
|
||||
visites.add(tuple(noeud_courant.etat))
|
||||
|
||||
for successeur in generer_successeurs(noeud_courant.etat):
|
||||
if tuple(successeur) not in visites:
|
||||
cout = noeud_courant.cout + cout_transition(noeud_courant.etat, successeur)
|
||||
heur = heuristique(successeur)
|
||||
noeud_successeur = Noeud(successeur, noeud_courant, cout, heur)
|
||||
heapq.heappush(frontiere, noeud_successeur)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def reconstruire_chemin(noeud_final):
|
||||
"""
|
||||
Reconstruit la séquence de mouvements depuis l’état initial jusqu’à l’état final.
|
||||
|
||||
:param noeud_final: Le nœud final de l'algorithme A*.
|
||||
:return: Une liste des états représentant le chemin de l'état initial à l'état final.
|
||||
"""
|
||||
chemin = []
|
||||
noeud_courant = noeud_final
|
||||
while noeud_courant:
|
||||
chemin.append(noeud_courant.etat)
|
||||
noeud_courant = noeud_courant.parent
|
||||
return chemin[::-1]
|
||||
|
||||
def sauvegarder_partie(historique, fichier="historique_parties.txt"):
|
||||
"""
|
||||
Sauvegarde l'historique de la partie dans un fichier.
|
||||
|
||||
:param historique: Liste des coups effectués pendant la partie.
|
||||
:param fichier: Nom du fichier où sauvegarder l'historique.
|
||||
"""
|
||||
with open(fichier, "a") as f:
|
||||
f.write("Nouvelle partie\n")
|
||||
for coup in historique:
|
||||
f.write(f"{coup}\n")
|
||||
f.write("\n")
|
||||
|
||||
|
||||
def jeu_nim(etat_initial):
|
||||
etat = etat_initial[:]
|
||||
historique = []
|
||||
while not est_etat_final(etat):
|
||||
afficher_etat(etat)
|
||||
try:
|
||||
pile = int(input("Entrez le numéro de la pile (1, 2, 3, ...): ")) - 1
|
||||
nb_objets = int(input("Entrez le nombre d'objets à retirer: "))
|
||||
historique.append(f"Joueur: Pile {pile + 1}, Objets retirés: {nb_objets}")
|
||||
appliquer_mouvement(etat, pile, nb_objets)
|
||||
afficher_etat(etat)
|
||||
except ValueError:
|
||||
print("Entrée invalide. Veuillez entrer des nombres entiers.")
|
||||
continue
|
||||
|
||||
if est_etat_final(etat):
|
||||
print("\nFélicitations ! Vous avez gagné !")
|
||||
break
|
||||
|
||||
# Tour de l'IA
|
||||
chemin_optimal = algorithme_a_star(etat)
|
||||
if chemin_optimal and len(chemin_optimal) > 1:
|
||||
etat_ia = chemin_optimal[1]
|
||||
historique.append(f"IA: Pile {pile + 1}, Objets retirés: {nb_objets}")
|
||||
print("\nL'IA joue...")
|
||||
etat = etat_ia
|
||||
|
||||
if est_etat_final(etat):
|
||||
print("\n L'IA a gagné !")
|
||||
break
|
||||
sauvegarder_partie(historique)
|
||||
|
||||
def pile_random(etat) :
|
||||
piles_non_vides = [i for i, pile in enumerate(etat) if pile > 0]
|
||||
return random.choice(piles_non_vides)
|
||||
|
||||
|
||||
def nb_objets_random(etat, pile):
|
||||
return random.randint(1, etat[pile])
|
||||
|
||||
|
||||
def jeu_nim_random(etat_initial):
|
||||
etat = etat_initial[:]
|
||||
historique = []
|
||||
while not est_etat_final(etat):
|
||||
afficher_etat(etat)
|
||||
try:
|
||||
pile = pile_random(etat)
|
||||
nb_objets = nb_objets_random(etat, pile)
|
||||
historique.append(f"Joueur: Pile {pile + 1}, Objets retirés: {nb_objets}")
|
||||
appliquer_mouvement(etat, pile, nb_objets)
|
||||
afficher_etat(etat)
|
||||
except ValueError:
|
||||
print("Entrée invalide. Veuillez entrer des nombres entiers.")
|
||||
continue
|
||||
|
||||
if est_etat_final(etat):
|
||||
print("\nFélicitations ! Vous avez gagné !")
|
||||
break
|
||||
|
||||
# Tour de l'IA
|
||||
chemin_optimal = algorithme_a_star(etat)
|
||||
if chemin_optimal and len(chemin_optimal) > 1:
|
||||
etat_ia = chemin_optimal[1]
|
||||
historique.append(f"IA: Pile {pile + 1}, Objets retirés: {nb_objets}")
|
||||
print("\nL'IA joue...")
|
||||
etat = etat_ia
|
||||
|
||||
if est_etat_final(etat):
|
||||
print("\n L'IA a gagné !")
|
||||
break
|
||||
sauvegarder_partie(historique)
|
||||
|
||||
|
||||
etat_initial = [3, 4, 5]
|
||||
jeu_nim_random(etat_initial)
|
Reference in New Issue
Block a user