Введение
Иногда, когда хочется отдохнуть или проверить свои стратегические способности, нет ничего лучше старой доброй пошаговой RPG. Современные игры часто перегружены графикой и сложными механиками, но классические текстовые приложения остаются актуальными благодаря своей простоте и глубине. Решил создать консольную игру в жанре «гладиаторские бои» на языке Java, вдохновляясь такими проектами, как «Мечи и сандали».
Проблема: многие начинающие программисты сталкиваются со сложностью реализации даже простых игр из-за непонимания базовых принципов объектно-ориентированного программирования и обработки пользовательского ввода.
Актуальность: создание консольной RPG позволяет на практике изучить основы Java, ООП, управление состоянием игры и работу с пользователем, что является фундаментом для дальнейшего изучения более сложных технологий.
Цель: изучение языка Java и его особенностей
Задачи:
Изучить особенности языка Java
Изучить ООП в языке Java
Изучить функции в Java для ввода и вывода информации:
Разработатьархитектуруигры (классы Hero, Enemy, Weapon, Armor, Battle, Shop, Game).
Реализовать боевую систему: атака, защита с шансом уклонения, лечение зельем.
Создать магазин для улучшения характеристик и покупки снаряжения.
Обеспечить устойчивость программы к некорректному вводу пользователя.
1.Теоретическая часть
§1.1 Особенности языка программирования Java
В нашем мире очень сильно развиты IT технологии, и без языков программирования нынче никак не справится. На данный момент существует большое разнообразия разных языков, такие как C++, Java, JavaScript, C#, PHP, Pascal, C, Cobol, Basic, Go, Lua, F#, Ruby, Rust, но сегодня мы остановимся на отдельном языке под названием Java.
Java – один из самых популярных и востребованных языков программирования в мире. Он был создан Джеймсом Гослингом в компании Sun Microsystems в 1995 году и с тех пор прочно занял лидирующие позиции в корпоративной разработке, мобильных приложениях (Android) и серверных решениях. По данным индекса TIOBE (регулярно обновляемый рейтинг популярности языков), Java регулярно входит в тройку лидеров, уступая лишь Python и C. Этот успех обусловлен несколькими ключевыми особенностями.
Кроссплатформенность. Программа, написанная на Java, компилируется не в машинный код конкретного процессора, а в байт-код, который выполняется виртуальной машиной Java (JVM). JVM существует для всех основных операционных систем (Windows, macOS, Linux, Android и даже некоторые встраиваемые системы), поэтому одно и то же приложение может работать везде без изменений. Девиз Java – «Write once, run anywhere» (Напиши один раз, запускай где угодно). Для разработчика это означает значительную экономию времени, так как не нужно переписывать программу под каждую платформу.
Безопасность и надёжность. Java – язык со строгой типизацией: все переменные должны иметь объявленный тип, и компилятор проверяет совместимость типов. Это предотвращает множество ошибок на этапе написания кода. Кроме того, в Java есть автоматическое управление памятью – сборщик мусора (Garbage Collector). Он отслеживает объекты, которые больше не используются, и освобождает занимаемую ими память. Это избавляет разработчика от ручного выделения и освобождения памяти (как, например, в C или C++), уменьшая риск утечек памяти и ошибок с указателями.
Объектно-ориентированная модель. Java с самого начала создавался как «чистый» объектно-ориентированный язык. Всё в Java – это объекты (кроме примитивных типов, таких как int, boolean, double). Программа на Java состоит из классов, а классы могут наследовать друг друга, реализовывать интерфейсы, использовать полиморфизм и инкапсуляцию. Это позволяет создавать масштабируемые и легко поддерживаемые проекты.
Богатая стандартная библиотека. Java поставляется с огромным набором готовых классов и пакетов: для работы с файлами (java.io), сетевыми протоколами (java.net), многопоточностью (java.util.concurrent), графическим интерфейсом (javax.swing), коллекциями (java.util) и многим другим. Для консольных приложений наиболее важны классы Scanner (для ввода), Random (генерация случайных чисел), System.out (вывод).
Сообщество и экосистема. Вокруг Java сложилось одно из крупнейших сообществ разработчиков. Существуют тысячи библиотек и фреймворков: Spring для серверных приложений, Hibernate для работы с базами данных, JUnit для тестирования, Maven и Gradle для сборки проектов. Это значит, что для любой задачи можно найти готовое решение или хотя бы пример.
Выбор языка Java для своего проекта по следующим причинам:
Java идеально подходит для изучения основ ООП, так как язык не позволяет писать процедурный код без классов (в отличие от C++, где можно смешивать стили).
Для консольных приложений Java предоставляет удобные средства ввода-вывода (класс Scanner) и обработки исключений, что необходимо для надёжного взаимодействия с пользователем.
Стандартная библиотека включает класс Random для генерации случайных чисел, что нужно для случайного урона и уклонения.
Кроссплатформенность гарантирует, что моя игра будет работать на любом компьютере с установленной JVM.
Таким образом, Java – оптимальный выбор для учебного проекта по разработке консольной RPG.
§1.2 Объектно-ориентированное программирование (ООП): принципы и преимущества
Объектно-ориентированное программирование – это парадигма, в которой программа строится как совокупность взаимодействующих объектов, каждый из которых является экземпляром определённого класса. Основные принципы ООП: инкапсуляция, наследование, полиморфизм и абстракция. Рассмотрим их подробно и покажем, как они применяются в моём проекте.
Инкапсуляция – это сокрытие внутренних данных объекта и предоставление доступа к ним только через специальные методы (геттеры и сеттеры) или методы, реализующие поведение. В моём проекте все поля классов (например, health, strength, gold в классе Hero) объявлены как private. Для изменения состояния используются публичные методы, такие как takeDamage(), addGold(), heal(). Это защищает данные от некорректного изменения извне. Например, без инкапсуляции другой класс мог бы напрямую присвоить hero.health = -100, что сломало бы логику игры. Благодаря инкапсуляции мы можем добавить проверки: в takeDamage идет гарантирование, что здоровье не станет отрицательным, а в heal – что оно не превысит максимальное значение.
Наследование – механизм, позволяющий создать новый класс на основе существующего, добавив или переопределив его методы. В моём проекте наследование не используется, так как герой и враг имеют разный набор полей и поведения (у героя есть золото, оружие, броня, флаг защиты; у врага – только базовые характеристики). Объединение их через общего предка привело бы к ненужным полям. Однако в принципе, если бы потребовалось добавить несколько типов врагов с общими чертами, можно было бы создать абстрактный класс Character с методами takeDamage, isAlive, а Hero и Enemy унаследовали бы его.
Полиморфизм – способность объектов разных классов отвечать на одни и те же методы по-своему. В моём проекте полиморфизм не используется, но он легко вводится: если бы интерфейс Attackable был сделан с методом attack(), то и герой, и враг, и, например, босс могли бы иметь свою реализацию атаки.
Композиция – хотя формально композиция не входит в «четыре кита» ООП, она является важным принципом проектирования. Композиция означает, что объект содержит в себе другие объекты как свои части. В моём проекте класс Hero содержит ссылки на объекты Weapon и Armor. Это даёт множество преимуществ:
Герой может менять оружие и броню во время игры без пересоздания самого объекта. Достаточно вызвать hero.setWeapon(newWeapon).
Классы оружия и брони остаются независимыми и могут переиспользоваться (например, в магазине или у врагов).
Код становится более гибким и понятным. Если бы мы использовали наследование (Hero extends Weapon), то герой был бы жёстко привязан к одному оружию, и его смена требовала бы создания нового объекта героя с новым оружием, что неудобно.
Абстракция – выделение главных характеристик объекта и игнорирование второстепенных. В моей игре это выражается в разделении кода на логические слои: модели (данные), сервисы (логика) и управление. Например, класс Battle не знает, как устроены герой и враг внутри – он только вызывает их публичные методы (attack, takeDamage, isAlive). Это позволяет изменять внутреннюю реализацию героя (добавить новую характеристику или умение), не затрагивая код боя.
Использование этих принципов позволяет создать надёжную, расширяемую и понятную программу. В моём проекте сознательно сделан упор на инкапсуляцию и композицию, чтобы продемонстрировать их преимущества на конкретном примере.
§1.3 Консольный ввод-вывод в Java: класс Scanner и обработка исключений
Взаимодействие с пользователем в консольных приложениях на Java осуществляется через стандартные потоки: System.in (ввод), System.out (вывод), System.err (вывод ошибок). Для удобного чтения данных из System.in предназначен класс Scanner из пакета java.util. Он предоставляет методы для чтения различных типов: nextInt(), nextDouble(), nextLine(), nextBoolean() и другие.
Однако при работе с Scanner есть важные тонкости. Рассмотримтипичнуюошибку:
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
String s = sc.nextLine();
После вызова nextInt() в буфере остаётся символ перевода строки (\n), который был введён после числа. Следующий вызов nextLine() считывает этот символ и возвращает пустую строку. Чтобы избежать этого, после каждого nextInt() или nextDouble() нужно вызывать nextLine() для очистки буфера.
Более серьёзная проблема – исключения. Если пользователь вводит не число, а букву, метод nextInt() выбрасывает исключение InputMismatchException. Без обработки программа аварийно завершается. Существует два подхода к решению:
1.Использование try-catch. Мы оборачиваем вызов nextInt() в блок try, перехватываем InputMismatchException и обрабатываем ошибку. Однако при этом нужно быть осторожным, так как после исключения некорректные данные остаются в буфере, и их нужно очистить.
2.Упреждающая проверка с hasNextInt(). Перед вызовом nextInt() мы проверяем, есть ли в потоке целое число. Если нет, считываем ошибочную строку через nextLine() и повторяем запрос. Этот подход не требует try-catch и считается более чистым.
В проекте был выбран второй подход и создал универсальный метод readInt, который принимает минимальное и максимальное допустимое значение и возвращает гарантированно корректное число:
private static int readInt(Scanner scanner, int min, int max) {
while (true) {
if (scanner.hasNextInt()) {
int value = scanner.nextInt();
scanner.nextLine();
if (value >= min && value <= max) {
return value;
} else {
System.out.print("Введитечислоот " + min + " до " + max + ": ");
}
} else {
String input = scanner.nextLine();
System.out.print("Некорректныйввод. Введите число от " + min + " до " + max + ": ");
}
}
}
Этот метод используется во всех местах, где ожидается выбор пункта меню (в бою и в магазине). Он делает программу абсолютно устойчивой к любым действиям пользователя, что является важным требованием для любого приложения.
§1.4 Игровые механики RPG
Ролевые игры (Role-Playing Games, RPG) – жанр, в котором игрок управляет одним или несколькими персонажами, развивает их характеристики, выполняет задания и сражается с противниками. Ключевые элементы, которые использованы в проекте:
Персонаж (Character) – основная сущность, управляемая игроком. Он имеет атрибуты: здоровье (health), сила (strength), ловкость (agility), золото (gold). Также персонаж может иметь экипировку: оружие (weapon) увеличивает урон, броня (armor) уменьшает получаемый урон. В моей игре класс Hero отвечает за все эти данные.
Враг (Enemy) – противник, управляемый компьютером. Его характеристики растут с каждым боем, чтобы игра не становилась слишком лёгкой. В классических RPG враги обычно имеют более простую логику, чем герой, – чаще всего они просто атакуют. Это и реализовал было реализовано.
Боевая система (Combat system) – сердце любой RPG. В моей игре бой пошаговый: игрок выбирает действие, затем враг отвечает. Это даёт время на размышление и стратегическое планирование. Урон рассчитывается по формуле: урон = сила_атакующего + урон_оружия - защита_цели. Минимальный урон – 1, чтобы бой не мог затянуться бесконечно. Защита – важный элемент: игрок может выбрать режим защиты, который удваивает защиту брони и даёт 50% шанс полностью уклониться от удара. Это добавляет риск: защита может быть очень эффективной, а может и не сработать.
Лечение (Healing) – в моей игре доступно зелье, восстанавливающее 20% от максимального здоровья. Это ограниченный ресурс (можно использовать каждый ход), но в текущей реализации зелье бесконечно. В будущем можно добавить ограничение на количество зелий.
Прогрессия (Progression) – игрок получает золото за победу и может тратить его в магазине на улучшение силы или максимального здоровья, а также на покупку лучшего оружия и брони. Враги становятся сильнее с каждым боем: их здоровье, сила и урон линейно растут. Это классическая прогрессия, которая заставляет игрока постоянно улучшать своего героя.
Магазин (Shop) – место для обмена золота на улучшения. Реализовал простой текстовый интерфейс с выбором пунктов меню. Цены привязаны к характеристикам предметов: для оружия цена = урон ×5, для брони = защита ×5. Это упрощает балансировку.
Такие механики характерны для многих известных RPG, например, серии Final Fantasy, Dragon Quest, а также для отечественных игр «Космические рейнджеры» и «Мечи и сандали». Они проверены временем и понятны широкой аудитории.
2. Практическая часть
§2.1 Разработка архитектуры приложения: проектирование классов и их взаимодействие
Прежде чем писать код, была спроектирована архитектура программы. Основные требования: чистота кода, разделение ответственности, возможность легко добавлять новый функционал. В результате выделил следующие классы:
Weapon – хранит название и урон оружия. Неизменяемый объект (immutable), все поля final.
Armor – хранит название и защиту брони. Также неизменяемый.
Hero – модель игрока. Содержит поля: имя, текущее и максимальное здоровье, сила, золото, ссылки на текущее оружие и броню, флаг защиты. Методы: конструктор, геттеры/сеттеры, takeDamage, heal, isAlive, getDefense, attack(Enemy), showStats.
Enemy – модель врага. Содержит поля: имя, здоровье, сила, урон оружия, защита. Методы: конструктор, геттеры, takeDamage, isAlive, calculateBaseDamage.
Battle – статический класс с логикой боя. Один публичный метод fight(Hero, Enemy, Scanner), возвращающий boolean.
Shop – статический класс с логикой магазина. Публичныйметод visit(Hero, Scanner).
Game – управляющийкласс. Содержит static Scanner и static Random. Публичныйметод start() запускаетигровойцикл. Вспомогательныеметоды createHero, generateEnemy, readInt.
Main – точкавхода, содержиттолькометод main, вызывающий Game.start().
Все классы находятся в одном пакете, поэтому не нужно импортировать друг друга (кроме java.util.Scanner и java.util.Random). Такая структура соответствует принципу единственной ответственности (Single Responsibility Principle): каждый класс отвечает за одну задачу. Weapon и Armor – за хранение данных предметов, Hero и Enemy – за состояние персонажей, Battle – за логику боя, Shop – за логику магазина, Game – за игровой цикл, Main – за запуск.
Взаимодействие классов:
Game создаёт объект Hero через createHero и объекты Enemy через generateEnemy.
Game передаёт Hero, Enemy и Scanner в Battle.fight(). Battle вызываетметодыгерояиврага (attack, takeDamage, isAlive, getDefense).
После победы Game начисляет награду и, если игрок хочет, передаёт Hero и Scanner в Shop.visit(). Shop вызываетметодыгероя (addStrength, addGold, setWeapon, setArmor ит.д.).
Game также содержит метод readInt для безопасного ввода, который используется и в Battle, и в Shop (это нарушение чистоты, но для упрощения оставил его в Game, а Battle и Shop обращаются к нему как к публичному статическому методу).
Композиция: класс Hero содержит объекты Weapon и Armor. Это позволяет легко менять экипировку: достаточно присвоить новую ссылку. Например, в магазине: hero.setWeapon(new Weapon("Меч", 10)).
Инкапсуляция: все поля классов private. Доступ к ним осуществляется через геттеры и методы-действия. Например, здоровье изменяется только через takeDamage и heal, что гарантирует корректные значения.
Почему не использовано наследование? Как уже говорилось, герой и враг слишком разные. Общий предок Character имел бы поля health, strength, но у героя есть gold, weapon, armor, а у врага – damage (урон оружия) и defense. Если бы был создал общий предок, то врагу пришлось бы добавить ненужные поля gold, weapon и armor, а герою – damage и defense, что нелогично. Поэтому композиция и раздельные классы – лучшее решение.
§2.2 Реализация боевой системы: пошаговый режим, расчёт урона, защита и уклонение
Бой – центральная механика игры. Реализовал её в классе Battle со статическим методом fight. Рассмотрим ключевые части кода.
Ход игрока:
System.out.println("\nВашездоровье: " + hero.getHealth() + "/" + hero.getMaxHealth());
System.out.println("Здоровьеврага: " + enemy.getHealth());
System.out.print("Действие (1 - атака, 2 - защита, 3 - зелье): ");
int choice = Game.readInt(scanner, 1, 3); // безопасныйввод
hero.setDefending(false);
switch (choice) {
case 1:
hero.attack(enemy);
break;
case 2:
hero.setDefending(true);
System.out.println("Вывсталивзащитнуюстойку.");
break;
case 3:
int heal = hero.getMaxHealth() / 5;
hero.heal(heal);
System.out.println("Вы использовали зелье и восстановили " + heal + " здоровья.");
break;
}
if (!enemy.isAlive()) return true;
Ходврага:
boolean dodged = false;
if (hero.isDefending() && random.nextBoolean()) {
dodged = true;
System.out.println("Выувернулисьотатаки " + enemy.getName() + "!");
}
if (!dodged) {
int baseDamage = enemy.calculateBaseDamage();
double multiplier = 0.8 + 0.4 * random.nextDouble();
int damage = (int) (baseDamage * multiplier);
int defense = hero.getDefense();
damage -= defense;
if (damage < 1) damage = 1;
hero.takeDamage(damage);
System.out.println(enemy.getName() + " наносит " + damage + " урона.");
}
if (!hero.isAlive()) return false;
Объяснение важных решений:
Защита удваивается – если герой выбрал защиту, то getDefense() возвращает armor.getDefense() * 2. Это делает защиту осмысленной: даже если уклонение не сработало, урон всё равно снижается.
50% уклонения при защите – это добавляет элемент случайности, делая защиту рискованной, но потенциально очень выгодной.
Случайный множитель урона врага (0.8–1.2) – без этого враг наносил бы каждый раз одинаковый урон, что предсказуемо и скучно. Множитель делает бои динамичнее.
Минимальный урон 1 – гарантирует, что бой не может застрять в ситуации, когда урон становится нулевым (например, защита превышает атаку).
Почему враг не защищается и не лечится? По замыслу игры, враг – просто агрессивный противник. Это упрощает реализацию и соответствует духу «гладиаторских боёв», где враг всегда атакует.
§2.3 Реализация магазина и прогрессии: улучшения, покупка предметов, рост сложности
Магазин реализован в классе Shop со статическим методом visit. Он выводит меню и обрабатывает выбор игрока.
Основное меню:
java
System.out.println("1 - +2 Силы (30 золота)");
System.out.println("2 - +10 макс. здоровья (40 золота)");
System.out.println("3 - Купить оружие");
System.out.println("4 - Купить броню");
System.out.println("5 - Выйти");
Улучшение силы:
java
if (hero.getGold() >= 30) {
hero.addStrength(2);
hero.addGold(-30);
System.out.println("Силаувеличена! Теперь " + hero.getStrength());
} else System.out.println("Недостаточнозолота!");
Улучшениездоровья:
java
if (hero.getGold() >= 40) {
hero.increaseMaxHealth(10);
hero.addGold(-40);
System.out.println("Макс. здоровьеувеличено! Теперь " + hero.getMaxHealth());
}
Метод increaseMaxHealth в Hero также увеличивает текущее здоровье, чтобы игрок получал немедленное лечение.
Покупкаоружия:
java
private static void buyWeapon(Hero hero, Scanner scanner) {
System.out.println("Оружие:");
Weapon[] weapons = { new Weapon("Короткиймеч", 6), new Weapon("Длинныймеч", 10), new Weapon("Секира", 14) };
for (int i = 0; i < weapons.length; i++) {
int cost = weapons[i].getDamage() * 5;
System.out.println((i+1) + " - " + weapons[i].getName() + " (урон " + weapons[i].getDamage() + ") — " + cost + " золота");
}
int idx = Game.readInt(scanner, 0, 3);
if (idx == 0) return;
Weapon selected = weapons[idx-1];
int cost = selected.getDamage() * 5;
if (hero.getGold() >= cost) {
hero.setWeapon(selected);
hero.addGold(-cost);
System.out.println("Выкупили " + selected.getName());
} else System.out.println("Недостаточнозолота!");
}
Аналогично для брони.
Прогрессия врагов (метод generateEnemy в Game):
java
private static Enemy generateEnemy(int battleNum) {
String[] names = {"Кратос"};
String name = names[random.nextInt(names.length)];
int health = 40 + battleNum * 10;
int strength = 3 + battleNum;
int damage = 3 + battleNum;
int defense = 2 + battleNum / 2;
return new Enemy(name, health, strength, damage, defense);
}
Наградазапобеду:
java
int reward = 40 + battleNum * 10;
hero.addGold(reward);
Зачемнужнапрогрессия? Если бы враги всегда были одинаковыми, игра быстро надоела бы. Рост сложности заставляет игрока прокачивать героя, искать лучшую стратегию и чувствовать прогресс. Формулы подобраны так, чтобы начальные бои были лёгкими, а после 5–6 боев требовали серьёзных улучшений.
§2.4 Тестирование и отладка: типичные ошибки и их исправление
В процессе разработки мы столкнулись с несколькими типичными ошибками, которые пришлось исправлять.
Ошибка 1: Бесконечный цикл при неправильном вводе.
Первая версия readInt не очищала буфер при ошибке, и если пользователь вводил букву, то hasNextInt() всегда возвращал false, и цикл зацикливался. Исправлено добавлением scanner.nextLine() в ветке else.
Ошибка 2: Некорректный расчёт защиты.
Изначально в методе getDefense возвращался armor.getDefense() без учёта флага защиты. Это делало защиту бесполезной. Добавил условие: если isDefending == true, возвращать удвоенную защиту.
Ошибка 3: Игрок мог купить одно и то же оружие повторно.
Было добавлено сравнение текущего оружия с выбранным: если совпадают по имени и характеристикам, покупка отменяется с сообщением.
Ошибка 4: При генерации врага для defense использовалось целочисленное деление, что давало неправильные значения на малых номерах боёв.
Например, при battleNum = 1, 2 + 1/2 = 2 (так как 1/2 = 0). Это нормально, но на 3-м бою 2 + 3/2 = 3 – защита растёт каждые два боя. Оставил так, посчитав это приемлемым.
Ошибка 5: После победы в бою и посещения магазина статистика героя не обновлялась перед следующим боем.
Исправлено вызовом hero.showStats() после магазина в основном цикле Game.
Тестирование проводилось вручную: мы проходили несколько боёв, вводили заведомо неверные данные (буквы, отрицательные числа, числа вне диапазона), проверяли работу магазина, улучшений, покупки предметов. Все сценарии отработали корректно. Игра не вылетала.
3. Заключение
В ходе работы над проектом мы успешно создали полностью функционирующую консольную RPG «Мечи и сандали». Все поставленные задачи были выполнены:
Изучены основы языка Java: синтаксис, типы данных, условные операторы, циклы, классы и объекты, исключения. Особое внимание уделено принципам ООП: инкапсуляции, композиции, абстракции.
Изучены особенности консольного ввода-вывода, создан универсальный метод readInt, обеспечивающий устойчивость к некорректному вводу.
Разработана архитектура из 8 классов, каждый из которых выполняет свою роль: модели данных (Weapon, Armor, Hero, Enemy), сервисы (Battle, Shop), управление (Game), точка входа (Main). Код отличается чистотой и разделением ответственности.
Реализована боевая система: пошаговый режим, атака, защита (с 50% шансом уклонения и удвоением защиты), лечение зельем (20% от максимума). Урон врага имеет случайный разброс (0.8–1.2 от базового), что делает бои динамичными.
Реализован магазин: улучшение силы (+2 за 30 золота), увеличение максимального здоровья (+10 за 40 золота), покупка оружия и брони из трёх видов каждое. Цены привязаны к характеристикам предметов.
Реализована прогрессия сложности: враги становятся сильнее с каждым боем (здоровье растёт на 10 единиц, сила и урон на 1 единицу, защита на 0.5). Награда за победу также растёт (на 10 золота за бой).
Обеспечена полная устойчивость к некорректному вводу: при вводе букв или чисел вне диапазона программа не падает, а повторяет запрос.
Что получилось хорошо:
Чистая архитектура, которую легко объяснить и в которой легко ориентироваться. Даже спустя несколько недель без труда можем добавить новую функциональность.
Надёжная обработка ввода – программа не вылетает при любых действиях пользователя, что особенно важно для консольных приложений.
Интересная боевая механика: случайный урон врага и 50% уклонение при защите делают каждый бой уникальным.
Полностью рабочий игровой цикл с бесконечным прохождением (пока игрок не проиграет).
Что можно улучшить в будущем (перспективы развития):
Сохранение прогресса. Добавить запись в файл (максимальный раунд, текущие характеристики, золото). При старте игры загружать последнее сохранение.
Расширенный ассортимент магазина. Добавить больше видов оружия и брони, а также расходные предметы (зелья разной силы, временные баффы).
Система уровней и опыта. За победы начислять опыт, после накопления определённого количества повышать уровень, что автоматически увеличивает характеристики.
Больше типов врагов. Сейчас только один тип (Кратос). Можно добавить несколько классов врагов с разными стратегиями (например, маг, стрелок, танк).
Интерфейс Character. Введение общего интерфейса для Hero и Enemy позволит писать более обобщённый код в Battle.
Цветной вывод. Использовать ANSI-коды для окрашивания текста в консоли (например, красный цвет для урона, зелёный для лечения).
Звук и музыка. Хотя в консоли это сложно, но можно добавить системные звуки через java.awt.Toolkit.
Вывод: Работа над проектом позволила мне углубить знания Java, научиться применять ООП на практике, разрабатывать многофайловую архитектуру, обрабатывать пользовательский ввод и создавать увлекательные игровые механики. Этот опыт станет фундаментом для более серьёзных проектов, например, игр с графическим интерфейсом на JavaFX или полноценных приложений на Spring. Считаю, что поставленная цель достигнута, игра готова к демонстрации и может быть использована как пример для начинающих программистов.
Список литературы
Хорстманн К.С., Корнелл Г. Java. Библиотека профессионала, том 1. Основы. – М.: Вильямс, 2019. – 864 с.
Официальная документация Oracle по Java SE: https://docs.oracle.com/en/java/javase/ (дата обращения: 18.05.2026).
Учебный портал Metanit: Java для начинающих. – URL: https://metanit.com/java/tutorial/ (дата обращения: 18.05.2026).
Habr.com. Разработка консольной игры на Java: практическое руководство. – URL: https://habr.com/ru/articles/31180/ (дата обращения: 18.05.2026).
CodeGym. Как создать игру «Тетрис» на Java: пошаговый урок. – URL: https://codegym.cc/ru/quests/lectures/ru.questgames.level01.lecture01 (дата обращения: 18.05.2026).
Лафоре Р. Объектно-ориентированное программирование в Java.
JavaRush. Онлайн-курс по Java: лекции и практика. – URL: https://javarush.com/ (дата обращения: 18.05.2026).
1