197 lines
5.9 KiB
Python
197 lines
5.9 KiB
Python
import random
|
|
|
|
# exo 1
|
|
|
|
def afficher_etat(etat_jeu):
|
|
print("État du jeu:", etat_jeu)
|
|
|
|
|
|
|
|
|
|
# exo 2
|
|
|
|
|
|
def generer_mouvements(etat_jeu):
|
|
mouvements = []
|
|
for i in range(len(etat_jeu)):
|
|
for j in range(1, etat_jeu[i] + 1):
|
|
nouveau_etat = etat_jeu.copy()
|
|
nouveau_etat[i] -= j
|
|
mouvements.append(nouveau_etat)
|
|
return mouvements
|
|
|
|
|
|
|
|
|
|
|
|
# exo 3
|
|
|
|
def appliquer_mouvement(etat_jeu, tas_index, nb_objets):
|
|
etat_jeu[tas_index] -= nb_objets
|
|
return etat_jeu
|
|
|
|
|
|
# exo 4
|
|
|
|
def heuristique(etat_jeu):
|
|
return sum(etat_jeu) # Total des objets restants
|
|
|
|
def heuristique_nim_sum(etat_jeu):
|
|
nim_sum = 0
|
|
for tas in etat_jeu:
|
|
nim_sum ^= tas # Calculer la somme de Nim (XOR)
|
|
return nim_sum # Retourne le Nim-sum pour guider l'algorithme A*
|
|
|
|
|
|
# exo 5
|
|
|
|
def est_etat_final(etat_jeu):
|
|
return all(tas == 0 for tas in etat_jeu)
|
|
|
|
def cout_mouvement():
|
|
return 1
|
|
|
|
|
|
#exo 6
|
|
|
|
class Noeud:
|
|
def __init__(self, etat, parent=None, g=0, h=0):
|
|
self.etat = etat # L'état actuel du jeu (tas d'objets)
|
|
self.parent = parent # Le nœud précédent
|
|
self.g = g # Coût réel du chemin jusqu'à ce nœud
|
|
self.h = h # Heuristique (estimation du coût restant)
|
|
self.f = g + h # Coût total (g + h)
|
|
|
|
# Ajout de la méthode __lt__ pour comparer les nœuds
|
|
def __lt__(self, autre):
|
|
return self.f < autre.f # Comparer en fonction du coût total
|
|
|
|
|
|
import heapq
|
|
def algorithme_a_star(etat_initial):
|
|
open_list = []
|
|
closed_list = set() # Ensemble pour stocker les états déjà visités
|
|
|
|
# Ajouter l'état initial à la file de priorité
|
|
heapq.heappush(open_list, Noeud(etat_initial, g=0, h=heuristique_nim_sum(etat_initial)))
|
|
|
|
while open_list:
|
|
# Extraire le nœud avec le plus petit coût total (g + h)
|
|
current_node = heapq.heappop(open_list)
|
|
|
|
# Si nous avons atteint l'état final, reconstruire le chemin
|
|
if est_etat_final(current_node.etat):
|
|
return reconstruire_chemin(current_node)
|
|
|
|
# Ajouter l'état actuel dans la liste des états explorés
|
|
closed_list.add(tuple(current_node.etat))
|
|
|
|
# Générer les mouvements possibles à partir de l'état actuel
|
|
for mouvement in generer_mouvements(current_node.etat):
|
|
# Si l'état résultant a déjà été visité, on l'ignore
|
|
if tuple(mouvement) in closed_list:
|
|
continue
|
|
|
|
# Créer un nouveau nœud pour cet état
|
|
nouveau_noeud = Noeud(mouvement, current_node, current_node.g + cout_mouvement(), heuristique_nim_sum(mouvement))
|
|
|
|
# Ajouter le nouveau nœud à la file de priorité
|
|
heapq.heappush(open_list, nouveau_noeud)
|
|
|
|
|
|
|
|
# exo 8
|
|
|
|
|
|
|
|
|
|
def reconstruire_chemin(noeud_final):
|
|
chemin = []
|
|
noeud_courant = noeud_final
|
|
while noeud_courant: # Tant qu'il y a un parent
|
|
chemin.append(noeud_courant.etat) # Ajouter l'état actuel au chemin
|
|
noeud_courant = noeud_courant.parent # Passer au nœud parent
|
|
return chemin[::-1] # Inverser le chemin pour avoir de l'état initial à l'état final
|
|
|
|
|
|
# exo 9
|
|
|
|
import json
|
|
import os
|
|
|
|
# Fonction pour écrire les résultats dans un fichier JSON
|
|
def enregistrer_resultat(resultat):
|
|
# Vérifier si le fichier JSON existe déjà
|
|
if os.path.exists("resultats.json"):
|
|
# Charger les résultats existants
|
|
with open("resultats.json", "r") as fichier:
|
|
try:
|
|
resultats = json.load(fichier)
|
|
except json.JSONDecodeError:
|
|
resultats = [] # Si le fichier est vide ou corrompu
|
|
else:
|
|
resultats = []
|
|
|
|
# Ajouter le nouveau résultat
|
|
resultats.append(resultat)
|
|
|
|
# Sauvegarder les résultats mis à jour dans le fichier JSON
|
|
with open("resultats.json", "w") as fichier:
|
|
json.dump(resultats, fichier, indent=4)
|
|
|
|
|
|
|
|
def jouer_contre_ia():
|
|
etat_jeu = [random.randint(1, 10) for _ in range(3)]
|
|
etat_jeu_initial = etat_jeu.copy()
|
|
historique_actions = [] # Liste pour enregistrer l'historique des actions
|
|
|
|
while not est_etat_final(etat_jeu):
|
|
# Tour de l'utilisateur
|
|
afficher_etat(etat_jeu)
|
|
|
|
tas_index = int(input("Sélectionnez le tas (index) : "))
|
|
nb_objets = int(input("Combien d'objets retirer ? "))
|
|
|
|
if nb_objets > etat_jeu[tas_index]:
|
|
print("Erreur : Vous ne pouvez pas retirer plus d'objets que ce qui est disponible.")
|
|
continue
|
|
|
|
# Appliquer le mouvement de l'utilisateur et ajouter à l'historique
|
|
etat_jeu = appliquer_mouvement(etat_jeu, tas_index, nb_objets)
|
|
historique_actions.append({
|
|
"joueur": "utilisateur",
|
|
"tas": tas_index,
|
|
"objets_retires": nb_objets,
|
|
"etat_apres": etat_jeu.copy() # Copier l'état après le mouvement
|
|
})
|
|
|
|
if est_etat_final(etat_jeu):
|
|
print("Vous avez gagné !")
|
|
enregistrer_resultat({"etat_jeu_initial": etat_jeu_initial, "gagnant": "utilisateur", "historique": historique_actions})
|
|
return
|
|
|
|
# Tour de l'IA
|
|
print("Tour de l'IA...")
|
|
etat_jeu = algorithme_a_star(etat_jeu)[1] # IA applique A* et choisit le meilleur mouvement
|
|
|
|
# Simuler une action de l'IA (ici c'est un exemple, tu devras remplacer cela par un vrai mouvement)
|
|
historique_actions.append({
|
|
"joueur": "IA",
|
|
"tas": 0, # Exemple de tas choisi par l'IA (à adapter)
|
|
"objets_retires": 1, # Exemple d'objets retirés par l'IA (à adapter)
|
|
"etat_apres": etat_jeu.copy() # Copier l'état après le mouvement
|
|
})
|
|
|
|
afficher_etat(etat_jeu)
|
|
|
|
if est_etat_final(etat_jeu):
|
|
print("L'IA a gagné !")
|
|
enregistrer_resultat({"etat_jeu_initial": etat_jeu_initial, "gagnant": "IA", "historique": historique_actions})
|
|
return
|
|
|
|
|
|
|
|
jouer_contre_ia()
|
|
|