From 02e56f43a7b143255694519d025eb093ed0a9a3d Mon Sep 17 00:00:00 2001 From: Guillaume VALLAT Date: Wed, 23 Oct 2024 11:11:19 +0200 Subject: [PATCH] =?UTF-8?q?T=C3=A9l=C3=A9verser=20les=20fichiers=20vers=20?= =?UTF-8?q?"/"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- heuristique_Nim.py | 161 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 heuristique_Nim.py diff --git a/heuristique_Nim.py b/heuristique_Nim.py new file mode 100644 index 0000000..d69ffe6 --- /dev/null +++ b/heuristique_Nim.py @@ -0,0 +1,161 @@ +import json +import random +import datetime +import heapq # Pour la file de priorité (algorithme A*) + +# Fonction pour afficher l'état actuel du jeu +def afficher_etat(etat_jeu): + print("\nVoici l'état actuel des tas :") + for i, nb_objets in enumerate(etat_jeu): + print(f"Tas {i+1}: {nb_objets} objets") + print() + +# Fonction pour générer tous les mouvements possibles +def generer_mouvements(etat_jeu): + mouvements = [] + for i, nb_objets in enumerate(etat_jeu): + for n in range(1, nb_objets + 1): + nouvel_etat = etat_jeu[:] + nouvel_etat[i] -= n + mouvements.append(nouvel_etat) + return mouvements + +# Fonction pour appliquer un mouvement à l'état +def appliquer_mouvement(etat_jeu, tas_index, nb_objets): + if 1 <= nb_objets <= etat_jeu[tas_index]: + etat_jeu[tas_index] -= nb_objets + return etat_jeu + else: + raise ValueError("Mouvement invalide") + +# Fonction pour vérifier si l'état est final (tous les tas sont vides) +def est_etat_final(etat_jeu): + return all(nb_objets == 0 for nb_objets in etat_jeu) + +# Fonction heuristique pour estimer le coût restant +def heuristique(etat_jeu): + # Heuristique simple : somme des objets restants + return sum(etat_jeu) + +# Classe Noeud pour l'algorithme A* +class Noeud: + def __init__(self, etat, parent=None, g=0, h=0): + self.etat = etat + self.parent = parent + self.g = g # Coût pour atteindre ce nœud + self.h = h # Heuristique estimée + self.f = g + h # Fonction de coût totale + + def __lt__(self, autre): + return self.f < autre.f + +# Fonction pour reconstruire le chemin optimal +def reconstruire_chemin(noeud_final): + chemin = [] + noeud_actuel = noeud_final + while noeud_actuel: + chemin.append(noeud_actuel.etat) + noeud_actuel = noeud_actuel.parent + return chemin[::-1] # Inverser le chemin pour obtenir du départ à l'arrivée + +# Algorithme A* pour résoudre le jeu de Nim +def algorithme_a_star(etat_initial): + # Initialisation de la file de priorité + open_list = [] + heapq.heappush(open_list, Noeud(etat_initial, h=heuristique(etat_initial))) + + # Ensemble des états déjà visités + visited = set() + + while open_list: + noeud_courant = heapq.heappop(open_list) + + if est_etat_final(noeud_courant.etat): + return reconstruire_chemin(noeud_courant) + + visited.add(tuple(noeud_courant.etat)) + + for mouvement in generer_mouvements(noeud_courant.etat): + if tuple(mouvement) not in visited: + noeud_successeur = Noeud(mouvement, parent=noeud_courant, + g=noeud_courant.g + 1, + h=heuristique(mouvement)) + heapq.heappush(open_list, noeud_successeur) + +# Sauvegarder la partie dans un fichier json + +def sauvegarder_partie(historique, resultat): + partie = { + "date": str(datetime.datetime.now()), + "historique": historique, + "resultat": resultat + } + + # Chargement du fichier JSON existant ou création s'il n'existe pas + try: + with open("historique_nim.json", "r") as fichier: + sauvegardes = json.load(fichier) + except FileNotFoundError: + sauvegardes = [] + + # Ajouter la nouvelle partie à l'historique + sauvegardes.append(partie) + + # Sauvegarde dans le fichier + with open("historique_nim.json", "w") as fichier: + json.dump(sauvegardes, fichier, indent=4) + +# Boucle principale pour jouer une partie +def jeu_de_nim(tas_initial, mode="normal"): + etat_jeu = tas_initial[:] + joueur = 1 # 1 pour joueur humain, 2 pour ordinateur + historique = [f"Tas initiaux: {etat_jeu}"] + + while not est_etat_final(etat_jeu): + if joueur == 1: + print("Tour du joueur :") + afficher_etat(etat_jeu) + tas_choisi = int(input("Choisissez un tas (numéro): ")) - 1 + nb_objets = int(input(f"Combien d'objets voulez-vous prendre dans le tas {tas_choisi + 1}? ")) + etat_jeu = appliquer_mouvement(etat_jeu, tas_choisi, nb_objets) + historique.append(f"Joueur a pris {nb_objets} objets du tas {tas_choisi + 1}") + else: + print("Tour de l'ordinateur :") + meilleur_chemin = algorithme_a_star(etat_jeu) + prochain_etat = meilleur_chemin[1] # Choisir le premier mouvement du chemin + for i in range(len(etat_jeu)): + if etat_jeu[i] != prochain_etat[i]: + nb_objets = etat_jeu[i] - prochain_etat[i] + etat_jeu = prochain_etat + historique.append(f"Ordinateur a pris {nb_objets} objets du tas {i + 1}") + break + + joueur = 2 if joueur == 1 else 1 + + # Condition de victoire/perte + if mode == "normal": + if joueur == 2: + print("Félicitations, vous avez gagné!") + resultat = "Joueur a gagné" + else: + print("Dommage, l'ordinateur a gagné.") + resultat = "Ordinateur a gagné" + elif mode == "misere": + if joueur == 2: + print("L'ordinateur a perdu (version misère)!") + resultat = "Ordinateur a perdu (misère)" + else: + print("Vous avez perdu (version misère).") + resultat = "Joueur a perdu (misère)" + + # Sauvegarder la partie + sauvegarder_partie(historique, resultat) + +# Lancement du jeu +if __name__ == "__main__": + tas_initial = [3, 4, 5] # Exemple de configuration initiale + mode_de_jeu = input("Choisissez le mode de jeu (normal/misere) : ").strip().lower() + if mode_de_jeu not in ["normal", "misere"]: + mode_de_jeu = "normal" + + jeu_de_nim(tas_initial, mode_de_jeu) \ No newline at end of file