Menu
Coddy logo textTech

Разработка игрового персонажа

Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy — урок 86 из 87.

В этом испытании вам предстоит создать систему разработки игровых персонажей, которая демонстрирует возможности ООП в моделировании сложных интерактивных сущностей.

Спроектируйте иерархию персонажей, в которой базовый класс Character определяет общие атрибуты, такие как здоровье, имя и уровень. Специализированные классы, такие как Warrior, Mage и Archer, расширяют эту базу уникальными способностями и стилями боя.

Интерфейсы здесь работают естественным образом: Attackable может определять методы боя, в то время как Healable управляет способностями к восстановлению. Mage может реализовывать и то, и другое, в то время как Warrior сосредоточен только на атаке.

Рассмотрите возможность использования паттерна «Стратегия» (Strategy) для реализации различных типов поведения при атаке, что позволит персонажам динамически переключать стили боя. Паттерн «Состояние» (State) может управлять такими состояниями персонажа, как обычное, отравление или оглушение, которые влияют на его поведение.

Подумайте об использовании композиции для систем экипировки, где персонажи «имеют» оружие и броню, а не наследуют их. Используйте перечисления (enums) для классов персонажей или типов урона и применяйте инкапсуляцию для защиты характеристик от некорректных изменений.

challenge icon

Задание

Легко

Давайте создадим систему разработки игровых персонажей, которая продемонстрирует мощь ООП при моделировании сложных интерактивных игровых сущностей! Вы создадите иерархию персонажей с различными стилями боя, специальными способностями и системой состояний, которая влияет на поведение персонажей.

Вы организуете свой код в семи файлах:

  • DamageType.java: Создайте перечисление (enum), представляющее различные типы урона в игре. Включите значения PHYSICAL, MAGICAL и RANGED. Добавьте приватное поле description (String), конструктор, который его устанавливает, и геттер. Физический урон должен иметь описание "brute force", магический — "arcane energy", а дальнобойный — "precision strike".
  • Attackable.java: Создайте интерфейс, определяющий боевые возможности. Объявите методы attack(Character target), который возвращает String с описанием атаки, и getDamageType(), который возвращает DamageType.
  • Healable.java: Создайте интерфейс для способностей к исцелению. Объявите метод heal(int amount), который возвращает String с описанием действия исцеления.
  • Character.java: Создайте абстрактный базовый класс для всех игровых персонажей. Включите приватные поля для name (String), health (int), maxHealth (int) и level (int). Конструктор принимает name, maxHealth и level, изначально устанавливая health равным maxHealth. Включите геттеры для всех полей. Добавьте защищенный метод setHealth(int health), который гарантирует, что здоровье остается в пределах от 0 до maxHealth. Создайте метод takeDamage(int damage), который уменьшает здоровье и возвращает "[name] takes [damage] damage! Health: [health]/[maxHealth]". Добавьте метод isAlive(), возвращающий true, если здоровье больше 0. Объявите абстрактный метод getCharacterClass(), возвращающий String.
  • 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:strength
    • CREATE_MAGE:name:maxHealth:level:intelligence:mana
    • ATTACK:attackerName:targetName
    • HEAL:mageName:amount
    • STATUS:characterName

    Поддерживайте коллекцию персонажей. Обработайте каждую команду и выведите:

    • CREATE_WARRIOR/CREATE_MAGE: [name] the [characterClass] joins the battle!
    • ATTACK: Выведите результат атаки (строку, возвращаемую методом attack)
    • HEAL: Выведите результат исцеления или [name] cannot heal, если персонаж не является магом (Mage)
    • 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), полиморфизм (единообразная работа с различными типами персонажей) и инкапсуляцию (защищенное управление здоровьем) в увлекательную игровую систему!

Попробуйте сами

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
        //   Выведите результат исцеления или "[name] cannot heal", если это не Mage
        // 
        // - STATUS:characterName
        //   Выведите: "[name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]"
        
        // TODO: После всех команд выведите "--- Battle Summary ---"
        // Затем выведите статус каждого персонажа
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование