diff --git a/nim.py b/nim.py new file mode 100644 index 0000000..515c05e --- /dev/null +++ b/nim.py @@ -0,0 +1,196 @@ +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() + diff --git a/resultats.json b/resultats.json new file mode 100644 index 0000000..1040c46 --- /dev/null +++ b/resultats.json @@ -0,0 +1,170 @@ +[ + { + "gagnant": "IA" + }, + { + "gagnant": "IA", + "historique": [ + { + "joueur": "utilisateur", + "tas": 0, + "objets_retires": 1, + "etat_apres": [ + 2, + 4, + 5 + ] + }, + { + "joueur": "IA", + "tas": 0, + "objets_retires": 1, + "etat_apres": [ + 2, + 3, + 5 + ] + }, + { + "joueur": "utilisateur", + "tas": 0, + "objets_retires": 1, + "etat_apres": [ + 1, + 3, + 5 + ] + }, + { + "joueur": "IA", + "tas": 0, + "objets_retires": 1, + "etat_apres": [ + 1, + 3, + 0 + ] + }, + { + "joueur": "utilisateur", + "tas": 0, + "objets_retires": 1, + "etat_apres": [ + 0, + 3, + 0 + ] + }, + { + "joueur": "IA", + "tas": 0, + "objets_retires": 1, + "etat_apres": [ + 0, + 0, + 0 + ] + } + ] + }, + { + "etat jeu initial": [ + 3, + 4, + 5 + ], + "gagnant": "IA", + "historique": [ + { + "joueur": "utilisateur", + "tas": 0, + "objets_retires": 3, + "etat_apres": [ + 0, + 4, + 5 + ] + }, + { + "joueur": "IA", + "tas": 0, + "objets_retires": 1, + "etat_apres": [ + 0, + 1, + 5 + ] + }, + { + "joueur": "utilisateur", + "tas": 2, + "objets_retires": 5, + "etat_apres": [ + 0, + 1, + 0 + ] + }, + { + "joueur": "IA", + "tas": 0, + "objets_retires": 1, + "etat_apres": [ + 0, + 0, + 0 + ] + } + ] + }, + { + "etat jeu initial": [ + 4, + 4, + 3 + ], + "gagnant": "IA", + "historique": [ + { + "joueur": "utilisateur", + "tas": 0, + "objets_retires": 4, + "etat_apres": [ + 0, + 4, + 3 + ] + }, + { + "joueur": "IA", + "tas": 0, + "objets_retires": 1, + "etat_apres": [ + 0, + 1, + 3 + ] + }, + { + "joueur": "utilisateur", + "tas": 1, + "objets_retires": 1, + "etat_apres": [ + 0, + 0, + 3 + ] + }, + { + "joueur": "IA", + "tas": 0, + "objets_retires": 1, + "etat_apres": [ + 0, + 0, + 0 + ] + } + ] + } +] \ No newline at end of file