Menu
Coddy logo textTech

Développement de personnages de jeu

Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy — leçon 86 sur 87.

Ce défi vous propose de construire un système de développement de personnages de jeu qui illustre la puissance de la POO dans la modélisation d'entités complexes et interactives.

Concevez une hiérarchie de personnages où une classe de base Character définit des attributs communs tels que la santé, le nom et le niveau. Des classes spécialisées telles que Warrior, Mage et Archer étendent cette base avec des capacités et des styles de combat uniques.

Les interfaces fonctionnent naturellement ici : Attackable pourrait définir des méthodes de combat, tandis que Healable gère les capacités de restauration. Un Mage pourrait implémenter les deux, alors qu'un Warrior se concentre uniquement sur l'attaque.

Envisagez d'utiliser le patron Strategy pour différents comportements d'attaque, permettant aux personnages de changer de style de combat de manière dynamique. Le patron State pourrait gérer les conditions des personnages comme les états normal, empoisonné ou étourdi qui affectent le comportement.

Pensez à la composition pour les systèmes d'équipement où les personnages « possèdent » des armes et des armures plutôt que d'en hériter. Utilisez des enums pour les classes de personnages ou les types de dégâts, et appliquez l'encapsulation pour protéger les statistiques contre les modifications invalides.

challenge icon

Défi

Facile

Construisons un système de développement de personnages de jeu qui met en avant la puissance de la POO pour modéliser des entités de jeu complexes et interactives ! Vous allez créer une hiérarchie de personnages avec différents styles de combat, des capacités spéciales et un système d'état qui affecte le comportement des personnages.

Vous organiserez votre code sur sept fichiers :

  • DamageType.java : Créez un enum représentant les différents types de dégâts dans le jeu. Incluez les valeurs PHYSICAL, MAGICAL, et RANGED. Ajoutez un champ privé description (String), un constructeur qui l'initialise, et un getter. Les dégâts physiques doivent avoir la description "brute force", les magiques doivent avoir "arcane energy", et à distance doivent avoir "precision strike".
  • Attackable.java : Créez une interface définissant les capacités de combat. Déclarez les méthodes attack(Character target) qui retourne une String décrivant l'attaque, et getDamageType() qui retourne un DamageType.
  • Healable.java : Créez une interface pour les capacités de restauration. Déclarez une méthode heal(int amount) qui retourne une String décrivant l'action de soin.
  • Character.java : Créez une classe de base abstraite pour tous les personnages du jeu. Incluez des champs privés pour name (String), health (int), maxHealth (int), et level (int). Le constructeur prend name, maxHealth, et level, en initialisant health à la valeur de maxHealth. Incluez des getters pour tous les champs. Ajoutez une méthode protégée setHealth(int health) qui garantit que la santé reste entre 0 et maxHealth. Créez une méthode takeDamage(int damage) qui réduit la santé et retourne "[name] takes [damage] damage! Health: [health]/[maxHealth]". Ajoutez une méthode isAlive() retournant true si la santé est supérieure à 0. Déclarez une méthode abstraite getCharacterClass() retournant une String.
  • Warrior.java : Créez une classe étendant Character et implémentant Attackable. Ajoutez un champ privé strength (int). Le constructeur prend name, maxHealth, level, et strength. Implémentez getCharacterClass() pour retourner "Warrior". Implémentez getDamageType() pour retourner PHYSICAL. Implémentez attack(Character target) pour infliger des dégâts égaux à strength plus level, appeler la méthode takeDamage de la cible, et retourner "[name] strikes with [damageType description] for [damage] damage!" suivi d'un saut de ligne et du résultat de takeDamage.
  • Mage.java : Créez une classe étendant Character et implémentant à la fois Attackable et Healable. Ajoutez des champs privés intelligence (int) et mana (int). Le constructeur prend name, maxHealth, level, intelligence, et mana. Implémentez getCharacterClass() pour retourner "Mage". Implémentez getDamageType() pour retourner MAGICAL. Implémentez attack(Character target) pour infliger des dégâts égaux à intelligence multipliée par 2, en suivant le même format que Warrior. Implémentez heal(int amount) pour restaurer la santé (en utilisant setHealth) et retourner "[name] channels healing magic! Health: [health]/[maxHealth]".
  • Main.java : Donnez vie à votre système de jeu ! Vous recevrez une chaîne de commandes séparées par des virgules :
    • CREATE_WARRIOR:name:maxHealth:level:strength
    • CREATE_MAGE:name:maxHealth:level:intelligence:mana
    • ATTACK:attackerName:targetName
    • HEAL:mageName:amount
    • STATUS:characterName

    Maintenez une collection de personnages. Traitez chaque commande et affichez :

    • CREATE_WARRIOR/CREATE_MAGE : [name] the [characterClass] joins the battle!
    • ATTACK : Affichez le résultat de l'attaque (la String retournée par la méthode attack)
    • HEAL : Affichez le résultat du soin, ou [name] cannot heal si le personnage n'est pas un Mage
    • STATUS : [name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]

    Après toutes les commandes, affichez --- Battle Summary --- suivi du statut de chaque personnage.

Vous recevrez une seule entrée : la chaîne de commandes séparées par des virgules.

Par exemple, avec l'entrée CREATE_WARRIOR:Thorin:100:5:15,CREATE_MAGE:Gandalf:80:7:12:50,ATTACK:Thorin:Gandalf,HEAL:Gandalf:25,STATUS:Gandalf, votre sortie serait :

Thorin the Warrior joins the battle!
Gandalf the Mage joins the battle!
Thorin strikes with brute force for 20 damage!
Gandalf takes 20 damage! Health: 60/80
Gandalf channels healing magic! Health: 80/80
Gandalf (Mage) - Level 7 - Health: 80/80 - Alive
--- Battle Summary ---
Thorin (Warrior) - Level 5 - Health: 100/100 - Alive
Gandalf (Mage) - Level 7 - Health: 80/80 - Alive

Ce défi combine l'héritage (hiérarchie Character), l'implémentation d'interfaces multiples (Mage implémente à la fois Attackable et Healable), les enums avec méthodes (DamageType), le polymorphisme (traiter différents types de personnages de manière uniforme) et l'encapsulation (gestion protégée de la santé) dans un système de jeu captivant !

Aide-mémoire

La programmation orientée objet (POO) permet de modéliser des systèmes complexes à travers des classes, l'héritage, les interfaces et les patrons de conception.

Hiérarchie de classes

Créez une classe de base avec des attributs communs et étendez-la avec des classes spécialisées :

public abstract class Character {
    private String name;
    private int health;
    private int maxHealth;
    private int level;
    
    public Character(String name, int maxHealth, int level) {
        this.name = name;
        this.maxHealth = maxHealth;
        this.health = maxHealth;
        this.level = level;
    }
    
    protected void setHealth(int health) {
        this.health = Math.max(0, Math.min(health, maxHealth));
    }
    
    public abstract String getCharacterClass();
}

Interfaces

Définissez des contrats pour des comportements spécifiques que les classes peuvent implémenter :

public interface Attackable {
    String attack(Character target);
    DamageType getDamageType();
}

public interface Healable {
    String heal(int amount);
}

Énumérations avec des champs

Les énumérations peuvent avoir des champs, des constructeurs et des méthodes :

public enum DamageType {
    PHYSICAL("brute force"),
    MAGICAL("arcane energy"),
    RANGED("precision strike");
    
    private String description;
    
    private DamageType(String description) {
        this.description = description;
    }
    
    public String getDescription() {
        return description;
    }
}

Implémentation d'interfaces multiples

Une classe peut implémenter plusieurs interfaces :

public class Mage extends Character implements Attackable, Healable {
    private int intelligence;
    private int mana;
    
    @Override
    public String attack(Character target) {
        // Implémentation
    }
    
    @Override
    public String heal(int amount) {
        // Implémentation
    }
}

Encapsulation

Utilisez des champs privés avec des setters protégés pour contrôler l'accès et valider les données :

protected void setHealth(int health) {
    this.health = Math.max(0, Math.min(health, maxHealth));
}

Polymorphisme

Traitez différents types de personnages de manière uniforme via leur classe de base commune ou leurs interfaces, permettant des collections et des appels de méthodes flexibles.

Essayez vous-même

import java.util.Scanner;
import java.util.HashMap;
import java.util.Map;
import java.util.LinkedHashMap;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        
        // TODO: Utiliser une collection pour maintenir les personnages (LinkedHashMap préserve l'ordre d'insertion)
        // LinkedHashMap<String, Character> characters = new LinkedHashMap<>();
        
        // TODO: Diviser l'entrée par virgule pour obtenir les commandes individuelles
        // String[] commands = input.split(",");
        
        // TODO: Traiter chaque commande :
        // - CREATE_WARRIOR:name:maxHealth:level:strength
        //   Afficher : "[name] the Warrior joins the battle!"
        // 
        // - CREATE_MAGE:name:maxHealth:level:intelligence:mana
        //   Afficher : "[name] the Mage joins the battle!"
        // 
        // - ATTACK:attackerName:targetName
        //   Afficher le résultat de l'attaque à partir de la méthode attack
        // 
        // - HEAL:mageName:amount
        //   Afficher le résultat du soin, ou "[name] cannot heal" s'il ne s'agit pas d'un Mage
        // 
        // - STATUS:characterName
        //   Afficher : "[name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]"
        
        // TODO: Après toutes les commandes, afficher "--- Battle Summary ---"
        // Puis afficher le statut de chaque personnage
    }
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet