Разработка игрового персонажа
Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy. Урок 86 из 87.
В этом задании тебе предстоит создать систему развития игрового персонажа, которая демонстрирует возможности ООП в моделировании сложных интерактивных сущностей.
Спроектируйте иерархию персонажей, где базовый класс Character определяет общие атрибуты, такие как здоровье, имя и уровень. Специализированные классы, такие как Warrior, Mage и Archer, расширяют этот базовый класс уникальными способностями и стилями боя.
Интерфейсы здесь подходят естественным образом: Attackable может определять методы боя, тогда как Healable отвечает за способности восстановления. Mage может реализовывать оба интерфейса, тогда как Warrior сосредотачивается только на атаке.
Рассмотрите возможность использования паттерна Strategy для разных вариантов поведения при атаке, позволяя персонажам динамически переключать стили боя. Паттерн State может управлять состояниями персонажа, такими как обычное состояние, отравление или оглушение, которые влияют на поведение.
Подумайте о композиции для систем экипировки, в которых characters «имеют» оружие и броню, а не наследуются от них. Используйте перечисления для class characters или типов урона и применяйте инкапсуляцию, чтобы защитить характеристики от недопустимых изменений.
Задание
ЛегкоДавайте создадим систему развития игровых персонажей, демонстрирующую возможности ООП при моделировании сложных интерактивных игровых сущностей! Вы создадите иерархию персонажей с различными стилями боя, особыми способностями и системой состояний, влияющей на поведение персонажей.
Вы организуете код в семи файлах:
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:strengthCREATE_MAGE:name:maxHealth:level:intelligence:manaATTACK:attackerName:targetNameHEAL:mageName:amountSTATUS: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 ---"
// Затем вывести статус каждого персонажа
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово thisМетодыПоля (атрибуты)Метод-конструкторПерегрузка конструкторовИтоги — Простой калькулятор4Наследование
Основы наследования (extends)Ключевое слово superПереопределение методов (@Override)Цепочка конструкторовКласс ObjectОдиночное и многоуровневое наследованиеПочему нет множественного наследования классовИтоги — Иерархия сотрудников7Специальные методы и класс Object
Метод toString()equals() и hashCode()Метод clone()compareTo() и ComparableИнтерфейс ComparatorПовторение — Кастомная сортировка2Модификаторы доступа и инкапсуляция
Обзор уровней доступаМетоды геттеры и сеттерыСокрытие данныхКлючевое слово finalИтоги — Менеджер банковского счета5Полиморфизм
Основы перегрузки методовПереопределение методов (Run-Time)Upcasting и DowncastingОператор instanceofАбстрактные классы и методыИтоги: Калькулятор фигур8Продвинутые концепции ООП
Композиция против наследованияАгрегация против композицииВнутренние, вложенные и анонимные классыEnums и методы перечисленийRecords (Java 16+)Sealed-классы (Java 17+)11Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy14Финальные испытания
Платформа онлайн-обученияБанковская системаРазработка игрового персонажаСервис аренды транспорта3Свойства класса и статические члены
Переменные экземпляра и статические переменныеСтатические методыСтатические блокиКонстанты (static final)Итоги: Счетчик и утилиты6Интерфейсы и абстрактные классы
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовDefault и Static методы в интерфейсахАбстрактные классы vs ИнтерфейсыФункциональные интерфейсыИтоги — Платежная система9Обобщения
Введение в обобщенияОбобщенные классыОбобщенные методыОграниченные параметры типаСимволы подстановки (Wildcards: ?, extends, super)Итоги — Обобщенный контейнер12Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»Паттерн «Итератор»Потренируйтесь самостоятельно: Онлайн-компилятор Java