게임 캐릭터 개발
Coddy Python 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 64개 중 63번째.
챌린지
중급이 챌린지에서는 포괄적인 테스트 커버리지를 갖춘 멀티 파일 RPG 캐릭터 시스템을 구현합니다.
character.py- 기본Character클래스 구현warrior.py-Warrior서브클래스 구현mage.py-Mage서브클래스 구현rogue.py-Rogue서브클래스 구현ability.py-Ability클래스 구현
각 파일에는 구현을 안내하는 상세한 TODO 주석이 포함되어 있습니다. 코드가 모든 요구 사항을 충족하도록 이 주석들을 따라 구현하세요.
직접 해보기
from character import Character
from warrior import Warrior
from mage import Mage
from rogue import Rogue
from ability import Ability
# 모든 시나리오와 예외 케이스를 다루는 종합 테스트 케이스 핸들러
test_case = input()
if test_case == "character_creation":
# 다양한 캐릭터 클래스 생성 테스트
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":
# 다양한 클래스의 레벨업 테스트
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":
# 기본 전투 메커니즘 테스트
warrior = Warrior("Aragorn", 5)
enemy = Character("Orc", 3)
print(f"Initial HP - {warrior.name}: {warrior.health}, {enemy.name}: {enemy.health}")
# 전사가 적을 공격
warrior.attack(enemy)
print(f"After warrior attack - Enemy HP: {enemy.health}")
# 적이 반격
enemy.attack(warrior)
print(f"After enemy attack - Warrior HP: {warrior.health}")
# 생존 여부 확인
print(f"Is warrior alive? {warrior.is_alive()}")
print(f"Is enemy alive? {enemy.is_alive()}")
elif test_case == "class_specific_attacks":
# 클래스별 공격 구현 테스트
warrior = Warrior("Aragorn", 5)
mage = Mage("Gandalf", 5)
rogue = Rogue("Legolas", 5)
target = Character("Training Dummy", 10)
target.defense = 0 # 순수 데미지 비교를 위해 방어력 제거
# 공격 사이에 대상의 체력 초기화
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}")
# 마법사 마나 재생 확인
initial_mana = mage.mana
mage.attack(target)
print(f"Mage mana before attack: {initial_mana}, after attack: {mage.mana}")
elif test_case == "abilities":
# 스킬 시스템 테스트
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
# 마법사 스킬 사용 테스트
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
# 전사 스킬 사용 테스트
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}")
# 마나 부족 테스트
mage.mana = 0
mage.use_ability(0, target)
elif test_case == "damage_calculation":
# 방어력이 포함된 데미지 계산 테스트
warrior = Warrior("Aragorn", 5)
low_defense = Character("Goblin", 3)
low_defense.defense = 2
high_defense = Character("Armored Knight", 3)
high_defense.defense = 15
# 낮은 방어력 공격
damage_to_low = warrior.attack(low_defense)
# 높은 방어력 공격
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}")
# 최소 데미지 규칙 테스트
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":
# 캐릭터 간의 전체 전투 테스트
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} ---")
# 전사의 턴
if round_num % 3 == 0 and warrior.mana >= cleave.mana_cost:
warrior.use_ability(0, mage)
else:
warrior.attack(mage)
# 마법사 패배 여부 확인
if not mage.is_alive():
print(f"{mage.name} has been defeated!")
break
# 마법사의 턴
if mage.mana >= fireball.mana_cost:
mage.use_ability(0, warrior)
else:
mage.attack(warrior)
# 전사 패배 여부 확인
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
# 무한 루프 방지를 위한 제한
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":
# 종합 상속 검증
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":
# 메서드 오버라이딩 동작 테스트
print('Testing method overriding...')
# 인스턴스 생성 및 오버라이딩된 메서드 테스트
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":
# 속성 접근 테스트
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":
# 경계 조건 및 극단값 테스트
print('Testing boundary conditions...')
# 체력이 0인 캐릭터 테스트
char = Character("Test", 1)
char.health = 0
print(f"Character at 0 HP is alive: {char.is_alive()}")
# 체력이 1인 캐릭터 테스트
char2 = Character("Test2", 1)
char2.health = 1
print(f"Character at 1 HP is alive: {char2.is_alive()}")
# 잘못된 스킬 인덱스 테스트 (음수)
warrior = Warrior("Test", 1)
result = warrior.use_ability(-1, char)
print(f"Invalid negative ability index returns: {result}")
# 잘못된 스킬 인덱스 테스트 (너무 높음)
result = warrior.use_ability(999, char)
print(f"Invalid high ability index returns: {result}")
# 매우 높은 방어력에 대한 최소 데미지(1) 테스트
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":
# 에러 핸들링 및 예외 시나리오 테스트
print('Testing error handling...')
# 마나가 부족한 상태에서 스킬 사용 테스트
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}")
# 배운 스킬이 없는 상태에서 스킬 사용 테스트
warrior = Warrior("TestWarrior", 1)
result = warrior.use_ability(0, target)
print(f"Using non-existent ability returns: {result}")
# 체력이 음수로 내려가지 않는지 테스트
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":
# 혼합 객체를 사용한 다형성 동작 테스트
print('Testing polymorphic behavior...')
# 다양한 캐릭터 타입 리스트 생성
characters = [
Character("Generic", 1),
Warrior("WarriorTest", 1),
Mage("MageTest", 1),
Rogue("RogueTest", 1)
]
# 모든 객체가 Character로 취급될 수 있는지 테스트
for char in characters:
print(f"{char.name}: Type={type(char).__name__}, IsAlive={char.is_alive()}")
# 다형성 메서드 호출 테스트
target = Character("Target", 10)
target.health = 1000 # 생존을 위해 높은 체력 설정
for char in characters:
damage = char.attack(target)
print('Polymorphic behavior test completed')
elif test_case == "stress_test":
# 다수의 객체를 사용한 부하 테스트
import time
start_time = time.time()
objects = []
for i in range(50):
try:
objects.append(Character(f'test_{i}'))
except:
pass # 생성 에러를 부드럽게 처리
try:
objects.append(Warrior(f'test_{i}'))
except:
pass # 생성 에러를 부드럽게 처리
try:
objects.append(Mage(f'test_{i}'))
except:
pass # 생성 에러를 부드럽게 처리
try:
objects.append(Rogue(f'test_{i}'))
except:
pass # 생성 에러를 부드럽게 처리
try:
objects.append(Ability(f'test_{i}', 10, 20))
except:
pass # 생성 에러를 부드럽게 처리
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":
# 종합 검증 테스트
print('=== Comprehensive Validation Test ===')
# 테스트 1: 기본 객체 생성
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 ===')