Développement de personnages de jeu
Fait partie de la section Object Oriented Programming du Journey Python de Coddy — leçon 63 sur 64.
Défi
MoyenDans ce défi, vous allez implémenter un système de personnages de RPG multi-fichiers avec une couverture de test complète.
character.py- Implémentez la classe de base Characterwarrior.py- Implémentez la sous-classe Warriormage.py- Implémentez la sous-classe Magerogue.py- Implémentez la sous-classe Rogueability.py- Implémentez la classe Ability
Chaque fichier contient des commentaires TODO détaillés guidant votre implémentation. Suivez ces commentaires pour vous assurer que votre code répond à toutes les exigences.
Essayez vous-même
from character import Character
from warrior import Warrior
from mage import Mage
from rogue import Rogue
from ability import Ability
# Gestionnaire de cas de test complet couvrant tous les scénarios et cas limites
test_case = input()
if test_case == "character_creation":
# Test de la création de différentes classes de personnages
warrior = Warrior("Aragorn", 1)
mage = Mage("Gandalf", 1)
rogue = Rogue("Legolas", 1)
print(f"Warrior: {warrior.name}, HP: {warrior.health}, Mana: {warrior.mana}, Str: {warrior.strength}")
print(f"Mage: {mage.name}, HP: {mage.health}, Mana: {mage.mana}, Int: {mage.intelligence}")
print(f"Rogue: {rogue.name}, HP: {rogue.health}, Mana: {rogue.mana}, Agi: {rogue.agility}")
elif test_case == "character_levelup":
# Test de la montée de niveau pour différentes classes
warrior = Warrior("Aragorn")
mage = Mage("Gandalf")
rogue = Rogue("Legolas")
print("Before level up:")
print(f"Warrior - Level: {warrior.level}, HP: {warrior.max_health}, Str: {warrior.strength}")
print(f"Mage - Level: {mage.level}, Mana: {mage.max_mana}, Int: {mage.intelligence}")
print(f"Rogue - Level: {rogue.level}, Agi: {rogue.agility}")
warrior.level_up()
mage.level_up()
rogue.level_up()
print("\nAfter level up:")
print(f"Warrior - Level: {warrior.level}, HP: {warrior.max_health}, Str: {warrior.strength}")
print(f"Mage - Level: {mage.level}, Mana: {mage.max_mana}, Int: {mage.intelligence}")
print(f"Rogue - Level: {rogue.level}, Agi: {rogue.agility}")
elif test_case == "combat_basic":
# Test des mécaniques de combat de base
warrior = Warrior("Aragorn", 5)
enemy = Character("Orc", 3)
print(f"Initial HP - {warrior.name}: {warrior.health}, {enemy.name}: {enemy.health}")
# Le guerrier attaque l'ennemi
warrior.attack(enemy)
print(f"After warrior attack - Enemy HP: {enemy.health}")
# L'ennemi riposte
enemy.attack(warrior)
print(f"After enemy attack - Warrior HP: {warrior.health}")
# Vérifier s'ils sont en vie
print(f"Is warrior alive? {warrior.is_alive()}")
print(f"Is enemy alive? {enemy.is_alive()}")
elif test_case == "class_specific_attacks":
# Test des implémentations d'attaque spécifiques aux classes
warrior = Warrior("Aragorn", 5)
mage = Mage("Gandalf", 5)
rogue = Rogue("Legolas", 5)
target = Character("Training Dummy", 10)
target.defense = 0 # Supprimer la défense pour une comparaison nette des dégâts
# Réinitialiser la santé de la cible entre les attaques
initial_health = target.health
warrior.attack(target)
warrior_damage = initial_health - target.health
target.health = initial_health
mage.attack(target)
mage_damage = initial_health - target.health
target.health = initial_health
rogue.attack(target)
rogue_damage = initial_health - target.health
print(f"Warrior damage: {warrior_damage:.1f}")
print(f"Mage damage: {mage_damage:.1f}")
print(f"Rogue damage: {rogue_damage:.1f}")
# Vérifier la régénération de mana du mage
initial_mana = mage.mana
mage.attack(target)
print(f"Mage mana before attack: {initial_mana}, after attack: {mage.mana}")
elif test_case == "abilities":
# Test du système de capacités
fireball = Ability("Fireball", 30, 25)
slash = Ability("Slash", 15, 20)
mage = Mage("Gandalf", 3)
warrior = Warrior("Aragorn", 3)
mage.learn_ability(fireball)
warrior.learn_ability(slash)
target = Character("Orc", 5)
initial_health = target.health
# Test du mage utilisant une capacité
print(f"Mage mana before: {mage.mana}")
mage.use_ability(0, target)
print(f"Mage mana after: {mage.mana}")
print(f"Target health: {target.health}")
target.health = initial_health
# Test du guerrier utilisant une capacité
print(f"Warrior mana before: {warrior.mana}")
warrior.use_ability(0, target)
print(f"Warrior mana after: {warrior.mana}")
print(f"Target health: {target.health}")
# Test de mana insuffisant
mage.mana = 0
mage.use_ability(0, target)
elif test_case == "damage_calculation":
# Test du calcul des dégâts avec la défense
warrior = Warrior("Aragorn", 5)
low_defense = Character("Goblin", 3)
low_defense.defense = 2
high_defense = Character("Armored Knight", 3)
high_defense.defense = 15
# Attaque d'une cible à faible défense
damage_to_low = warrior.attack(low_defense)
# Attaque d'une cible à défense élevée
damage_to_high = warrior.attack(high_defense)
print(f"Damage to low defense target: {damage_to_low:.1f}")
print(f"Damage to high defense target: {damage_to_high:.1f}")
# Test de la règle des dégâts minimums
super_defense = Character("Impenetrable Shield", 1)
super_defense.defense = 100
damage_to_super = warrior.attack(super_defense)
print(f"Damage to extremely high defense: {damage_to_super:.1f}")
elif test_case == "full_battle_simulation":
# Test d'une simulation de combat complet entre personnages
warrior = Warrior("Aragorn", 5)
mage = Mage("Saruman", 5)
fireball = Ability("Fireball", 30, 40)
ice_spike = Ability("Ice Spike", 25, 35)
cleave = Ability("Cleave", 20, 30)
warrior.learn_ability(cleave)
mage.learn_ability(fireball)
mage.learn_ability(ice_spike)
print(f"Battle begins: {warrior.name} vs {mage.name}")
print(f"{warrior.name}: {warrior.health}/{warrior.max_health} HP, {warrior.mana}/{warrior.max_mana} Mana")
print(f"{mage.name}: {mage.health}/{mage.max_health} HP, {mage.mana}/{mage.max_mana} Mana")
round_num = 1
while warrior.is_alive() and mage.is_alive():
print(f"\n--- Round {round_num} ---")
# Tour du guerrier
if round_num % 3 == 0 and warrior.mana >= cleave.mana_cost:
warrior.use_ability(0, mage)
else:
warrior.attack(mage)
# Vérifier si le mage est vaincu
if not mage.is_alive():
print(f"{mage.name} has been defeated!")
break
# Tour du mage
if mage.mana >= fireball.mana_cost:
mage.use_ability(0, warrior)
else:
mage.attack(warrior)
# Vérifier si le guerrier est vaincu
if not warrior.is_alive():
print(f"{warrior.name} has been defeated!")
break
print(f"Status: {warrior.name} ({warrior.health:.1f} HP, {warrior.mana} Mana) | {mage.name} ({mage.health:.1f} HP, {mage.mana} Mana)")
round_num += 1
# Limite pour éviter les boucles infinies
if round_num > 10:
print("Battle exceeded 10 rounds and was called a draw.")
break
print("\nBattle Results:")
print(f"{warrior.name}: {warrior.health:.1f}/{warrior.max_health} HP remaining")
print(f"{mage.name}: {mage.health:.1f}/{mage.max_health} HP remaining")
if warrior.is_alive() and not mage.is_alive():
print(f"{warrior.name} wins!")
elif mage.is_alive() and not warrior.is_alive():
print(f"{mage.name} wins!")
else:
print("The battle ended in a draw!")
elif test_case == "inheritance_validation_test":
# Validation complète de l'héritage
objects = []
if 'Character' in locals():
objects.append(Character('test_param'))
if 'Warrior' in locals():
objects.append(Warrior('test_param'))
if 'Mage' in locals():
objects.append(Mage('test_param'))
if 'Rogue' in locals():
objects.append(Rogue('test_param'))
if 'Ability' in locals():
objects.append(Ability('test_param', 10, 20))
for obj in objects:
print(f'{type(obj).__name__}:')
print(f' MRO: {[cls.__name__ for cls in type(obj).__mro__]}')
print()
elif test_case == "method_overriding_test":
# Test du comportement de redéfinition de méthode (overriding)
print('Testing method overriding...')
# Créer des instances et tester les méthodes redéfinies
if 'Warrior' in locals():
obj = Warrior('test')
print(f'Warrior methods work correctly')
if 'Mage' in locals():
obj = Mage('test')
print(f'Mage methods work correctly')
if 'Rogue' in locals():
obj = Rogue('test')
print(f'Rogue methods work correctly')
elif test_case == "attribute_access_test":
# Test de l'accès aux attributs
print('Testing attribute access...')
if 'Character' in locals():
obj = Character('test')
print(f'Character attributes accessible')
if 'Warrior' in locals():
obj = Warrior('test')
print(f'Warrior attributes accessible')
if 'Mage' in locals():
obj = Mage('test')
print(f'Mage attributes accessible')
if 'Rogue' in locals():
obj = Rogue('test')
print(f'Rogue attributes accessible')
if 'Ability' in locals():
obj = Ability('test', 10, 20)
print(f'Ability attributes accessible')
elif test_case == "boundary_conditions_test":
# Test des conditions limites et des valeurs critiques
print('Testing boundary conditions...')
# Test d'un personnage à 0 de santé
char = Character("Test", 1)
char.health = 0
print(f"Character at 0 HP is alive: {char.is_alive()}")
# Test d'un personnage à 1 de santé
char2 = Character("Test2", 1)
char2.health = 1
print(f"Character at 1 HP is alive: {char2.is_alive()}")
# Test d'un index de capacité invalide (négatif)
warrior = Warrior("Test", 1)
result = warrior.use_ability(-1, char)
print(f"Invalid negative ability index returns: {result}")
# Test d'un index de capacité invalide (trop élevé)
result = warrior.use_ability(999, char)
print(f"Invalid high ability index returns: {result}")
# Test des dégâts minimums (1) contre une défense très élevée
attacker = Character("Attacker", 1)
defender = Character("Defender", 1)
defender.defense = 1000
initial_hp = defender.health
attacker.attack(defender)
damage = initial_hp - defender.health
print(f"Minimum damage dealt: {damage}")
print('Boundary conditions test completed')
elif test_case == "error_handling_test":
# Test de la gestion des erreurs et des scénarios d'exception
print('Testing error handling...')
# Test de l'utilisation d'une capacité avec mana insuffisant
mage = Mage("TestMage", 1)
ability = Ability("Expensive", 1000, 50)
mage.learn_ability(ability)
target = Character("Target", 1)
result = mage.use_ability(0, target)
print(f"Ability with insufficient mana returns: {result}")
# Test de l'utilisation d'une capacité sans aucune capacité apprise
warrior = Warrior("TestWarrior", 1)
result = warrior.use_ability(0, target)
print(f"Using non-existent ability returns: {result}")
# Test que la santé ne devient pas négative
char = Character("Test", 1)
char.take_damage(1000)
print(f"Health after massive damage: {char.health}")
print('Error handling test completed')
elif test_case == "polymorphic_behavior_test":
# Test du comportement polymorphe avec des objets mixtes
print('Testing polymorphic behavior...')
# Créer une liste de différents types de personnages
characters = [
Character("Generic", 1),
Warrior("WarriorTest", 1),
Mage("MageTest", 1),
Rogue("RogueTest", 1)
]
# Tester que tous peuvent être traités comme des Character
for char in characters:
print(f"{char.name}: Type={type(char).__name__}, IsAlive={char.is_alive()}")
# Test des appels de méthodes polymorphes
target = Character("Target", 10)
target.health = 1000 # Santé élevée pour survivre
for char in characters:
damage = char.attack(target)
print('Polymorphic behavior test completed')
elif test_case == "stress_test":
# Test de charge avec de multiples objets
import time
start_time = time.time()
objects = []
for i in range(50):
try:
objects.append(Character(f'test_{i}'))
except:
pass # Gérer les erreurs de création gracieusement
try:
objects.append(Warrior(f'test_{i}'))
except:
pass # Gérer les erreurs de création gracieusement
try:
objects.append(Mage(f'test_{i}'))
except:
pass # Gérer les erreurs de création gracieusement
try:
objects.append(Rogue(f'test_{i}'))
except:
pass # Gérer les erreurs de création gracieusement
try:
objects.append(Ability(f'test_{i}', 10, 20))
except:
pass # Gérer les erreurs de création gracieusement
end_time = time.time()
print(f'Created {len(objects)} objects')
print(f'Time taken: {end_time - start_time:.4f} seconds')
print('Stress test completed')
elif test_case == "comprehensive_validation":
# Test de validation complet
print('=== Comprehensive Validation Test ===')
# Test 1 : Création d'objets de base
print('1. Basic Object Creation:')
success_count = 0
classes = ['Character', 'Warrior', 'Mage', 'Rogue', 'Ability']
try:
obj = Character('test')
success_count += 1
print(f' Character: Created successfully')
except Exception as e:
print(f' Character: Creation failed - {e}')
try:
obj = Warrior('test')
success_count += 1
print(f' Warrior: Created successfully')
except Exception as e:
print(f' Warrior: Creation failed - {e}')
try:
obj = Mage('test')
success_count += 1
print(f' Mage: Created successfully')
except Exception as e:
print(f' Mage: Creation failed - {e}')
try:
obj = Rogue('test')
success_count += 1
print(f' Rogue: Created successfully')
except Exception as e:
print(f' Rogue: Creation failed - {e}')
try:
obj = Ability('test', 10, 20)
success_count += 1
print(f' Ability: Created successfully')
except Exception as e:
print(f' Ability: Creation failed - {e}')
print(f' Successfully created {success_count}/{len(classes)} classes')
print('=== Validation Complete ===')Toutes les leçons de Object Oriented Programming
1Les fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe paramètre selfMéthodesAttributsMéthode constructeur (__init__)Récapitulatif - Calculatrice simple4Héritage
Héritage de baseLa fonction super()Redéfinition de méthodeHéritage multipleOrdre de résolution des méthodesRécapitulatif - Hiérarchie des employés7Méthodes spéciales
Introduction aux méthodes magiquesSurcharge d'opérateursMéthodes magiques de conteneurRécapitulatif - Liste personnalisée10Patrons de conception, Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FactoryPatron ObserverPatron Strategy13Défis finaux
Plateforme d'e-learningSystème bancaireDéveloppement de personnages de jeuService de location de véhicules2Décorateurs
Introduction aux décorateursDécorateur de propriétéDécorateur de méthode statiqueDécorateur de méthode de classe5Polymorphisme
Retour sur la redéfinition de méthodeDuck TypingClasses et méthodes abstraitesConception d'interfacesRécapitulatif - Calculateur de formes8Concepts avancés de la POO
Composition vs HéritageMixinsMéthodes statiques et de classeDécorateurs de classeGestionnaires de contexte11Patrons de conception, Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode TemplatePatron ÉtatPatron Composite3Propriétés de classe
Variables d'instance vs variables de classeDécorateurs de propriétéAttributs privésRécapitulatif - Gestionnaire de compte bancaire