ajout de tous les cours et TP préparés cet été

This commit is contained in:
2026-01-17 23:10:49 +01:00
parent ed9415bc81
commit 301cf5a98f
125 changed files with 21614 additions and 542 deletions

251
POO/TP/Corrige_TP_POO.md Normal file
View File

@@ -0,0 +1,251 @@
# Corrigé du TP Programmation Orientée Objet
---
## 2. Classe Auteur
```python
class Auteur:
def __init__(self, nom, naissance, deces=False):
"""
Méthode constructeur de Auteur.
:param nom: (str) Nom de l'auteur
:param naissance: (int) Année de naissance de l'auteur
:param deces: (int/bool) Année de décès / False si toujours en vie
"""
self.nom = nom
self.annee_naissance = naissance
self.deces = deces
def __repr__(self):
"""Représentation de l'auteur."""
if self.deces:
return f"{self.nom} ({self.annee_naissance}-{self.deces})"
else:
return f"{self.nom} (né en {self.annee_naissance})"
```
**Explications :**
- L'attribut `deces` a une valeur par défaut (`False`) pour gérer les auteurs vivants
- La méthode `__repr__` est ajoutée pour un affichage lisible
---
## 3. Classe Livre
```python
class Livre:
def __init__(self, titre, genre, auteur):
"""
Méthode constructeur de Livre.
:param titre: (str) Titre du livre
:param genre: (str) Genre du livre
:param auteur: (Auteur) Auteur du livre (objet de type Auteur)
"""
self.titre = titre
self.genre = genre
self.auteur = auteur
def __repr__(self):
"""Représentation du livre."""
return f"{self.titre} - {self.auteur.nom}"
```
**Point important :**
- L'attribut `auteur` doit être un objet de type `Auteur`, pas une chaîne de caractères
- Cela permet d'accéder aux informations de l'auteur via `livre.auteur.nom`, `livre.auteur.annee_naissance`, etc.
---
## 4. Classe Bibliothèque
```python
class Bibliotheque:
def __init__(self, rayon):
"""
Méthode constructeur de Bibliothèque.
L'ensemble des livres est vide lors de l'initialisation.
:param rayon: (str) Type de livre que la bibliothèque peut recevoir
"""
self.rayon = rayon
self.ens_livre = []
def add_livre(self, livre):
"""
Méthode permettant d'ajouter un livre.
:param livre: (Livre) Livre à ajouter
:return: (str) Précise si le livre est ajouté ou non
"""
if livre.genre == self.rayon:
self.ens_livre.append(livre)
return "Livre ajouté"
else:
return "Impossible d'ajouter le livre (genre incompatible)"
def est_dispo(self, nom_livre):
"""
Méthode parcourant l'ensemble des livres de la bibliothèque
pour savoir si un livre est disponible.
:param nom_livre: (str) Nom du livre à rechercher
:return: (int) Indice du livre si dispo, -1 sinon
"""
i = 0
while i < len(self.ens_livre):
if self.ens_livre[i].titre == nom_livre:
return i
i += 1
return -1
def prete_livre(self, nom_livre):
"""
Méthode permettant de prêter un livre s'il est disponible.
:param nom_livre: (str) Nom du livre à emprunter
:return: (Livre/bool) Livre si emprunt possible, False sinon
"""
indice = self.est_dispo(nom_livre)
if indice != -1:
livre = self.ens_livre[indice]
# Suppression du livre de la liste
self.ens_livre = self.ens_livre[:indice] + self.ens_livre[indice+1:]
return livre
else:
return False
def __repr__(self):
"""Représentation de la bibliothèque."""
return f"Bibliothèque [{self.rayon}] - {len(self.ens_livre)} livre(s)"
```
**Explications :**
- `add_livre` vérifie que le genre du livre correspond au rayon
- `est_dispo` parcourt la liste et renvoie l'indice ou -1
- `prete_livre` utilise `est_dispo` et supprime le livre de la liste via les slices
---
## 5. Création des objets
```python
# Création des auteurs
a1 = Auteur('Victor Hugo', 1802, 1885)
a2 = Auteur('J.K. Rowling', 1965)
a3 = Auteur('Agatha Christie', 1890, 1976)
a4 = Auteur('Stephen King', 1947)
# Création des livres
l1 = Livre('Les Misérables', 'Classique', a1)
l2 = Livre('Notre-Dame de Paris', 'Classique', a1)
l3 = Livre("Harry Potter à l'école des sorciers", 'Fantastique', a2)
l4 = Livre('Le Crime de l\'Orient-Express', 'Policier', a3)
l5 = Livre('Shining', 'Horreur', a4)
l6 = Livre('Ça', 'Horreur', a4)
# Création des bibliothèques
biblio_classique = Bibliotheque('Classique')
biblio_horreur = Bibliotheque('Horreur')
# Ajout des livres
print(biblio_classique.add_livre(l1)) # "Livre ajouté"
print(biblio_classique.add_livre(l2)) # "Livre ajouté"
print(biblio_classique.add_livre(l3)) # "Impossible..." (genre incompatible)
print(biblio_horreur.add_livre(l5)) # "Livre ajouté"
print(biblio_horreur.add_livre(l6)) # "Livre ajouté"
# Affichage
print(biblio_classique) # Bibliothèque [Classique] - 2 livre(s)
print(biblio_horreur) # Bibliothèque [Horreur] - 2 livre(s)
```
---
## 6. Tests complets
```python
# Test de disponibilité
print(biblio_classique.est_dispo('Les Misérables')) # 0
print(biblio_classique.est_dispo('Livre inexistant')) # -1
# Test de prêt
livre_emprunte = biblio_classique.prete_livre('Les Misérables')
print(livre_emprunte) # Les Misérables - Victor Hugo
print(biblio_classique) # Bibliothèque [Classique] - 1 livre(s)
# Le livre n'est plus disponible
print(biblio_classique.est_dispo('Les Misérables')) # -1
# Tentative de prêt d'un livre non disponible
print(biblio_classique.prete_livre('Les Misérables')) # False
```
---
## Diagramme de classes (UML simplifié)
```
+----------------+ +----------------+ +------------------+
| Auteur | | Livre | | Bibliotheque |
+----------------+ +----------------+ +------------------+
| - nom | | - titre | | - rayon |
| - annee_naiss. |<------| - genre | | - ens_livre |
| - deces | | - auteur |------>| |
+----------------+ +----------------+ +------------------+
| + __init__() | | + __init__() | | + __init__() |
| + __repr__() | | + __repr__() | | + add_livre() |
+----------------+ +----------------+ | + est_dispo() |
| + prete_livre() |
| + __repr__() |
+------------------+
```
---
## Pour aller plus loin
### Ajout d'une méthode de retour de livre
```python
def retour_livre(self, livre):
"""
Méthode permettant de retourner un livre emprunté.
:param livre: (Livre) Livre à retourner
:return: (str) Message de confirmation
"""
if livre.genre == self.rayon:
self.ens_livre.append(livre)
return f"'{livre.titre}' a été retourné"
else:
return "Ce livre n'appartient pas à ce rayon"
```
### Ajout d'une recherche par auteur
```python
def livres_par_auteur(self, nom_auteur):
"""
Renvoie tous les livres d'un auteur donné.
:param nom_auteur: (str) Nom de l'auteur
:return: (list) Liste des livres de cet auteur
"""
resultat = []
for livre in self.ens_livre:
if livre.auteur.nom == nom_auteur:
resultat.append(livre)
return resultat
```
---
Auteurs : Florian Mathieu, Enzo Frémeaux, Thimothée Decooster
Licence CC BY NC
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.

View File

@@ -0,0 +1,358 @@
"""
Corrigé du TP Pokémon Arena — Programmation Orientée Objet
"""
# =============================================================================
# Dictionnaire des faiblesses (Bonus Exercice 3)
# =============================================================================
FAIBLESSES = {
"Eau": ["Feu"],
"Feu": ["Plante"],
"Plante": ["Eau"],
"Electrik": ["Eau"],
"Roche": ["Eau", "Plante"]
}
# =============================================================================
# PARTIE 1 : Classe Pokemon
# =============================================================================
class Pokemon:
def __init__(self, nom, type_pokemon, niveau=1, pv_max=100, attaque=10):
"""
Constructeur de la classe Pokemon.
:param nom: (str) Nom du Pokémon
:param type_pokemon: (str) Type élémentaire
:param niveau: (int) Niveau du Pokémon
:param pv_max: (int) Points de vie maximum
:param attaque: (int) Puissance d'attaque
"""
self.nom = nom
self.type_pokemon = type_pokemon
self.niveau = niveau
self.pv_max = pv_max
self.pv = pv_max
self.attaque = attaque
def __repr__(self):
"""Représentation textuelle du Pokémon."""
return f"{self.nom} ({self.type_pokemon}) - Nv.{self.niveau} - {self.pv}/{self.pv_max} PV"
def est_ko(self):
"""
Vérifie si le Pokémon est KO.
:return: (bool) True si PV <= 0, False sinon
"""
return self.pv <= 0
def subir_degats(self, degats):
"""
Inflige des dégâts au Pokémon.
Les PV ne peuvent pas descendre en dessous de 0.
:param degats: (int) Nombre de dégâts subis
"""
self.pv = max(0, self.pv - degats)
def attaquer(self, cible):
"""
Attaque un autre Pokémon avec prise en compte des faiblesses.
:param cible: (Pokemon) Pokémon ciblé par l'attaque
"""
degats = self.attaque
# Vérifier si le type de la cible est faible contre notre type
if self.type_pokemon in FAIBLESSES:
if cible.type_pokemon in FAIBLESSES[self.type_pokemon]:
degats *= 2
print(f"C'est super efficace !")
print(f"{self.nom} attaque {cible.nom} et inflige {degats} dégâts !")
cible.subir_degats(degats)
def soigner(self, soin):
"""
Soigne le Pokémon.
Les PV ne peuvent pas dépasser pv_max.
:param soin: (int) Nombre de PV récupérés
"""
self.pv = min(self.pv_max, self.pv + soin)
# =============================================================================
# PARTIE 2 : Classe Dresseur
# =============================================================================
class Dresseur:
def __init__(self, nom):
"""
Constructeur de la classe Dresseur.
:param nom: (str) Nom du dresseur
"""
self.nom = nom
self.equipe = []
def ajouter_pokemon(self, pokemon):
"""
Ajoute un Pokémon à l'équipe si possible (max 6).
:param pokemon: (Pokemon) Pokémon à ajouter
:return: (bool) True si ajouté, False sinon
"""
if len(self.equipe) < 6:
self.equipe.append(pokemon)
return True
else:
print("L'équipe est complète (6 Pokémon maximum) !")
return False
def pokemon_disponibles(self):
"""
Renvoie la liste des Pokémon non KO.
:return: (list) Liste des Pokémon encore en état de combattre
"""
disponibles = []
for pokemon in self.equipe:
if not pokemon.est_ko():
disponibles.append(pokemon)
return disponibles
def premier_pokemon_dispo(self):
"""
Renvoie le premier Pokémon non KO.
:return: (Pokemon/None) Premier Pokémon dispo ou None
"""
for pokemon in self.equipe:
if not pokemon.est_ko():
return pokemon
return None
def tous_ko(self):
"""
Vérifie si tous les Pokémon sont KO.
:return: (bool) True si tous KO, False sinon
"""
for pokemon in self.equipe:
if not pokemon.est_ko():
return False
return True
def __repr__(self):
"""Représentation du dresseur."""
result = f"Dresseur {self.nom} - {len(self.equipe)} Pokémon"
for pokemon in self.equipe:
result += f"\n - {pokemon}"
return result
# =============================================================================
# PARTIE 3 : Classe Combat
# =============================================================================
class Combat:
def __init__(self, dresseur1, dresseur2):
"""
Constructeur de la classe Combat.
:param dresseur1: (Dresseur) Premier dresseur
:param dresseur2: (Dresseur) Second dresseur
"""
self.dresseur1 = dresseur1
self.dresseur2 = dresseur2
self.tour = 0
def afficher_etat(self):
"""Affiche l'état actuel du combat."""
print(f"\n{'='*40}")
print(f"Tour {self.tour}")
print(f"{'='*40}")
poke1 = self.dresseur1.premier_pokemon_dispo()
poke2 = self.dresseur2.premier_pokemon_dispo()
if poke1:
print(f"{self.dresseur1.nom}: {poke1.nom} ({poke1.pv}/{poke1.pv_max} PV)")
if poke2:
print(f"{self.dresseur2.nom}: {poke2.nom} ({poke2.pv}/{poke2.pv_max} PV)")
print()
def lancer_combat(self):
"""
Lance le combat tour par tour.
Chaque tour, les deux Pokémon actifs s'attaquent.
Quand un Pokémon est KO, le suivant prend sa place.
Le combat s'arrête quand un dresseur n'a plus de Pokémon.
"""
print(f"\n*** COMBAT : {self.dresseur1.nom} VS {self.dresseur2.nom} ***")
while not self.dresseur1.tous_ko() and not self.dresseur2.tous_ko():
self.tour += 1
self.afficher_etat()
# Récupérer les Pokémon actifs
poke1 = self.dresseur1.premier_pokemon_dispo()
poke2 = self.dresseur2.premier_pokemon_dispo()
# Le Pokémon 1 attaque
poke1.attaquer(poke2)
# Vérifier si Pokémon 2 est KO
if poke2.est_ko():
print(f"\n{poke2.nom} est KO !")
nouveau = self.dresseur2.premier_pokemon_dispo()
if nouveau:
print(f"{self.dresseur2.nom} envoie {nouveau.nom} !")
continue # Passer au tour suivant
# Le Pokémon 2 attaque
poke2.attaquer(poke1)
# Vérifier si Pokémon 1 est KO
if poke1.est_ko():
print(f"\n{poke1.nom} est KO !")
nouveau = self.dresseur1.premier_pokemon_dispo()
if nouveau:
print(f"{self.dresseur1.nom} envoie {nouveau.nom} !")
# Afficher le vainqueur
print(f"\n{'='*40}")
if self.dresseur1.tous_ko():
print(f"Tous les Pokémon de {self.dresseur1.nom} sont KO !")
print(f"*** {self.dresseur2.nom.upper()} REMPORTE LE COMBAT ! ***")
else:
print(f"Tous les Pokémon de {self.dresseur2.nom} sont KO !")
print(f"*** {self.dresseur1.nom.upper()} REMPORTE LE COMBAT ! ***")
print(f"{'='*40}")
# =============================================================================
# PARTIE 4 : Centre Pokémon
# =============================================================================
class CentrePokemon:
def __init__(self, ville):
"""
:param ville: (str) Ville où se trouve le centre
"""
self.ville = ville
def soigner_equipe(self, dresseur):
"""
Soigne tous les Pokémon d'un dresseur à 100% de leurs PV.
:param dresseur: (Dresseur) Dresseur dont l'équipe doit être soignée
"""
print(f"\n*** Centre Pokémon de {self.ville} ***")
print(f"Bienvenue {dresseur.nom} !")
print("Nous allons soigner vos Pokémon...")
for pokemon in dresseur.equipe:
pokemon.pv = pokemon.pv_max
print("Vos Pokémon sont en pleine forme !")
print("À bientôt !\n")
# =============================================================================
# BONUS : Classe Capacite
# =============================================================================
class Capacite:
def __init__(self, nom, puissance, type_capacite, pp_max):
"""
:param nom: (str) Nom de la capacité
:param puissance: (int) Puissance de base
:param type_capacite: (str) Type de la capacité
:param pp_max: (int) Nombre d'utilisations max
"""
self.nom = nom
self.puissance = puissance
self.type_capacite = type_capacite
self.pp_max = pp_max
self.pp = pp_max
def utiliser(self):
"""Utilise la capacité si PP disponibles."""
if self.pp > 0:
self.pp -= 1
return True
else:
print(f"{self.nom} : plus de PP !")
return False
def __repr__(self):
return f"{self.nom} ({self.type_capacite}) - {self.puissance} DMG - {self.pp}/{self.pp_max} PP"
# =============================================================================
# TESTS
# =============================================================================
if __name__ == "__main__":
print("=" * 50)
print("TEST DES CLASSES POKEMON")
print("=" * 50)
# Création des Pokémon
pikachu = Pokemon("Pikachu", "Electrik", 25, 80, 15)
dracaufeu = Pokemon("Dracaufeu", "Feu", 50, 150, 25)
tortank = Pokemon("Tortank", "Eau", 45, 140, 22)
onix = Pokemon("Onix", "Roche", 30, 120, 18)
racaillou = Pokemon("Racaillou", "Roche", 20, 80, 12)
print("\nPokémon créés :")
print(f" - {pikachu}")
print(f" - {dracaufeu}")
print(f" - {tortank}")
print(f" - {onix}")
print(f" - {racaillou}")
# Test des attaques avec faiblesses
print("\n--- Test attaque avec faiblesse ---")
print(f"Avant : {onix}")
tortank.attaquer(onix) # Eau bat Roche -> x2
print(f"Après : {onix}")
# Création des dresseurs
print("\n" + "=" * 50)
print("CREATION DES DRESSEURS")
print("=" * 50)
sacha = Dresseur("Sacha")
sacha.ajouter_pokemon(Pokemon("Pikachu", "Electrik", 25, 80, 15))
sacha.ajouter_pokemon(Pokemon("Dracaufeu", "Feu", 50, 150, 25))
sacha.ajouter_pokemon(Pokemon("Tortank", "Eau", 45, 140, 22))
pierre = Dresseur("Pierre")
pierre.ajouter_pokemon(Pokemon("Onix", "Roche", 30, 120, 18))
pierre.ajouter_pokemon(Pokemon("Racaillou", "Roche", 20, 80, 12))
print(f"\n{sacha}")
print(f"\n{pierre}")
# Lancement du combat
print("\n" + "=" * 50)
print("LANCEMENT DU COMBAT")
print("=" * 50)
combat = Combat(sacha, pierre)
combat.lancer_combat()
# Soins au Centre Pokémon
print("\n" + "=" * 50)
print("SOINS AU CENTRE POKEMON")
print("=" * 50)
centre = CentrePokemon("Argenta")
centre.soigner_equipe(sacha)
print(sacha)

View File

@@ -4,7 +4,7 @@
## 1. Introduction
Le but principal de ce TP est d'implémenter une classe Auteur. Ainsi qu'une classe Livre et Bibliothèque. Il y a volontairement pas/peu d'indication sur le code. Seuls les attributs et méthode **nécessaires** sont indiqués. Leurs implémentations sont libre et dépendent de chacun.
Le but principal de ce TP est d'implémenter une classe Auteur, ainsi qu'une classe Livre et Bibliothèque. Il n'y a volontairement pas ou peu d'indications sur le code. Seuls les attributs et méthode **nécessaires** sont indiqués. Leurs implémentations sont libre et dépendent de chacun.
## 2. Classe Auteur
@@ -67,4 +67,12 @@ Créer la classe est bien, maintenant il faut manipuler les objets.
## 6. Pour aller plus loin
Ici, il est possible d'ajouter n'importe quel attributs et/ou méthodes de votre choix.
Il faut s'entraîner, essayer d'aller le plus loin possible. Alors essayez, testez !
Il faut s'entraîner, essayer d'aller le plus loin possible. Alors essayez, testez !
---
Auteurs : Florian Mathieu, Enzo Frémeaux, Thimothée Decooster
Licence CC BY NC
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.

448
POO/TP/TP_Pokemon.md Normal file
View File

@@ -0,0 +1,448 @@
# TP : Pokémon Arena — Programmation Orientée Objet
> **Thème** : Classes, attributs, méthodes, interactions entre objets
---
## Contexte
Depuis 1996, Pokémon est l'une des franchises les plus populaires au monde. En 2026, avec la sortie de Pokémon Legends: Z-A, la licence bat tous les records.
Dans ce TP, vous allez créer un **simulateur de combat Pokémon** en utilisant la Programmation Orientée Objet. Vous modéliserez des Pokémon, des dresseurs et des combats.
---
## Partie 1 : La classe Pokémon
### Exercice 1 : Créer la classe de base
Créez une classe `Pokemon` avec les caractéristiques suivantes :
**Attributs :**
- `nom` : nom du Pokémon (str)
- `type_pokemon` : type élémentaire (str) — "Feu", "Eau", "Plante", "Electrik", etc.
- `niveau` : niveau du Pokémon (int, par défaut 1)
- `pv_max` : points de vie maximum (int, par défaut 100)
- `pv` : points de vie actuels (int, initialisé à `pv_max`)
- `attaque` : puissance d'attaque (int, par défaut 10)
**Méthodes :**
- `__init__` : constructeur
- `__repr__` : affiche le Pokémon sous la forme `"Pikachu (Electrik) - Nv.25 - 80/100 PV"`
```python
class Pokemon:
def __init__(self, nom, type_pokemon, niveau=1, pv_max=100, attaque=10):
"""
Constructeur de la classe Pokemon.
:param nom: (str) Nom du Pokémon
:param type_pokemon: (str) Type élémentaire
:param niveau: (int) Niveau du Pokémon
:param pv_max: (int) Points de vie maximum
:param attaque: (int) Puissance d'attaque
"""
# À compléter
pass
def __repr__(self):
"""Représentation textuelle du Pokémon."""
# À compléter
pass
```
**Tests :**
```python
>>> pikachu = Pokemon("Pikachu", "Electrik", niveau=25, pv_max=80, attaque=15)
>>> print(pikachu)
Pikachu (Electrik) - Nv.25 - 80/80 PV
```
---
### Exercice 2 : Méthodes de combat
Ajoutez les méthodes suivantes à la classe `Pokemon` :
```python
def est_ko(self):
"""
Vérifie si le Pokémon est KO.
:return: (bool) True si PV <= 0, False sinon
"""
# À compléter
pass
def subir_degats(self, degats):
"""
Inflige des dégâts au Pokémon.
Les PV ne peuvent pas descendre en dessous de 0.
:param degats: (int) Nombre de dégâts subis
"""
# À compléter
pass
def attaquer(self, cible):
"""
Attaque un autre Pokémon.
Affiche un message et inflige des dégâts à la cible.
:param cible: (Pokemon) Pokémon ciblé par l'attaque
"""
# À compléter
pass
def soigner(self, soin):
"""
Soigne le Pokémon.
Les PV ne peuvent pas dépasser pv_max.
:param soin: (int) Nombre de PV récupérés
"""
# À compléter
pass
```
**Tests :**
```python
>>> pikachu = Pokemon("Pikachu", "Electrik", niveau=25, pv_max=80, attaque=15)
>>> salameche = Pokemon("Salamèche", "Feu", niveau=20, pv_max=70, attaque=12)
>>> pikachu.attaquer(salameche)
Pikachu attaque Salamèche et inflige 15 dégâts !
>>> print(salameche)
Salamèche (Feu) - Nv.20 - 55/70 PV
>>> salameche.est_ko()
False
```
---
### Exercice 3 : Système de faiblesses (Bonus)
En Pokémon, certains types sont plus efficaces contre d'autres :
- **Eau** bat **Feu** (×2 dégâts)
- **Feu** bat **Plante** (×2 dégâts)
- **Plante** bat **Eau** (×2 dégâts)
- **Electrik** bat **Eau** (×2 dégâts)
Modifiez la méthode `attaquer` pour prendre en compte les faiblesses :
```python
# Dictionnaire des faiblesses : type_attaquant -> liste des types faibles
FAIBLESSES = {
"Eau": ["Feu"],
"Feu": ["Plante"],
"Plante": ["Eau"],
"Electrik": ["Eau"]
}
def attaquer(self, cible):
"""
Attaque un autre Pokémon avec prise en compte des faiblesses.
"""
degats = self.attaque
# Vérifier si le type de la cible est faible contre notre type
if self.type_pokemon in FAIBLESSES:
if cible.type_pokemon in FAIBLESSES[self.type_pokemon]:
degats *= 2
print(f"C'est super efficace !")
print(f"{self.nom} attaque {cible.nom} et inflige {degats} dégâts !")
cible.subir_degats(degats)
```
---
## Partie 2 : La classe Dresseur
### Exercice 4 : Créer la classe Dresseur
Un dresseur possède une équipe de Pokémon (maximum 6).
**Attributs :**
- `nom` : nom du dresseur (str)
- `equipe` : liste de Pokémon (list, vide par défaut)
**Méthodes :**
- `__init__` : constructeur
- `ajouter_pokemon(pokemon)` : ajoute un Pokémon à l'équipe (max 6)
- `pokemon_disponibles()` : renvoie la liste des Pokémon non KO
- `premier_pokemon_dispo()` : renvoie le premier Pokémon non KO ou None
- `tous_ko()` : renvoie True si tous les Pokémon sont KO
- `__repr__` : affiche le dresseur et son équipe
```python
class Dresseur:
def __init__(self, nom):
"""
Constructeur de la classe Dresseur.
:param nom: (str) Nom du dresseur
"""
# À compléter
pass
def ajouter_pokemon(self, pokemon):
"""
Ajoute un Pokémon à l'équipe si possible (max 6).
:param pokemon: (Pokemon) Pokémon à ajouter
:return: (bool) True si ajouté, False sinon
"""
# À compléter
pass
def pokemon_disponibles(self):
"""
Renvoie la liste des Pokémon non KO.
:return: (list) Liste des Pokémon encore en état de combattre
"""
# À compléter
pass
def premier_pokemon_dispo(self):
"""
Renvoie le premier Pokémon non KO.
:return: (Pokemon/None) Premier Pokémon dispo ou None
"""
# À compléter
pass
def tous_ko(self):
"""
Vérifie si tous les Pokémon sont KO.
:return: (bool) True si tous KO, False sinon
"""
# À compléter
pass
def __repr__(self):
"""Représentation du dresseur."""
# À compléter
pass
```
**Tests :**
```python
>>> sacha = Dresseur("Sacha")
>>> sacha.ajouter_pokemon(Pokemon("Pikachu", "Electrik", 25, 80, 15))
True
>>> sacha.ajouter_pokemon(Pokemon("Dracaufeu", "Feu", 50, 150, 25))
True
>>> print(sacha)
Dresseur Sacha - 2 Pokémon
- Pikachu (Electrik) - Nv.25 - 80/80 PV
- Dracaufeu (Feu) - Nv.50 - 150/150 PV
>>> sacha.tous_ko()
False
```
---
## Partie 3 : La classe Combat
### Exercice 5 : Simulateur de combat
Créez une classe `Combat` qui simule un affrontement entre deux dresseurs.
**Attributs :**
- `dresseur1` : premier dresseur (Dresseur)
- `dresseur2` : second dresseur (Dresseur)
- `tour` : numéro du tour actuel (int)
**Méthodes :**
- `__init__` : constructeur
- `lancer_combat()` : lance le combat jusqu'à ce qu'un dresseur n'ait plus de Pokémon
- `afficher_etat()` : affiche l'état actuel du combat
```python
class Combat:
def __init__(self, dresseur1, dresseur2):
"""
Constructeur de la classe Combat.
:param dresseur1: (Dresseur) Premier dresseur
:param dresseur2: (Dresseur) Second dresseur
"""
# À compléter
pass
def afficher_etat(self):
"""Affiche l'état actuel du combat."""
print(f"\n{'='*40}")
print(f"Tour {self.tour}")
print(f"{'='*40}")
# Afficher les Pokémon actifs
# À compléter
pass
def lancer_combat(self):
"""
Lance le combat tour par tour.
Chaque tour, les deux Pokémon actifs s'attaquent.
Quand un Pokémon est KO, le suivant prend sa place.
Le combat s'arrête quand un dresseur n'a plus de Pokémon.
"""
print(f"\n*** COMBAT : {self.dresseur1.nom} VS {self.dresseur2.nom} ***\n")
while not self.dresseur1.tous_ko() and not self.dresseur2.tous_ko():
self.tour += 1
self.afficher_etat()
# Récupérer les Pokémon actifs
poke1 = self.dresseur1.premier_pokemon_dispo()
poke2 = self.dresseur2.premier_pokemon_dispo()
# Le Pokémon 1 attaque
# À compléter
# Vérifier si Pokémon 2 est KO
# À compléter
# Le Pokémon 2 attaque (s'il n'est pas KO)
# À compléter
# Vérifier si Pokémon 1 est KO
# À compléter
# Afficher le vainqueur
# À compléter
pass
```
**Exemple d'exécution :**
```
*** COMBAT : Sacha VS Pierre ***
========================================
Tour 1
========================================
Sacha: Pikachu (80/80 PV)
Pierre: Onix (120/120 PV)
Pikachu attaque Onix et inflige 15 dégâts !
Onix attaque Pikachu et inflige 20 dégâts !
========================================
Tour 2
========================================
Sacha: Pikachu (60/80 PV)
Pierre: Onix (105/120 PV)
...
Pikachu est KO !
Sacha envoie Dracaufeu !
...
Tous les Pokémon de Pierre sont KO !
*** SACHA REMPORTE LE COMBAT ! ***
```
---
## Partie 4 : Améliorations
### Exercice 6 : Centre Pokémon
Créez une classe `CentrePokemon` qui permet de soigner une équipe :
```python
class CentrePokemon:
def __init__(self, ville):
"""
:param ville: (str) Ville où se trouve le centre
"""
self.ville = ville
def soigner_equipe(self, dresseur):
"""
Soigne tous les Pokémon d'un dresseur à 100% de leurs PV.
:param dresseur: (Dresseur) Dresseur dont l'équipe doit être soignée
"""
# À compléter
pass
```
---
### Exercice 7 : Capacités spéciales (Pour aller plus loin)
Créez une classe `Capacite` pour donner des attaques spéciales aux Pokémon :
```python
class Capacite:
def __init__(self, nom, puissance, type_capacite, pp_max):
"""
:param nom: (str) Nom de la capacité
:param puissance: (int) Puissance de base
:param type_capacite: (str) Type de la capacité
:param pp_max: (int) Nombre d'utilisations max
"""
self.nom = nom
self.puissance = puissance
self.type_capacite = type_capacite
self.pp_max = pp_max
self.pp = pp_max
```
Modifiez la classe `Pokemon` pour qu'un Pokémon possède une liste de capacités (max 4) et puisse choisir son attaque.
---
## Résumé des classes
| Classe | Attributs | Méthodes principales |
|--------|-----------|----------------------|
| `Pokemon` | nom, type, niveau, pv, attaque | attaquer(), subir_degats(), est_ko() |
| `Dresseur` | nom, equipe | ajouter_pokemon(), tous_ko() |
| `Combat` | dresseur1, dresseur2, tour | lancer_combat() |
| `CentrePokemon` | ville | soigner_equipe() |
---
## Code de test final
```python
# Création des Pokémon
pikachu = Pokemon("Pikachu", "Electrik", 25, 80, 15)
dracaufeu = Pokemon("Dracaufeu", "Feu", 50, 150, 25)
tortank = Pokemon("Tortank", "Eau", 45, 140, 22)
onix = Pokemon("Onix", "Roche", 30, 120, 18)
racaillou = Pokemon("Racaillou", "Roche", 20, 80, 12)
# Création des dresseurs
sacha = Dresseur("Sacha")
sacha.ajouter_pokemon(pikachu)
sacha.ajouter_pokemon(dracaufeu)
sacha.ajouter_pokemon(tortank)
pierre = Dresseur("Pierre")
pierre.ajouter_pokemon(onix)
pierre.ajouter_pokemon(racaillou)
# Lancement du combat
combat = Combat(sacha, pierre)
combat.lancer_combat()
# Soins au Centre Pokémon
centre = CentrePokemon("Argenta")
centre.soigner_equipe(sacha)
print(sacha)
```
---
Auteurs : Florian Mathieu, Enzo Frémeaux, Thimothée Decooster
Licence CC BY NC
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.

View File

@@ -70,7 +70,7 @@ class Bibliotheque :
#Initialisation des valeurs :
a1 = Auteur('Bob',1990)
a2 = Auteur('Alice', 1998,2009)
l1 = Livre('Livre NSI terminale','Cours','Bob')
l1 = Livre('Livre NSI terminale','Cours',a1)
l2 = Livre('Livre NSI premiere','Cours',a2)
l3 = Livre('Les animaux de compagnies','Animaux',a1)
l4 = Livre('Les animaux sauvages','Animaux',a2)