게임 캐릭터 개발
Coddy Java 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 87개 중 86번째.
이 챌린지에서는 복잡하고 상호작용하는 엔티티를 모델링하는 데 있어 OOP의 강력함을 보여주는 게임 캐릭터 개발 시스템을 구축하게 됩니다.
기본 Character 클래스가 health, name, level과 같은 공통 속성을 정의하는 캐릭터 계층 구조를 설계하세요. Warrior, Mage, Archer와 같은 특화된 클래스들은 고유한 능력과 전투 스타일로 이 기본 클래스를 확장합니다.
인터페이스는 여기서 자연스럽게 작동합니다: Attackable은 전투 메서드를 정의할 수 있고, Healable은 회복 능력을 처리합니다. Mage는 두 가지를 모두 구현할 수 있는 반면, Warrior는 공격에만 집중합니다.
다양한 공격 행동을 위해 전략 패턴(Strategy pattern)을 사용하는 것을 고려해 보세요. 이를 통해 캐릭터가 전투 스타일을 동적으로 전환할 수 있습니다. 상태 패턴(State pattern)은 행동에 영향을 미치는 정상, 독, 또는 기절 상태와 같은 캐릭터의 상태를 관리할 수 있습니다.
캐릭터가 무기와 방어구를 상속받는 대신 "가지는" 장비 시스템을 위한 컴포지션(composition)에 대해 생각해 보세요. 캐릭터 클래스나 데미지 유형에는 열거형(enums)을 사용하고, 유효하지 않은 수정으로부터 스탯을 보호하기 위해 캡슐화(encapsulation)를 적용하세요.
챌린지
쉬움복잡하고 상호작용하는 게임 엔티티를 모델링하는 데 있어 OOP의 강력함을 보여주는 게임 캐릭터 개발 시스템을 구축해 봅시다! 다양한 전투 스타일, 특수 능력, 그리고 캐릭터의 행동에 영향을 미치는 상태 시스템을 갖춘 캐릭터 계층 구조를 만들게 됩니다.
코드는 다음 일곱 개의 파일로 구성됩니다:
DamageType.java: 게임 내 다양한 데미지 유형을 나타내는 열거형(enum)을 생성합니다.PHYSICAL,MAGICAL,RANGED값을 포함하세요. 프라이빗 필드description(String), 이를 설정하는 생성자, 그리고 게터(getter)를 추가합니다. Physical 데미지는 "brute force", magical은 "arcane energy", ranged는 "precision strike"라는 설명을 가져야 합니다.Attackable.java: 전투 능력을 정의하는 인터페이스를 생성합니다. 공격을 설명하는 String을 반환하는attack(Character target)메서드와 DamageType을 반환하는getDamageType()메서드를 선언합니다.Healable.java: 회복 능력을 위한 인터페이스를 생성합니다. 치유 행동을 설명하는 String을 반환하는heal(int amount)메서드를 선언합니다.Character.java: 모든 게임 캐릭터의 추상 기본 클래스를 생성합니다.name(String),health(int),maxHealth(int),level(int)를 위한 프라이빗 필드를 포함합니다. 생성자는 name, maxHealth, level을 매개변수로 받아 health를 초기 maxHealth와 동일하게 설정합니다. 모든 필드에 대한 게터를 포함합니다. health가 0과 maxHealth 사이를 유지하도록 보장하는 프로텍티드(protected) 메서드setHealth(int health)를 추가합니다. health를 감소시키고"[name] takes [damage] damage! Health: [health]/[maxHealth]"를 반환하는takeDamage(int damage)메서드를 만듭니다. health가 0보다 크면 true를 반환하는isAlive()메서드를 추가합니다. String을 반환하는 추상 메서드getCharacterClass()를 선언합니다.Warrior.java: Character를 상속받고 Attackable을 구현하는 클래스를 생성합니다. 프라이빗 필드strength(int)를 추가합니다. 생성자는 name, maxHealth, level, strength를 매개변수로 받습니다.getCharacterClass()가"Warrior"를 반환하도록 구현합니다.getDamageType()이PHYSICAL을 반환하도록 구현합니다.attack(Character target)은 strength에 level을 더한 만큼의 데미지를 입히고, 타겟의 takeDamage 메서드를 호출한 뒤,"[name] strikes with [damageType description] for [damage] damage!"와 줄바꿈 문자, 그리고 takeDamage 결과가 이어지는 문자열을 반환하도록 구현합니다.Mage.java: Character를 상속받고 Attackable과 Healable을 모두 구현하는 클래스를 생성합니다. 프라이빗 필드intelligence(int)와mana(int)를 추가합니다. 생성자는 name, maxHealth, level, intelligence, mana를 매개변수로 받습니다.getCharacterClass()가"Mage"를 반환하도록 구현합니다.getDamageType()이MAGICAL을 반환하도록 구현합니다.attack(Character target)은 intelligence의 2배에 해당하는 데미지를 입히며, Warrior와 동일한 형식을 따릅니다.heal(int amount)는 (setHealth를 사용하여) 체력을 회복하고"[name] channels healing magic! Health: [health]/[maxHealth]"를 반환하도록 구현합니다.Main.java: 게임 시스템에 생명력을 불어넣으세요! 쉼표로 구분된 명령 문자열을 받게 됩니다:CREATE_WARRIOR:name:maxHealth:level:strengthCREATE_MAGE:name:maxHealth:level:intelligence:manaATTACK:attackerName:targetNameHEAL:mageName:amountSTATUS:characterName
캐릭터 컬렉션을 유지 관리합니다. 각 명령을 처리하고 다음을 출력합니다:
- CREATE_WARRIOR/CREATE_MAGE:
[name] the [characterClass] joins the battle! - ATTACK: 공격 결과(attack 메서드에서 반환된 String)를 출력합니다.
- HEAL: 치유 결과를 출력하거나, 캐릭터가 Mage가 아닌 경우
[name] cannot heal을 출력합니다. - STATUS:
[name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]
모든 명령이 끝나면
--- Battle Summary ---를 출력하고 각 캐릭터의 상태를 출력합니다.
입력으로 쉼표로 구분된 명령 문자열 하나를 받게 됩니다.
예를 들어, 입력이 CREATE_WARRIOR:Thorin:100:5:15,CREATE_MAGE:Gandalf:80:7:12:50,ATTACK:Thorin:Gandalf,HEAL:Gandalf:25,STATUS:Gandalf인 경우, 출력은 다음과 같습니다:
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이 챌린지는 상속(Character 계층 구조), 다중 인터페이스 구현(Mage는 Attackable과 Healable을 모두 구현), 메서드가 있는 열거형(DamageType), 다형성(다양한 캐릭터 유형을 균일하게 처리), 캡슐화(protected 체력 관리)를 매력적인 게임 시스템으로 결합합니다!
치트 시트
객체 지향 프로그래밍(OOP)은 클래스, 상속, 인터페이스 및 디자인 패턴을 통해 복잡한 시스템을 모델링할 수 있게 해줍니다.
클래스 계층 구조
공통 속성을 가진 기본 클래스를 생성하고 이를 특수화된 클래스로 확장합니다:
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();
}인터페이스
클래스가 구현할 수 있는 특정 동작에 대한 계약을 정의합니다:
public interface Attackable {
String attack(Character target);
DamageType getDamageType();
}
public interface Healable {
String heal(int amount);
}필드가 있는 열거형(Enums)
열거형은 필드, 생성자 및 메서드를 가질 수 있습니다:
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;
}
}다중 인터페이스 구현
클래스는 여러 인터페이스를 구현할 수 있습니다:
public class Mage extends Character implements Attackable, Healable {
private int intelligence;
private int mana;
@Override
public String attack(Character target) {
// 구현
}
@Override
public String heal(int amount) {
// 구현
}
}캡슐화
접근을 제어하고 데이터를 검증하기 위해 protected 세터(setter)와 함께 private 필드를 사용합니다:
protected void setHealth(int health) {
this.health = Math.max(0, Math.min(health, maxHealth));
}다형성
공통 기본 클래스 또는 인터페이스를 통해 서로 다른 캐릭터 유형을 균일하게 처리하여 유연한 컬렉션 및 메서드 호출을 가능하게 합니다.
직접 해보기
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: 캐릭터를 관리하기 위해 컬렉션을 사용하세요 (LinkedHashMap은 삽입 순서를 유지합니다)
// LinkedHashMap<String, Character> characters = new LinkedHashMap<>();
// TODO: 개별 명령을 얻기 위해 입력을 쉼표로 분할하세요
// String[] commands = input.split(",");
// TODO: 각 명령을 처리하세요:
// - CREATE_WARRIOR:name:maxHealth:level:strength
// 출력: "[name] the Warrior joins the battle!"
//
// - CREATE_MAGE:name:maxHealth:level:intelligence:mana
// 출력: "[name] the Mage joins the battle!"
//
// - ATTACK:attackerName:targetName
// attack 메서드로부터의 공격 결과를 출력하세요
//
// - HEAL:mageName:amount
// 치유 결과를 출력하거나, Mage가 아닌 경우 "[name] cannot heal"을 출력하세요
//
// - STATUS:characterName
// 출력: "[name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]"
// TODO: 모든 명령이 끝난 후, "--- Battle Summary ---"를 출력하세요
// 그런 다음 각 캐릭터의 상태를 출력하세요
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
4상속
상속의 기초 (extends)super 키워드메서드 오버라이딩 (@Override)생성자 체이닝Object 클래스단일 및 다중 레벨 상속다중 클래스 상속이 불가능한 이유요약 - 직원 계층 구조