Menu
Coddy logo textTech

게임 캐릭터 개발

Coddy PHP 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 91개 중 90번째.

challenge icon

챌린지

쉬움

고유한 능력을 사용해 서로 다른 캐릭터 클래스가 전투하는 Game Character Development 시스템을 만들어 봅시다. 상속, 인터페이스, 트레이트, 캡슐화가 게임 맥락에서 어떻게 함께 작동하는지 보여 주는 경험치 및 레벨 시스템을 갖춘 캐릭터 계층 구조를 만들게 됩니다.

코드를 여섯 개의 파일로 구성합니다:

  • Ability.php: 두 메서드인 getName(): stringuse(Character $target): string을 포함하는 Ability 인터페이스를 Define합니다. 이 계약을 통해 각 능력의 구체적인 효과와 관계없이 모든 능력을 일관되게 사용할 수 있습니다.
  • CombatLogger.php: logAction(string $action): string 메서드를 제공하는 CombatLogger 트레이트를 Create합니다. 이 메서드는 "[COMBAT] "을 앞에 붙인 action 문자열을 반환해야 합니다. 캐릭터는 이 트레이트를 사용해 전투 메시지의 형식을 일관되게 지정합니다.
  • Character.php: Ability 및 CombatLogger 파일을 포함합니다. CombatLogger 트레이트를 사용하는 abstract Character 클래스를 Create합니다. name에 대해 생성자 프로모션(string, public readonly)을 사용합니다. health(int, 100에서 시작), level(int, 1에서 시작), experience(int, 0에서 시작)를 위한 private 속성을 포함합니다. 다음을 구현합니다:
    • getHealth(): intgetLevel(): int: private 속성을 위한 getter
    • takeDamage(int $amount): void: health를 감소시키지만 0보다 낮아지지 않도록 함
    • heal(int $amount): void: health를 증가시키지만 100보다 높아지지 않도록 함
    • gainExperience(int $xp): string: XP를 추가합니다. experience가 100 이상에 도달하면 레벨을 올리고(XP를 0으로 재설정하고, level을 증가시키며, HP를 20 회복), "[name] leveled up to [level]!"을 반환합니다. 그렇지 않으면 "[name] gained [xp] XP"를 반환합니다.
    • isAlive(): bool: health가 0보다 크면 true를 반환함
    • abstract getSpecialAbility(): Ability: 각 캐릭터 유형이 고유한 능력을 제공함
    • attack(Character $target): string: target에게 10 damage를 입히고, logAction()을 사용해 "[COMBAT] [name] attacks [target name] for 10 damage"를 반환함
  • Warrior.php: Character 파일을 포함합니다. Character를 extending하는 Warrior 클래스를 Create합니다. Ability를 구현하는 anonymous 클래스를 반환하도록 getSpecialAbility()를 구현합니다:
    • getName()"Shield Bash"를 반환함
    • use()는 25 damage를 입히고 "[COMBAT] Shield Bash hits [target name] for 25 damage!"을 반환함 (트레이트의 logAction()을 사용)
  • Mage.php: Character 파일을 포함합니다. Character를 extending하는 Mage 클래스를 Create합니다. Ability를 구현하는 anonymous 클래스를 반환하도록 getSpecialAbility()를 구현합니다:
    • getName()"Fireball"을 반환함
    • use()는 35 damage를 입히고 "[COMBAT] Fireball engulfs [target name] for 35 damage!"을 반환함
  • main.php: Warrior 및 Mage 파일을 포함합니다. 두 개의 입력, 즉 캐릭터 데이터(JSON)와 일련의 전투 action(JSON)을 받습니다.

    Characters JSON 형식:

    [{"type": "warrior", "name": "Thorin"}, {"type": "mage", "name": "Gandalf"}]

    Actions JSON 형식:

    [{"action": "attack", "attacker": 0, "target": 1}, {"action": "special", "attacker": 1, "target": 0}, {"action": "xp", "character": 0, "amount": 100}, {"action": "status", "character": 0}]

    모든 캐릭터를 Create하고 array에 저장합니다(index 0, 1 등). 각 action을 Process합니다:

    • "attack": attacker index의 Character가 target을 공격하고 결과를 출력함
    • "special": Character가 target에게 자신의 special ability를 사용하고 결과를 출력함
    • "xp": Character가 experience를 얻고 결과를 출력함
    • "heal": Character가 지정된 amount만큼 회복하고 "[name] healed to [health] HP"를 출력함
    • "status": "[name] - Level [level], HP: [health], Alive: [Yes/No]"를 출력함

    각 결과를 새 줄에 출력합니다.

이 시스템은 abstract 클래스가 공유되는 캐릭터 동작을 정의하고, 인터페이스가 능력이 일관된 계약을 따르도록 보장하며, 트레이트가 재사용 가능한 로깅 기능을 제공하고, anonymous 클래스가 한 번만 사용하는 클래스로 코드베이스를 복잡하게 만들지 않고 고유한 능력 구현을 Create하는 방식을 보여 줍니다.

직접 해보기

<?php
require_once 'Warrior.php';
require_once 'Mage.php';

// 입력 읽기
$charactersJson = trim(fgets(STDIN));
$actionsJson = trim(fgets(STDIN));

// JSON 입력 파싱
$charactersData = (array)json_decode($charactersJson, true);
$actionsData = (array)json_decode($actionsJson, true);

// TODO: 캐릭터 객체를 저장할 배열 생성
$characters = [];

// TODO: $charactersData를 순회하며 Warrior 또는 Mage 객체 생성
// "type" 필드를 기반으로 $characters 배열에 저장

// TODO: $actionsData의 각 액션 처리
// 다음 액션 유형 처리:
// - "attack": attacker 인덱스의 캐릭터가 target을 공격; 결과 출력
// - "special": 캐릭터가 target에 getSpecialAbility()->use() 사용; 결과 출력
// - "xp": 캐릭터가 경험치 획득; 결과 출력
// - "heal": 캐릭터 회복; "[name] healed to [health] HP" 출력
// - "status": "[name] - Level [level], HP: [health], Alive: [Yes/No]" 출력

?>

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 PHP 컴파일러