Menu
Coddy logo textTech

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

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

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

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

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

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

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

challenge icon

Задание

Легко

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

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

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

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

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
        //   Print: "[name] the Warrior joins the battle!"
        // 
        // - CREATE_MAGE:name:maxHealth:level:intelligence:mana
        //   Print: "[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: After all commands, print "--- Battle Summary ---"
        // Затем вывести статус каждого персонажа
    }
}
quiz iconПроверьте себя

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

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

Потренируйтесь самостоятельно: Онлайн-компилятор Java