Menu
Coddy logo textTech

Système de personnages de jeu

Fait partie de la section Programmation Orientée Objet du Journey GO de Coddy. Leçon 107 sur 107.

challenge icon

Défi

Facile

Construisons un système de personnages de jeu qui réunit l’intégration de structures, les interfaces et le modèle Strategy afin de créer des mécaniques de combat flexibles ! Vous concevrez différents types de personnages capables d’attaquer et de se défendre de manière unique, avec des capacités pouvant être remplacées à l’exécution.

Vous organiserez votre code sur cinq fichiers :

  • character.go : définissez une structure Character de base avec des champs communs : Name (string), Health (int) et MaxHealth (int). Incluez un constructeur NewCharacter et les méthodes suivantes :
    • IsAlive() bool : renvoie true si la santé est supérieure à 0
    • Status() string : renvoie le format : [Name]: [Health]/[MaxHealth] HP
  • interfaces.go : définissez les interfaces de combat qui permettent le polymorphisme :
    • interface Attacker avec Attack() int : renvoie les dégâts infligés
    • interface Defender avec TakeDamage(damage int) int : applique une réduction des dégâts et renvoie les dégâts réellement subis
    • interface Ability avec Use() string : renvoie une description de l’effet de la capacité
  • characters.go : créez trois types de personnages qui intègrent Character et implémentent à la fois Attacker et Defender :

    Warrior : possède les champs Strength (int) et Armor (int). L’attaque renvoie Strength comme dégâts. TakeDamage réduit les dégâts entrants de la valeur d’Armor (avec un minimum de 1 dégât subi).

    Mage : possède les champs Intelligence (int) et MagicResist (int). L’attaque renvoie Intelligence * 2 comme dégâts. TakeDamage réduit les dégâts entrants de MagicResist / 2 (avec un minimum de 1 dégât subi).

    Archer : possède les champs Agility (int) et Evasion (int). L’attaque renvoie Agility + 5 comme dégâts. TakeDamage : si Evasion > 10, réduit les dégâts de 25 % (division entière), sinon les dégâts complets sont subis (avec un minimum de 1 dégât subi).

    Incluez des constructeurs pour chacun d’eux : NewWarrior, NewMage, NewArcher, qui prennent le nom, la santé et les valeurs de statistiques spécifiques à leur type.

  • abilities.go : implémentez le modèle Strategy avec des capacités interchangeables :

    structure FireSpell avec Power (int). Son Use() renvoie : Casts fireball for [Power] damage

    structure IceSpell avec Power (int). Son Use() renvoie : Casts ice shard for [Power] damage

    structure PowerStrike avec Multiplier (int). Son Use() renvoie : Performs power strike at [Multiplier]x damage

    Ajoutez un champ ability (de type Ability) à la structure Mage, avec les méthodes SetAbility(a Ability) et UseAbility() string. UseAbility renvoie No ability set si ability vaut nil.

  • main.go : créez des personnages et démontrez les mécaniques de combat.

    Lisez le type du personnage (warrior, mage ou archer), puis lisez le nom, la santé et les statistiques propres à son type. Créez le personnage approprié.

    Lisez ensuite le nombre d’actions. Chaque action est l’une des suivantes :

    • status : affiche l’état du personnage
    • attack : affiche [Name] attacks for [damage] damage
    • defend [amount] : applique les dégâts et affiche [Name] takes [actual] damage
    • setability [type] [power] : pour les mages uniquement, définit la capacité (type : fire, ice ou strike)
    • useability : pour les mages uniquement, affiche le résultat de Use() de la capacité

Les entrées suivantes seront fournies :

  • Le type, le nom, la santé et les statistiques propres au type du personnage
  • Le nombre d’actions, puis chaque action sur une ligne distincte

Par exemple, avec :

warrior
Thorin
100
15
8
5
status
attack
defend 20
status
defend 100

Votre sortie doit être :

Thorin: 100/100 HP
Thorin attacks for 15 damage
Thorin takes 12 damage
Thorin: 88/100 HP
Thorin takes 92 damage

Et avec :

mage
Gandalf
80
25
10
6
attack
useability
setability fire 30
useability
setability ice 25
useability
defend 40

Votre sortie doit être :

Gandalf attacks for 50 damage
No ability set
Casts fireball for 30 damage
Casts ice shard for 25 damage
Gandalf takes 35 damage

Et avec :

archer
Legolas
90
18
15
4
status
attack
defend 24
status

Votre sortie doit être :

Legolas: 90/90 HP
Legolas attacks for 23 damage
Legolas takes 18 damage
Legolas: 72/90 HP

Remarquez comment l’intégration de structures permet à chaque type de personnage de partager les champs et les méthodes de base de Character, tandis que les interfaces permettent un combat polymorphe où tout Attacker peut infliger des dégâts et tout Defender peut en subir. Le modèle Strategy se révèle particulièrement utile avec les capacités interchangeables du Mage : le même personnage peut utiliser différents sorts sans modifier son implémentation principale !

Essayez vous-même

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)

	// Lire le type de personnage
	scanner.Scan()
	charType := strings.TrimSpace(scanner.Text())

	// Lire le nom du personnage
	scanner.Scan()
	name := strings.TrimSpace(scanner.Text())

	// Lire la santé
	scanner.Scan()
	health, _ := strconv.Atoi(strings.TrimSpace(scanner.Text()))

	// Lire la première statistique spécifique au type
	scanner.Scan()
	stat1, _ := strconv.Atoi(strings.TrimSpace(scanner.Text()))

	// Lire la deuxième statistique spécifique au type
	scanner.Scan()
	stat2, _ := strconv.Atoi(strings.TrimSpace(scanner.Text()))

	// TODO: Créer le personnage approprié en fonction de charType
	// Utiliser les variables : charType, name, health, stat1, stat2
	// Pour warrior : stat1 = Strength, stat2 = Armor
	// Pour mage : stat1 = Intelligence, stat2 = MagicResist
	// Pour archer : stat1 = Agility, stat2 = Evasion

	// Lire le nombre d'actions
	scanner.Scan()
	numActions, _ := strconv.Atoi(strings.TrimSpace(scanner.Text()))

	// Traiter chaque action
	for i := 0; i < numActions; i++ {
		scanner.Scan()
		line := strings.TrimSpace(scanner.Text())
		parts := strings.Fields(line)
		action := parts[0]

		// TODO: Gérer chaque type d'action :
		// - "status": afficher le Status() du personnage
		// - "attack": afficher "[Name] attacks for [damage] damage"
		// - "defend [amount]": appliquer les dégâts et afficher "[Name] takes [actual] damage"
		// - "setability [type] [power]": pour les mages, définir la capacité (fire, ice, or strike)
		// - "useability": pour les mages, afficher le résultat de UseAbility()

		_ = action // Supprimer cette ligne lors de l'implémentation
		_ = fmt.Println // Supprimer cette ligne lors de l'implémentation
	}
}

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur Go en ligne