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énoms
prenoms = ["Alice", "Bob", "Charlie"]
# Accès par index (position)
print(prenoms[0]) # Affiche : Alice
print(prenoms[1]) # Affiche : Bob
print(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 liste
cle = ["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 informations
print(cle[0]) # nom
print(cle[1]) # position x
print(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 dictionnaire
personne = {
"nom": "Alice",
"age": 25,
"ville": "Paris"
}
# Accès par clé (beaucoup plus clair !)
print(personne["nom"]) # Affiche : Alice
print(personne["age"]) # Affiche : 25
print(personne["ville"]) # Affiche : Paris
Structure :
dictionnaire = {
"clé1": valeur1,
"clé2": valeur2,
"clé3": valeur3
}
- 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"]
Quelle version préférez-vous lire ?
Opérations de base sur les dictionnaires
Accéder à une valeur
joueur = {"nom": "Alice", "vie": 100, "niveau": 1}
print(joueur["nom"]) # Alice
print(joueur["vie"]) # 100
Modifier une valeur
joueur["vie"] = 80 # La vie passe à 80
joueur["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" in joueur:
print("Le joueur a des points de vie")
if "magie" in joueur:
print("Le joueur a de la magie")
else:
print("Pas de magie") # Ceci sera affiché
Supprimer une paire clé-valeur
del joueur["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éfaut
magie = 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 objets
for objet in objets:
print(f"Objet : {objet['nom']} à la position ({objet['x']}, {objet['y']})")
# Trouver un objet par son nom
def trouver_objet(nom_objet):
for objet in objets:
if objet["nom"] == nom_objet:
return objet
return None
# Utilisation
porte = trouver_objet("porte")
if porte["verrouille"]:
print("La porte est verrouillée")
3.4. Détecter un clic sur un objet
def verifier_clic_objet(x_souris, y_souris):
"""Vérifie si le clic touche un objet"""
for objet in objets:
# Vérifier si le clic est dans les limites de l'objet
if (objet["x"] <= x_souris <= objet["x"] + objet["largeur"] and
objet["y"] <= y_souris <= objet["y"] + objet["hauteur"]):
return objet
return None
# Dans la boucle d'événements
if event.type == pygame.MOUSEBUTTONDOWN:
x, y = event.pos
objet_clique = verifier_clic_objet(x, y)
if objet_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 dictionnaires
inventaire = []
def ramasser_objet(objet):
"""Ajoute un objet à l'inventaire"""
if not objet.get("ramassee", False):
objet["ramassee"] = True
inventaire.append(objet)
return f"Vous ramassez : {objet['nom']}"
else:
return "Cet objet a déjà été ramassé"
def afficher_inventaire():
"""Affiche le contenu de l'inventaire"""
if len(inventaire) == 0:
print("Votre inventaire est vide")
else:
print("Inventaire :")
for objet in inventaire:
print(f" - {objet['nom']}")
def objet_dans_inventaire(nom_objet):
"""Vérifie si un objet est dans l'inventaire"""
for objet in inventaire:
if objet["nom"] == nom_objet:
return True
return False
3.6. Gérer les interactions entre objets
def utiliser_cle_sur_porte():
"""Tente d'ouvrir la porte avec la clé"""
porte = trouver_objet("porte")
if objet_dans_inventaire("clé"):
if porte["verrouille"]:
porte["verrouille"] = False
return "Vous utilisez la clé. La porte s'ouvre !"
else:
return "La porte est déjà ouverte"
else:
return "Vous n'avez pas de clé"
def examiner_objet(objet):
"""Examine un objet en détail"""
if objet["nom"] == "tableau" and not objet.get("examine", False):
objet["examine"] = True
return objet.get("description_detaillee", objet["description"])
else:
return objet["description"]
4. Exemple complet : Mini escape game avec dictionnaires (10 min)
Voici un exemple fonctionnel simplifié qui montre comment tout s’assemble :
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
font = pygame.font.Font(None, 28)
# Définition des objets avec des dictionnaires
objets = [
{
"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 jeu
inventaire = []
message = "Trouvez la clé et ouvrez la porte !"
victoire = False
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN and not victoire:
x_souris, y_souris = event.pos
# Vérifier les clics sur les objets
for objet in objets:
if (objet["x"] <= x_souris <= objet["x"] + objet["largeur"] and
objet["y"] <= y_souris <= objet["y"] + objet["hauteur"]):
# Clic sur la clé
if objet["nom"] == "clé" and not objet["ramassee"]:
objet["ramassee"] = True
inventaire.append(objet)
message = "Vous ramassez la clé !"
# Clic sur la porte
elif objet["nom"] == "porte":
# Vérifier si on a la clé
a_la_cle = any(obj["nom"] == "clé" for obj in inventaire)
if a_la_cle and objet["verrouille"]:
objet["verrouille"] = False
message = "Vous ouvrez la porte ! VICTOIRE !"
victoire = True
elif objet["verrouille"]:
message = "La porte est verrouillée. Il faut une clé."
else:
message = "La porte est déjà ouverte !"
# Affichage
screen.fill((50, 50, 50)) # Fond gris
# Dessiner les objets
for objet in objets:
# Ne pas dessiner la clé si elle est ramassée
if objet["nom"] == "clé" and objet["ramassee"]:
continue
pygame.draw.rect(screen, objet["couleur"],
(objet["x"], objet["y"], objet["largeur"], objet["hauteur"]))
# Afficher le message
texte = font.render(message, True, (255, 255, 255))
screen.blit(texte, (50, 550))
# Afficher l'inventaire
inv_text = "Inventaire : " + ", ".join([obj["nom"] for obj in inventaire])
if len(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ées
print(objet_complexe["position"]["x"]) # 100
print(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 faciles
if "code_coffre" in etat_jeu["indices_trouves"]:
print("Vous connaissez le code du coffre")
if etat_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"
}
]
def interagir_avec_objet(objet):
"""Gère l'interaction avec un objet selon son type d'action"""
if objet["action"] == "ouvrir_passage":
objet["actif"] = True
return objet["description_active"]
elif objet["action"] == "donner_indice":
if not objet["lu"]:
objet["lu"] = True
return objet["texte"]
else:
return "Vous avez déjà lu ce livre"
return objet["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
}
}
]
def verifier_quetes():
"""Vérifie si les quêtes sont terminées"""
for quete in quetes:
if not quete["terminee"]:
# Vérifier si tous les objectifs sont remplis
tous_objectifs = all(quete["objectifs"].values())
if tous_objectifs:
quete["terminee"] = True
return f"Quête terminée : {quete['titre']}"
return None
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
# Bien
joueur = {"points_de_vie": 100, "niveau": 5}
# Moins bien
joueur = {"pv": 100, "niv": 5}
✅ Soyez cohérents dans la structure
# Tous les objets ont les mêmes clés de base
objet1 = {"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 pas
vie = joueur["vie"]
# Sûr - retourne 100 par défaut
vie = 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
🎯 Avantages : Code lisible, flexible, maintenable, auto-documenté
🎯 Pour votre escape game :
- Chaque objet est un dictionnaire
- L’inventaire est une liste de dictionnaires
- L’état du jeu est un dictionnaire
- Les quêtes sont des dictionnaires dans une liste
Exercices pratiques
Exercice 1 : Créer vos objets
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
Bon courage pour votre escape game ! 🗝️🚪
