ajout de tous les cours et TP préparés cet été
This commit is contained in:
448
POO/TP/TP_Pokemon.md
Normal file
448
POO/TP/TP_Pokemon.md
Normal 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>.
|
||||
Reference in New Issue
Block a user