Nim_python/nim.py

217 lines
6.7 KiB
Python
Raw Permalink Normal View History

2024-10-23 11:39:03 +02:00
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)
2024-10-23 11:48:36 +02:00
"""tas_index = int(input("Sélectionnez le tas (index) : "))
2024-10-23 11:39:03 +02:00
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})
2024-10-23 11:48:36 +02:00
return"""
# Tour de l'IA
print("Tour de l'IA 1...")
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 1",
"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 1 a gagné !")
enregistrer_resultat({"etat_jeu_initial": etat_jeu_initial, "gagnant": "IA 1", "historique": historique_actions})
2024-10-23 11:39:03 +02:00
return
2024-10-23 11:48:36 +02:00
2024-10-23 11:39:03 +02:00
# Tour de l'IA
2024-10-23 11:48:36 +02:00
print("Tour de l'IA 2...")
2024-10-23 11:39:03 +02:00
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({
2024-10-23 11:48:36 +02:00
"joueur": "IA 2",
2024-10-23 11:39:03 +02:00
"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):
2024-10-23 11:48:36 +02:00
print("L'IA 2 a gagné !")
enregistrer_resultat({"etat_jeu_initial": etat_jeu_initial, "gagnant": "IA 2", "historique": historique_actions})
2024-10-23 11:39:03 +02:00
return
jouer_contre_ia()