Les dictionnaires Python pour gérer un escape game
Durée : 1 heure Prérequis : Connaître les listes Python Objectif : Découvrir les dictionnaires et comprendre pourquoi ils sont essentiels pour gérer les objets et états d’un jeu
1. Rappel : Les listes, ce que vous connaissez déjà (10 min)
Structure des listes
Une liste est une collection ordonnée d’éléments, accessibles par leur position (index).
# Liste de prénomsprenoms=["Alice","Bob","Charlie"]# Accès par index (position)print(prenoms[0])# Affiche : Aliceprint(prenoms[1])# Affiche : Bobprint(prenoms[2])# Affiche : Charlie
Utiliser les listes pour un jeu : première tentative
Imaginons qu’on veuille gérer un objet de notre escape game avec une liste :
# Un objet "clé" représenté par une listecle=["clé dorée",150,200,False,"Une petite clé qui brille"]# [0] nom [1] x [2] y [3] ramassée [4] description# Accès aux informationsprint(cle[0])# nomprint(cle[1])# position xprint(cle[3])# est-elle ramassée ?
Le problème avec les listes
❌ Difficile à lire : Que représente cle[3] ? Il faut se souvenir de l’ordre
❌ Difficile à maintenir : Si on ajoute une propriété, tous les indices changent
❌ Erreurs faciles : Confondre l’ordre des éléments
❌ Code cryptique : if objet[3] == False: ne dit rien sur ce qu’on vérifie
Exercice mental : Si on a 10 objets différents avec des propriétés différentes, comment s’en sortir avec des listes ?
2. Introduction aux dictionnaires (15 min)
Qu’est-ce qu’un dictionnaire ?
Un dictionnaire est une collection d’éléments accessibles par leur nom (clé) plutôt que par leur position.
Analogie : Un dictionnaire papier
Dans un dictionnaire français, on cherche un mot (la clé) pour obtenir sa définition (la valeur)
On ne dit pas “donne-moi le 1547ème mot”, mais “donne-moi la définition de ’escape'”
Syntaxe de base
# Création d'un dictionnairepersonne={"nom":"Alice","age":25,"ville":"Paris"}# Accès par clé (beaucoup plus clair !)print(personne["nom"])# Affiche : Aliceprint(personne["age"])# Affiche : 25print(personne["ville"])# Affiche : Paris
Les clés sont généralement des chaînes de caractères (entre guillemets)
Les valeurs peuvent être de n’importe quel type : nombres, chaînes, booléens, listes, ou même d’autres dictionnaires !
Comparaison liste vs dictionnaire
# AVEC UNE LISTE (difficile à lire)cle_liste=["clé dorée",150,200,False,"Une petite clé qui brille"]nom=cle_liste[0]est_ramassee=cle_liste[3]# AVEC UN DICTIONNAIRE (clair et explicite)cle_dict={"nom":"clé dorée","x":150,"y":200,"ramassee":False,"description":"Une petite clé qui brille"}nom=cle_dict["nom"]est_ramassee=cle_dict["ramassee"]
joueur["vie"]=80# La vie passe à 80joueur["niveau"]=2# Le niveau passe à 2
Ajouter une nouvelle paire clé-valeur
joueur["score"]=1500# Ajoute une nouvelle clé "score"
Vérifier si une clé existe
if"vie"injoueur:print("Le joueur a des points de vie")if"magie"injoueur:print("Le joueur a de la magie")else:print("Pas de magie")# Ceci sera affiché
Supprimer une paire clé-valeur
deljoueur["score"]# Supprime la clé "score"
Obtenir une valeur avec une valeur par défaut
# Si la clé n'existe pas, retourne une valeur par défautmagie=joueur.get("magie",0)# Retourne 0 si "magie" n'existe pas
3. Les dictionnaires pour l’escape game (20 min)
3.1. Représenter un objet du jeu
Au lieu d’utiliser des listes compliquées, utilisons des dictionnaires pour chaque objet :
porte={"nom":"porte","x":300,"y":200,"largeur":150,"hauteur":300,"verrouille":True,"description":"Une lourde porte en bois","message_verrouille":"La porte est fermée à clé","message_ouvert":"Vous ouvrez la porte et sortez. Victoire !"}cle={"nom":"clé","x":100,"y":400,"largeur":30,"hauteur":15,"ramassee":False,"description":"Une petite clé dorée","dans_inventaire":False}tableau={"nom":"tableau","x":450,"y":150,"largeur":200,"hauteur":150,"examine":False,"description":"Un tableau représentant un paysage","description_detaillee":"En examinant de plus près, vous voyez un code : 1234"}
Avantages :
✅ Chaque objet peut avoir des propriétés différentes
✅ Le code est auto-documenté (on comprend ce que fait objet["verrouille"])
✅ Facile d’ajouter de nouvelles propriétés
✅ Pas de confusion sur l’ordre des éléments
3.2. Gérer une collection d’objets
On peut mettre tous les objets dans une liste :
objets=[{"nom":"porte","x":300,"y":200,"largeur":150,"hauteur":300,"verrouille":True,"description":"Une lourde porte en bois"},{"nom":"clé","x":100,"y":400,"largeur":30,"hauteur":15,"ramassee":False,"description":"Une petite clé dorée"},{"nom":"coffre","x":550,"y":350,"largeur":100,"hauteur":80,"ouvert":False,"description":"Un vieux coffre poussiéreux"}]
3.3. Parcourir et utiliser les objets
# Afficher tous les objetsforobjetinobjets:print(f"Objet : {objet['nom']} à la position ({objet['x']}, {objet['y']})")# Trouver un objet par son nomdeftrouver_objet(nom_objet):forobjetinobjets:ifobjet["nom"]==nom_objet:returnobjetreturnNone# Utilisationporte=trouver_objet("porte")ifporte["verrouille"]:print("La porte est verrouillée")
3.4. Détecter un clic sur un objet
defverifier_clic_objet(x_souris,y_souris):"""Vérifie si le clic touche un objet"""forobjetinobjets:# Vérifier si le clic est dans les limites de l'objetif(objet["x"]<=x_souris<=objet["x"]+objet["largeur"]andobjet["y"]<=y_souris<=objet["y"]+objet["hauteur"]):returnobjetreturnNone# Dans la boucle d'événementsifevent.type==pygame.MOUSEBUTTONDOWN:x,y=event.posobjet_clique=verifier_clic_objet(x,y)ifobjet_clique:print(f"Vous avez cliqué sur : {objet_clique['nom']}")print(objet_clique["description"])
3.5. Gérer l’inventaire
# L'inventaire est une liste de dictionnairesinventaire=[]deframasser_objet(objet):"""Ajoute un objet à l'inventaire"""ifnotobjet.get("ramassee",False):objet["ramassee"]=Trueinventaire.append(objet)returnf"Vous ramassez : {objet['nom']}"else:return"Cet objet a déjà été ramassé"defafficher_inventaire():"""Affiche le contenu de l'inventaire"""iflen(inventaire)==0:print("Votre inventaire est vide")else:print("Inventaire :")forobjetininventaire:print(f" - {objet['nom']}")defobjet_dans_inventaire(nom_objet):"""Vérifie si un objet est dans l'inventaire"""forobjetininventaire:ifobjet["nom"]==nom_objet:returnTruereturnFalse
3.6. Gérer les interactions entre objets
defutiliser_cle_sur_porte():"""Tente d'ouvrir la porte avec la clé"""porte=trouver_objet("porte")ifobjet_dans_inventaire("clé"):ifporte["verrouille"]:porte["verrouille"]=Falsereturn"Vous utilisez la clé. La porte s'ouvre !"else:return"La porte est déjà ouverte"else:return"Vous n'avez pas de clé"defexaminer_objet(objet):"""Examine un objet en détail"""ifobjet["nom"]=="tableau"andnotobjet.get("examine",False):objet["examine"]=Truereturnobjet.get("description_detaillee",objet["description"])else:returnobjet["description"]
4. Exemple complet : Mini escape game avec dictionnaires (10 min)
Voici un exemple fonctionnel simplifié qui montre comment tout s’assemble :
importpygamepygame.init()screen=pygame.display.set_mode((800,600))clock=pygame.time.Clock()font=pygame.font.Font(None,28)# Définition des objets avec des dictionnairesobjets=[{"nom":"clé","x":100,"y":400,"largeur":40,"hauteur":20,"couleur":(255,215,0),# Doré"ramassee":False,"description":"Une clé dorée"},{"nom":"porte","x":650,"y":200,"largeur":100,"hauteur":200,"couleur":(139,69,19),# Marron"verrouille":True,"description":"Une porte en bois"}]# État du jeuinventaire=[]message="Trouvez la clé et ouvrez la porte !"victoire=Falserunning=Truewhilerunning:foreventinpygame.event.get():ifevent.type==pygame.QUIT:running=Falseifevent.type==pygame.MOUSEBUTTONDOWNandnotvictoire:x_souris,y_souris=event.pos# Vérifier les clics sur les objetsforobjetinobjets:if(objet["x"]<=x_souris<=objet["x"]+objet["largeur"]andobjet["y"]<=y_souris<=objet["y"]+objet["hauteur"]):# Clic sur la cléifobjet["nom"]=="clé"andnotobjet["ramassee"]:objet["ramassee"]=Trueinventaire.append(objet)message="Vous ramassez la clé !"# Clic sur la porteelifobjet["nom"]=="porte":# Vérifier si on a la cléa_la_cle=any(obj["nom"]=="clé"forobjininventaire)ifa_la_cleandobjet["verrouille"]:objet["verrouille"]=Falsemessage="Vous ouvrez la porte ! VICTOIRE !"victoire=Trueelifobjet["verrouille"]:message="La porte est verrouillée. Il faut une clé."else:message="La porte est déjà ouverte !"# Affichagescreen.fill((50,50,50))# Fond gris# Dessiner les objetsforobjetinobjets:# Ne pas dessiner la clé si elle est ramasséeifobjet["nom"]=="clé"andobjet["ramassee"]:continuepygame.draw.rect(screen,objet["couleur"],(objet["x"],objet["y"],objet["largeur"],objet["hauteur"]))# Afficher le messagetexte=font.render(message,True,(255,255,255))screen.blit(texte,(50,550))# Afficher l'inventaireinv_text="Inventaire : "+", ".join([obj["nom"]forobjininventaire])iflen(inventaire)==0:inv_text="Inventaire : vide"inv_surface=font.render(inv_text,True,(200,200,200))screen.blit(inv_surface,(50,20))pygame.display.flip()clock.tick(60)pygame.quit()
Ce que fait ce programme :
Définit une clé et une porte comme dictionnaires
Permet de cliquer sur la clé pour la ramasser
La clé disparaît et va dans l’inventaire
On peut cliquer sur la porte pour tenter de l’ouvrir
La porte s’ouvre seulement si on a la clé
5. Dictionnaires avancés pour le jeu (10 min)
5.1. Dictionnaires imbriqués
On peut mettre des dictionnaires dans des dictionnaires :
objet_complexe={"nom":"coffre","position":{"x":100,"y":200},"dimensions":{"largeur":80,"hauteur":60},"contenu":{"or":50,"gemmes":3,"objet_special":"amulette"},"ouvert":False}# Accès aux valeurs imbriquéesprint(objet_complexe["position"]["x"])# 100print(objet_complexe["contenu"]["or"])# 50
5.2. État global du jeu
Un dictionnaire peut représenter l’état complet du jeu :
etat_jeu={"niveau_actuel":1,"temps_ecoule":0,"enigmes_resolues":["enigme1","enigme3"],"inventaire":[],"score":1500,"indices_trouves":{"code_coffre":True,"message_secret":False},"pieces_visitees":["salon","cuisine"],"drapeaux":{"porte_ouverte":False,"alarme_declenchee":False,"a_parle_au_gardien":True}}# Vérifications facilesif"code_coffre"inetat_jeu["indices_trouves"]:print("Vous connaissez le code du coffre")ifetat_jeu["drapeaux"]["a_parle_au_gardien"]:print("Le gardien vous a donné un indice")
5.3. Actions et interactions
On peut même stocker des fonctions ou des messages dans les dictionnaires :
objets_interactifs=[{"nom":"levier","x":300,"y":250,"actif":False,"description_initial":"Un levier rouillé","description_active":"Le levier a été activé. Un passage secret s'ouvre.","action":"ouvrir_passage"},{"nom":"livre","x":150,"y":180,"lu":False,"description":"Un vieux grimoire","texte":"Les pages révèlent : 'Le code est 4-2-7-9'","action":"donner_indice"}]definteragir_avec_objet(objet):"""Gère l'interaction avec un objet selon son type d'action"""ifobjet["action"]=="ouvrir_passage":objet["actif"]=Truereturnobjet["description_active"]elifobjet["action"]=="donner_indice":ifnotobjet["lu"]:objet["lu"]=Truereturnobjet["texte"]else:return"Vous avez déjà lu ce livre"returnobjet["description"]
5.4. Système de quêtes
quetes=[{"id":"trouver_cle","titre":"Trouver la clé","description":"Cherchez la clé pour ouvrir la porte","terminee":False,"objectifs":{"cle_trouvee":False}},{"id":"resoudre_enigme","titre":"Résoudre l'énigme du tableau","description":"Déchiffrez le message caché dans le tableau","terminee":False,"objectifs":{"tableau_examine":False,"code_trouve":False}}]defverifier_quetes():"""Vérifie si les quêtes sont terminées"""forqueteinquetes:ifnotquete["terminee"]:# Vérifier si tous les objectifs sont remplistous_objectifs=all(quete["objectifs"].values())iftous_objectifs:quete["terminee"]=Truereturnf"Quête terminée : {quete['titre']}"returnNone
6. Comparaison finale et bonnes pratiques (5 min)
Pourquoi les dictionnaires sont parfaits pour les jeux
Critère
Listes
Dictionnaires
Lisibilité
❌ objet[3]
✅ objet["verrouille"]
Flexibilité
❌ Ordre fixe
✅ Propriétés variables
Maintenance
❌ Changer l’ordre casse tout
✅ Ajouter/retirer facilement
Clarté du code
❌ Besoin de commentaires
✅ Auto-documenté
Gestion d’objets complexes
❌ Très difficile
✅ Naturel
Bonnes pratiques avec les dictionnaires
✅ Utilisez des noms de clés descriptifs
# Bienjoueur={"points_de_vie":100,"niveau":5}# Moins bienjoueur={"pv":100,"niv":5}
✅ Soyez cohérents dans la structure
# Tous les objets ont les mêmes clés de baseobjet1={"nom":"...","x":0,"y":0,"description":"..."}objet2={"nom":"...","x":0,"y":0,"description":"..."}
✅ Utilisez .get() pour éviter les erreurs
# Risqué - erreur si la clé n'existe pasvie=joueur["vie"]# Sûr - retourne 100 par défautvie=joueur.get("vie",100)
✅ Documentez la structure de vos dictionnaires
# Structure d'un objet du jeu :# {# "nom": str, # Nom de l'objet# "x": int, # Position X# "y": int, # Position Y# "ramassable": bool, # Peut-on le ramasser ?# "description": str # Description affichée# }
Quand utiliser listes vs dictionnaires ?
Utilisez une liste quand :
L’ordre est important
Vous avez une série d’éléments similaires et simples
Exemple : scores = [100, 95, 87, 82]
Utilisez un dictionnaire quand :
Vous avez des propriétés nommées
Vous voulez accéder aux données par leur signification
Vous gérez des objets complexes
Exemple : joueur = {"nom": "Alice", "score": 100, "niveau": 3}
Récapitulatif
🎯 Les dictionnaires permettent d’accéder aux données par nom (clé) plutôt que par position
🎯 Syntaxe : {"clé": valeur, "clé2": valeur2}
🎯 Parfaits pour : Représenter des objets de jeu avec de multiples propriétés
Créez 3 dictionnaires représentant des objets pour votre escape game. Chaque objet doit avoir au minimum : nom, position (x, y), dimensions, et une description.
Exercice 2 : Fonction de recherche
Écrivez une fonction trouver_objet_par_nom(nom, liste_objets) qui cherche un objet dans une liste de dictionnaires et le retourne.
Exercice 3 : Système d’inventaire
Créez un système d’inventaire avec les fonctions :
ajouter_a_inventaire(objet)
retirer_de_inventaire(nom_objet)
afficher_inventaire()
Exercice 4 : Interaction complexe
Créez une fonction qui vérifie si le joueur peut ouvrir un coffre :
Le coffre doit être fermé
Le joueur doit avoir la clé dans son inventaire
Si oui, le coffre s’ouvre et donne son contenu
Pour aller plus loin dans votre projet
Maintenant que vous connaissez les dictionnaires, vous pouvez :
Créer un fichier JSON pour stocker vos objets (JSON est basé sur les dictionnaires)
Gérer plusieurs salles avec un dictionnaire de salles
Créer un système de sauvegarde en enregistrant l’état du jeu
Ajouter des dialogues avec des personnages (PNJ)
Implémenter des énigmes complexes avec plusieurs étapes