Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Combat encounter

Nous allons refactoriser le code suivant afin d’appliquer les principes de responsabilité unique et de Stepdown Rule.

  1. Créez un répertoire TP12/ ainsi que les répertoires et fichiers suivants.

TP12/
├── include/
│    ├── character.h
│    └── combat-encounter.h
├── source/
│    ├── character.cpp
│    ├── combat-encounter.cpp
│    └── main.cpp
├── compile_flags.txt
└── makefile
character.h
combat-encounter.h
character.cpp
combat-encounter.cpp
main.cpp
compile_flags.txt
makefile
#ifndef CHARACTER_H
#define CHARACTER_H

#include <string>

class Character {
public:
    Character(const std::string& name, int health, int attack, int defense, int healAmount);

    std::string getName() const;
    int getHealth() const;
    int getAttack() const;
    int getDefense() const;
    int getHealAmount() const;

    bool isAlive() const;
    void takeDamage(int damage);
    void heal();

private:
    std::string mName;
    int mHealth;
    int mAttack;
    int mDefense;
    int mHealAmount;
};

#endif

Vous pouvez ajouter ce TP aux inputs des tâches dans tasks.json et créer une configuration dans launch.json afin de pouvoir le compiler, l’exécuter et le déboguer via l’interface de VSCodium, si vous le souhaitez.

  1. Exécutez le code et essayez de comprendre le comportement du programme.

Notre objectif est de refactoriser CombatEncounter::run(), ce qui nous amènera probablement à modifier Character, CombatEncounter et à introduire de nouvelles classes.

  1. Dans un premier temps, nous allons extraire les affichages sous forme de méthodes statiques dans une classe CombatPrinter.

Dans l’implémentation des méthodes d’affichage de CombatPrinter, certains affichages concernent uniquement un personnage, comme ses attributs ou ses points de vie. Dans ce cas, la responsabilité revient naturellement à la classe Character.

  1. Vous pouvez extraire l’affichage des attributs des personnages dans Character::displayInformation et l’affichage des points de vie dans Character::displayHealth.

Une fois les fonctions liées à la sortie (std::cout) correctement factorisées, nous allons passer à la lecture des actions de l’utilisateur (std::cin). Pour le moment, cette responsabilité est directement gérée par CombatEncounter à l’aide de enum Action.

  1. Nous allons extraire enum Action et le placer dans une classe InputAction, avec une méthode readAction qui récupère l’entrée de l’utilisateur.

Maintenant, nous voulons que la boucle de combat soit facile à lire. Un pseudo-code de CombatEncounter::run() devrait ressembler à ceci :

  1. Nous allons extraire les tours du héros et de l’ennemi dans CombatEncounter::playHeroTurn() et CombatEncounter::playEnemyTurn() afin que CombatEncounter::run() respecte correctement The Stepdown Rule.

Finalement, le calcul des dégâts dans le tour du héros et celui de l’ennemi est identique. Extraire ce calcul dans une fonction permet de rendre le code moins redondant et plus facile à modifier si la formule de calcul évolue par la suite.

  1. Nous allons donc extraire le calcul de int damage dans une méthode CombatEncounter::calculateDamage.