rendu final
This commit is contained in:
commit
affd1b3ae0
24
TPIA/jeu_nim/exo1.py
Normal file
24
TPIA/jeu_nim/exo1.py
Normal file
@ -0,0 +1,24 @@
|
||||
def afficher_etat(etat_jeu):
|
||||
print("État actuel du jeu:")
|
||||
for i, tas in enumerate(etat_jeu):
|
||||
print(f"Tas {i+1}: {tas} objets")
|
||||
|
||||
#etat_jeu = [3, 4, 5]#
|
||||
#afficher_etat(etat_jeu)#
|
||||
|
||||
|
||||
|
||||
# Test de la fonction avec plusieurs configurations
|
||||
configurations = [
|
||||
[3, 4, 5],
|
||||
[1, 0, 2],
|
||||
[0, 0, 1],
|
||||
[4, 4, 4],
|
||||
[5, 1, 0, 2]
|
||||
]
|
||||
|
||||
for etat in configurations:
|
||||
afficher_etat(etat)
|
||||
print('-' * 20) # Pour séparer les affichages entre les tests
|
||||
|
||||
|
0
TPIA/jeu_nim/exo10.py
Normal file
0
TPIA/jeu_nim/exo10.py
Normal file
52
TPIA/jeu_nim/exo2.py
Normal file
52
TPIA/jeu_nim/exo2.py
Normal file
@ -0,0 +1,52 @@
|
||||
|
||||
def generer_mouvements(etat_jeu):
|
||||
mouvements = [] # Liste pour stocker les nouveaux états possibles
|
||||
|
||||
for i, tas in enumerate(etat_jeu):
|
||||
# Vérifier si le tas a au moins un objet
|
||||
if tas > 0:
|
||||
# Retirer 1 à tas objets, générer un nouvel état
|
||||
for nb_objets in range(1, tas + 1):
|
||||
nouvel_etat = etat_jeu.copy() # Faire une copie de l'état actuel
|
||||
nouvel_etat[i] -= nb_objets # Retirer des objets de ce tas
|
||||
mouvements.append(nouvel_etat) # Ajouter le nouvel état à la liste
|
||||
|
||||
return mouvements
|
||||
|
||||
etat_jeu = [3, 4, 5]
|
||||
mouvements_possibles = generer_mouvements(etat_jeu)
|
||||
|
||||
for mouvement in mouvements_possibles:
|
||||
print(mouvement)
|
||||
|
||||
def afficher_mouvements(mouvements):
|
||||
print("Mouvements possibles :")
|
||||
for mouvement in mouvements:
|
||||
print(mouvement)
|
||||
|
||||
# Vérification avec plusieurs configurations d'état de jeu
|
||||
etat_jeu1 = [3, 4, 5]
|
||||
etat_jeu2 = [1, 0, 2]
|
||||
etat_jeu3 = [0, 0, 1]
|
||||
etat_jeu4 = [2, 2, 2]
|
||||
|
||||
print("Test avec l'état [3, 4, 5] :")
|
||||
mouvements1 = generer_mouvements(etat_jeu1)
|
||||
afficher_mouvements(mouvements1)
|
||||
print('-' * 30)
|
||||
|
||||
print("Test avec l'état [1, 0, 2] :")
|
||||
mouvements2 = generer_mouvements(etat_jeu2)
|
||||
afficher_mouvements(mouvements2)
|
||||
print('-' * 30)
|
||||
|
||||
print("Test avec l'état [0, 0, 1] :")
|
||||
mouvements3 = generer_mouvements(etat_jeu3)
|
||||
afficher_mouvements(mouvements3)
|
||||
print('-' * 30)
|
||||
|
||||
print("Test avec l'état [2, 2, 2] :")
|
||||
mouvements4 = generer_mouvements(etat_jeu4)
|
||||
afficher_mouvements(mouvements4)
|
||||
print('-' * 30)
|
||||
|
23
TPIA/jeu_nim/exo3.py
Normal file
23
TPIA/jeu_nim/exo3.py
Normal file
@ -0,0 +1,23 @@
|
||||
def appliquer_mouvement(etat_jeu, tas_index, nb_objets):
|
||||
# Créer une copie de l'état du jeu pour ne pas modifier l'état original
|
||||
nouvel_etat = etat_jeu.copy()
|
||||
|
||||
# Retirer nb_objets du tas à l'index tas_index
|
||||
if 0 <= tas_index < len(nouvel_etat) and nouvel_etat[tas_index] >= nb_objets:
|
||||
nouvel_etat[tas_index] -= nb_objets
|
||||
else:
|
||||
raise ValueError("Mouvement invalide : index du tas ou nombre d'objets incorrect")
|
||||
|
||||
return nouvel_etat
|
||||
|
||||
# Test 1 : Retirer 3 objets du tas 0 (le premier tas)
|
||||
etat1 = appliquer_mouvement([3, 4, 5], 0, 3)
|
||||
print("Test 1 :", etat1) # [0, 4, 5]
|
||||
|
||||
# Test 2 : Retirer 1 objet du tas 2 (le troisième tas)
|
||||
etat2 = appliquer_mouvement([1, 0, 2], 2, 1)
|
||||
print("Test 2 :", etat2) # [1, 0, 1]
|
||||
|
||||
# Test 3 : Retirer 1 objet du tas 1 (le deuxième tas)
|
||||
etat3 = appliquer_mouvement([2, 2, 2], 1, 1)
|
||||
print("Test 3 :", etat3) # [2, 1, 2]
|
17
TPIA/jeu_nim/exo4.py
Normal file
17
TPIA/jeu_nim/exo4.py
Normal file
@ -0,0 +1,17 @@
|
||||
def heuristique(etat_jeu):
|
||||
# Retourner le nombre total d'objets restants dans tous les tas
|
||||
return sum(etat_jeu)
|
||||
|
||||
# Test avec différents états de jeu
|
||||
etat_jeu1 = [3, 4, 5] # Total de 12 objets
|
||||
etat_jeu2 = [1, 0, 2] # Total de 3 objets
|
||||
etat_jeu3 = [0, 0, 1] # Total de 1 objet
|
||||
etat_jeu4 = [0, 0, 0] # Aucun objet restant, donc état final
|
||||
|
||||
print("Heuristique pour [3, 4, 5] :", heuristique(etat_jeu1)) # 12
|
||||
print("Heuristique pour [1, 0, 2] :", heuristique(etat_jeu2)) # 3
|
||||
print("Heuristique pour [0, 0, 1] :", heuristique(etat_jeu3)) # 1
|
||||
print("Heuristique pour [0, 0, 0] :", heuristique(etat_jeu4)) # 0
|
||||
|
||||
|
||||
etat_jeu = [3, 2, 2] # Un total de 7 objets
|
10
TPIA/jeu_nim/exo5.py
Normal file
10
TPIA/jeu_nim/exo5.py
Normal file
@ -0,0 +1,10 @@
|
||||
def est_etat_final(etat_jeu):
|
||||
# Un état est final si tous les tas sont vides (c'est-à-dire que tous les éléments de la liste sont égaux à 0)
|
||||
return all(tas == 0 for tas in etat_jeu)
|
||||
|
||||
# Exemple d'état final et non-final
|
||||
etat_jeu1 = [0, 0, 0] # Tous les tas sont vides, donc état final
|
||||
etat_jeu2 = [1, 0, 2] # Il reste encore des objets, donc pas un état final
|
||||
|
||||
print("L'état [0, 0, 0] est-il un état final ?", est_etat_final(etat_jeu1)) # True
|
||||
print("L'état [1, 0, 2] est-il un état final ?", est_etat_final(etat_jeu2)) # False
|
66
TPIA/jeu_nim/exo6.py
Normal file
66
TPIA/jeu_nim/exo6.py
Normal file
@ -0,0 +1,66 @@
|
||||
def cout_mouvement(etat_actuel, nouvel_etat):
|
||||
# Chaque mouvement a un coût constant de 1
|
||||
return 1
|
||||
|
||||
etat_jeu1 = [3, 4, 5] # État initial
|
||||
etat_jeu2 = [3, 3, 5] # Après avoir retiré 1 objet du deuxième tas
|
||||
|
||||
# Le coût de passer de l'état [3, 4, 5] à l'état [3, 3, 5]
|
||||
print("Coût du mouvement :", cout_mouvement(etat_jeu1, etat_jeu2)) # 1
|
||||
|
||||
import heapq
|
||||
|
||||
def algorithme_a_star(etat_initial):
|
||||
# File de priorité (tas) pour les nœuds à explorer
|
||||
file_priorite = []
|
||||
|
||||
# Ajouter l'état initial dans la file de priorité (f(n), g(n), état)
|
||||
heapq.heappush(file_priorite, (0 + heuristique(etat_initial), 0, etat_initial))
|
||||
|
||||
# Dictionnaire pour stocker le coût minimal pour atteindre chaque état
|
||||
cout_minimal = {tuple(etat_initial): 0}
|
||||
|
||||
# Dictionnaire pour reconstruire le chemin
|
||||
predecesseurs = {tuple(etat_initial): None}
|
||||
|
||||
while file_priorite:
|
||||
# Extraire l'état avec le plus faible coût estimé f(n)
|
||||
_, cout_actuel, etat_actuel = heapq.heappop(file_priorite)
|
||||
|
||||
# Vérifier si l'état actuel est l'état final
|
||||
if est_etat_final(etat_actuel):
|
||||
# Reconstruire le chemin optimal
|
||||
chemin = []
|
||||
while etat_actuel is not None:
|
||||
chemin.append(etat_actuel)
|
||||
etat_actuel = predecesseurs[tuple(etat_actuel)]
|
||||
chemin.reverse() # On inverse le chemin pour l'avoir dans l'ordre
|
||||
return chemin
|
||||
|
||||
# Générer tous les mouvements possibles à partir de l'état actuel
|
||||
mouvements_possibles = generer_mouvements(etat_actuel)
|
||||
|
||||
for nouvel_etat in mouvements_possibles:
|
||||
# Calculer le coût du mouvement (toujours 1 dans notre cas)
|
||||
cout_mouvement_actuel = cout_actuel + cout_mouvement(etat_actuel, nouvel_etat)
|
||||
|
||||
# Si le nouvel état est rencontré avec un coût inférieur à celui déjà connu
|
||||
if tuple(nouvel_etat) not in cout_minimal or cout_mouvement_actuel < cout_minimal[tuple(nouvel_etat)]:
|
||||
cout_minimal[tuple(nouvel_etat)] = cout_mouvement_actuel
|
||||
predecesseurs[tuple(nouvel_etat)] = etat_actuel
|
||||
# Calculer f(n) = g(n) + h(n)
|
||||
f_n = cout_mouvement_actuel + heuristique(nouvel_etat)
|
||||
# Ajouter le nouvel état dans la file de priorité
|
||||
heapq.heappush(file_priorite, (f_n, cout_mouvement_actuel, nouvel_etat))
|
||||
|
||||
# Si aucun chemin n'a été trouvé (ce qui ne devrait pas arriver dans le jeu de Nim)
|
||||
return None
|
||||
|
||||
etat_initial = [3, 4, 5] # Exemple d'état initial
|
||||
|
||||
# Appel de l'algorithme A* pour trouver le chemin optimal
|
||||
chemin_optimal = algorithme_a_star(etat_initial)
|
||||
|
||||
# Affichage du chemin
|
||||
for etat in chemin_optimal:
|
||||
print(etat)
|
72
TPIA/jeu_nim/exo7.py
Normal file
72
TPIA/jeu_nim/exo7.py
Normal file
@ -0,0 +1,72 @@
|
||||
import heapq
|
||||
|
||||
def algorithme_a_star(etat_initial):
|
||||
# File de priorité (tas) pour les nœuds à explorer
|
||||
file_priorite = []
|
||||
|
||||
# Ajouter l'état initial dans la file de priorité (f(n), g(n), état)
|
||||
heapq.heappush(file_priorite, (0 + heuristique(etat_initial), 0, etat_initial))
|
||||
|
||||
# Dictionnaire pour stocker le coût minimal pour atteindre chaque état
|
||||
cout_minimal = {tuple(etat_initial): 0}
|
||||
|
||||
# Dictionnaire pour reconstruire le chemin
|
||||
predecesseurs = {tuple(etat_initial): None}
|
||||
|
||||
# Ensemble pour stocker les états déjà visités
|
||||
etats_visites = set()
|
||||
|
||||
while file_priorite:
|
||||
# Extraire l'état avec le plus faible coût estimé f(n)
|
||||
_, cout_actuel, etat_actuel = heapq.heappop(file_priorite)
|
||||
|
||||
# Convertir l'état en tuple pour le stockage dans les ensembles
|
||||
etat_tuple = tuple(etat_actuel)
|
||||
|
||||
# Si l'état a déjà été visité, on l'ignore
|
||||
if etat_tuple in etats_visites:
|
||||
continue
|
||||
|
||||
# Marquer l'état comme visité
|
||||
etats_visites.add(etat_tuple)
|
||||
|
||||
# Vérifier si l'état actuel est l'état final
|
||||
if est_etat_final(etat_actuel):
|
||||
# Reconstruire le chemin optimal
|
||||
chemin = []
|
||||
while etat_actuel is not None:
|
||||
chemin.append(etat_actuel)
|
||||
etat_actuel = predecesseurs[tuple(etat_actuel)]
|
||||
chemin.reverse() # On inverse le chemin pour l'avoir dans l'ordre
|
||||
return chemin
|
||||
|
||||
# Générer tous les mouvements possibles à partir de l'état actuel
|
||||
mouvements_possibles = generer_mouvements(etat_actuel)
|
||||
|
||||
for nouvel_etat in mouvements_possibles:
|
||||
# Calculer le coût du mouvement (toujours 1 dans notre cas)
|
||||
cout_mouvement_actuel = cout_actuel + cout_mouvement(etat_actuel, nouvel_etat)
|
||||
|
||||
# Si le nouvel état est rencontré avec un coût inférieur à celui déjà connu
|
||||
etat_tuple_nouveau = tuple(nouvel_etat)
|
||||
|
||||
# Vérifier si l'état a déjà été visité ou si le coût est inférieur
|
||||
if etat_tuple_nouveau not in etats_visites or cout_mouvement_actuel < cout_minimal.get(etat_tuple_nouveau, float('inf')):
|
||||
cout_minimal[etat_tuple_nouveau] = cout_mouvement_actuel
|
||||
predecesseurs[etat_tuple_nouveau] = etat_actuel
|
||||
# Calculer f(n) = g(n) + h(n)
|
||||
f_n = cout_mouvement_actuel + heuristique(nouvel_etat)
|
||||
# Ajouter le nouvel état dans la file de priorité
|
||||
heapq.heappush(file_priorite, (f_n, cout_mouvement_actuel, nouvel_etat))
|
||||
|
||||
# Si aucun chemin n'a été trouvé (ce qui ne devrait pas arriver dans le jeu de Nim)
|
||||
return None
|
||||
|
||||
etat_initial = [3, 4, 5] # Exemple d'état initial
|
||||
|
||||
# Appel de l'algorithme A* pour trouver le chemin optimal
|
||||
chemin_optimal = algorithme_a_star(etat_initial)
|
||||
|
||||
# Affichage du chemin
|
||||
for etat in chemin_optimal:
|
||||
print(etat)
|
72
TPIA/jeu_nim/exo8.py
Normal file
72
TPIA/jeu_nim/exo8.py
Normal file
@ -0,0 +1,72 @@
|
||||
import heapq
|
||||
|
||||
def algorithme_a_star(etat_initial):
|
||||
# File de priorité (tas) pour les nœuds à explorer
|
||||
file_priorite = []
|
||||
|
||||
# Ajouter l'état initial dans la file de priorité (f(n), g(n), état)
|
||||
heapq.heappush(file_priorite, (0 + heuristique(etat_initial), 0, etat_initial))
|
||||
|
||||
# Dictionnaire pour stocker le coût minimal pour atteindre chaque état
|
||||
cout_minimal = {tuple(etat_initial): 0}
|
||||
|
||||
# Dictionnaire pour stocker le parent de chaque état (reconstruction du chemin)
|
||||
predecesseurs = {tuple(etat_initial): None}
|
||||
|
||||
# Ensemble pour stocker les états déjà visités
|
||||
etats_visites = set()
|
||||
|
||||
while file_priorite:
|
||||
# Extraire l'état avec le plus faible coût estimé f(n)
|
||||
_, cout_actuel, etat_actuel = heapq.heappop(file_priorite)
|
||||
|
||||
# Convertir l'état en tuple pour le stockage dans les ensembles
|
||||
etat_tuple = tuple(etat_actuel)
|
||||
|
||||
# Si l'état a déjà été visité, on l'ignore
|
||||
if etat_tuple in etats_visites:
|
||||
continue
|
||||
|
||||
# Marquer l'état comme visité
|
||||
etats_visites.add(etat_tuple)
|
||||
|
||||
# Vérifier si l'état actuel est l'état final
|
||||
if est_etat_final(etat_actuel):
|
||||
# Reconstruire le chemin optimal
|
||||
chemin = []
|
||||
while etat_actuel is not None:
|
||||
chemin.append(etat_actuel)
|
||||
etat_actuel = predecesseurs[tuple(etat_actuel)]
|
||||
chemin.reverse() # On inverse le chemin pour l'avoir dans l'ordre
|
||||
return chemin
|
||||
|
||||
# Générer tous les mouvements possibles à partir de l'état actuel
|
||||
mouvements_possibles = generer_mouvements(etat_actuel)
|
||||
|
||||
for nouvel_etat in mouvements_possibles:
|
||||
# Calculer le coût du mouvement (toujours 1 dans notre cas)
|
||||
cout_mouvement_actuel = cout_actuel + cout_mouvement(etat_actuel, nouvel_etat)
|
||||
|
||||
# Si le nouvel état est rencontré avec un coût inférieur à celui déjà connu
|
||||
etat_tuple_nouveau = tuple(nouvel_etat)
|
||||
|
||||
# Vérifier si l'état a déjà été visité ou si le coût est inférieur
|
||||
if etat_tuple_nouveau not in etats_visites or cout_mouvement_actuel < cout_minimal.get(etat_tuple_nouveau, float('inf')):
|
||||
cout_minimal[etat_tuple_nouveau] = cout_mouvement_actuel
|
||||
predecesseurs[etat_tuple_nouveau] = etat_actuel # Stocker le parent
|
||||
# Calculer f(n) = g(n) + h(n)
|
||||
f_n = cout_mouvement_actuel + heuristique(nouvel_etat)
|
||||
# Ajouter le nouvel état dans la file de priorité
|
||||
heapq.heappush(file_priorite, (f_n, cout_mouvement_actuel, nouvel_etat))
|
||||
|
||||
# Si aucun chemin n'a été trouvé (ce qui ne devrait pas arriver dans le jeu de Nim)
|
||||
return None
|
||||
|
||||
etat_initial = [3, 4, 5] # Exemple d'état initial
|
||||
|
||||
# Appel de l'algorithme A* pour trouver le chemin optimal
|
||||
chemin_optimal = algorithme_a_star(etat_initial)
|
||||
|
||||
# Affichage du chemin
|
||||
for etat in chemin_optimal:
|
||||
print(etat)
|
44
TPIA/jeu_nim/exo8b.py
Normal file
44
TPIA/jeu_nim/exo8b.py
Normal file
@ -0,0 +1,44 @@
|
||||
def reconstruire_chemin(predecesseurs, etat_final):
|
||||
"""
|
||||
Reconstruit le chemin à partir de l'état final en suivant les parents jusqu'à l'état initial.
|
||||
|
||||
Args:
|
||||
predecesseurs (dict): Dictionnaire où chaque clé est un état et la valeur est le parent de cet état.
|
||||
etat_final (list): L'état final à partir duquel remonter pour trouver le chemin.
|
||||
|
||||
Returns:
|
||||
list: Le chemin depuis l'état initial jusqu'à l'état final, incluant tous les états intermédiaires.
|
||||
"""
|
||||
chemin = []
|
||||
etat_actuel = tuple(etat_final) # Convertir en tuple pour correspondre aux clés dans 'predecesseurs'
|
||||
|
||||
# Remonter à travers les parents jusqu'à l'état initial
|
||||
while etat_actuel is not None:
|
||||
chemin.append(list(etat_actuel)) # Ajouter l'état actuel au chemin (reconverti en liste pour l'affichage)
|
||||
etat_actuel = predecesseurs[etat_actuel] # Suivre le parent de l'état actuel
|
||||
|
||||
# Inverser le chemin pour qu'il soit dans l'ordre de l'état initial à l'état final
|
||||
chemin.reverse()
|
||||
|
||||
return chemin
|
||||
|
||||
etat_initial = [3, 4, 5] # Exemple d'état initial
|
||||
etat_final = [0, 0, 0] # Exemple d'état final (victoire)
|
||||
|
||||
# Dictionnaire des parents (simulé pour cet exemple)
|
||||
predecesseurs = {
|
||||
(3, 4, 5): None, # État initial sans parent
|
||||
(2, 4, 5): (3, 4, 5),
|
||||
(2, 3, 5): (2, 4, 5),
|
||||
(2, 3, 4): (2, 3, 5),
|
||||
(0, 3, 4): (2, 3, 4),
|
||||
(0, 0, 4): (0, 3, 4),
|
||||
(0, 0, 0): (0, 0, 4) # État final
|
||||
}
|
||||
|
||||
# Reconstruction du chemin
|
||||
chemin = reconstruire_chemin(predecesseurs, etat_final)
|
||||
|
||||
# Affichage du chemin
|
||||
for etat in chemin:
|
||||
print(etat)
|
46
TPIA/jeu_nim/exo9.py
Normal file
46
TPIA/jeu_nim/exo9.py
Normal file
@ -0,0 +1,46 @@
|
||||
def afficher_etat(etat_jeu):
|
||||
"""Affiche l'état actuel du jeu."""
|
||||
print("État actuel du jeu :")
|
||||
for i, tas in enumerate(etat_jeu):
|
||||
print(f"Tas {i + 1}: {tas} objets")
|
||||
|
||||
def appliquer_mouvement(etat_jeu, tas_index, nb_objets):
|
||||
"""Applique un mouvement et modifie l'état du jeu."""
|
||||
etat_jeu[tas_index] -= nb_objets
|
||||
|
||||
def mouvement_valide(etat_jeu, tas_index, nb_objets):
|
||||
"""Vérifie si un mouvement est valide."""
|
||||
return 0 <= tas_index < len(etat_jeu) and 1 <= nb_objets <= etat_jeu[tas_index]
|
||||
|
||||
def est_etat_final(etat_jeu):
|
||||
"""Vérifie si tous les tas sont vides."""
|
||||
return all(tas == 0 for tas in etat_jeu)
|
||||
|
||||
def boucle_de_jeu():
|
||||
"""Boucle de jeu pour permettre à l'utilisateur de jouer."""
|
||||
# Initialisation de l'état du jeu (par exemple, trois tas avec 3, 4 et 5 objets)
|
||||
etat_jeu = [3, 4, 5]
|
||||
|
||||
# Boucle principale du jeu
|
||||
while not est_etat_final(etat_jeu):
|
||||
# Afficher l'état actuel du jeu
|
||||
afficher_etat(etat_jeu)
|
||||
|
||||
# Demander à l'utilisateur quel tas et combien d'objets retirer
|
||||
try:
|
||||
tas_index = int(input("Choisissez un tas (1, 2, 3...): ")) - 1
|
||||
nb_objets = int(input(f"Combien d'objets voulez-vous retirer du tas {tas_index + 1}? "))
|
||||
|
||||
# Vérifier si le mouvement est valide
|
||||
if mouvement_valide(etat_jeu, tas_index, nb_objets):
|
||||
appliquer_mouvement(etat_jeu, tas_index, nb_objets)
|
||||
else:
|
||||
print("Mouvement invalide ! Essayez à nouveau.")
|
||||
except ValueError:
|
||||
print("Entrée invalide. Veuillez entrer des nombres entiers.")
|
||||
|
||||
# Fin du jeu : si tous les tas sont vides
|
||||
print("Félicitations ! Vous avez gagné !")
|
||||
|
||||
# Lancer la boucle de jeu
|
||||
boucle_de_jeu()
|
Loading…
Reference in New Issue
Block a user