Tworzenie postaci do gry
Część sekcji Programowanie obiektowe ścieżki Java w Coddy. Lekcja 86 z 87.
To wyzwanie polega na zbudowaniu systemu rozwoju postaci w grze, który pokazuje możliwości programowania obiektowego w modelowaniu złożonych, interaktywnych bytów.
Stwórz hierarchię postaci, w której bazowa klasa Character definiuje wspólne atrybuty, takie jak zdrowie, imię i poziom. Wyspecjalizowane klasy, takie jak Warrior, Mage i Archer, rozszerzają tę bazę o unikalne umiejętności i style walki.
Interfejsy sprawdzają się tu naturalnie: Attackable może definiować metody walki, a Healable obsługiwać zdolności przywracania zdrowia. Mage może implementować oba interfejsy, podczas gdy Warrior skupia się wyłącznie na atakowaniu.
Rozważ użycie wzorca Strategia dla różnych zachowań związanych z atakiem, aby postacie mogły dynamicznie zmieniać style walki. Wzorzec Stan mógłby zarządzać stanami postaci, takimi jak normalny, zatruty lub ogłuszony, które wpływają na zachowanie.
Pomyśl o kompozycji w systemach wyposażenia, w których postacie „mają” broń i zbroję, zamiast po nich dziedziczyć. Używaj wyliczeń dla klas postaci lub typów obrażeń i stosuj enkapsulację, aby chronić statystyki przed nieprawidłowymi modyfikacjami.
Wyzwanie
ŁatwyZbudujmy system rozwoju postaci w grze, który pokazuje możliwości programowania obiektowego w modelowaniu złożonych, interaktywnych postaci! Stworzysz hierarchię postaci o różnych stylach walki, specjalnych zdolnościach i systemie stanu, który wpływa na zachowanie postaci.
Rozmieścisz swój kod w siedmiu plikach:
DamageType.java: Utwórz typ wyliczeniowy reprezentujący różne rodzaje obrażeń w grze. Uwzględnij wartościPHYSICAL,MAGICALiRANGED. Dodaj prywatne poledescription(String), konstruktor, który je ustawia, oraz metodę pobierającą. Obrażenia fizyczne powinny mieć opis "brute force", magiczne — "arcane energy", a dystansowe — "precision strike".Attackable.java: Utwórz interfejs określający możliwości walki. Zadeklaruj metodyattack(Character target), która zwraca String opisujący atak, orazgetDamageType(), która zwraca DamageType.Healable.java: Utwórz interfejs dla zdolności przywracania zdrowia. Zadeklaruj metodęheal(int amount), która zwraca String opisujący leczenie.Character.java: Utwórz abstrakcyjną klasę bazową dla wszystkich postaci w grze. Uwzględnij prywatne pola:name(String),health(int),maxHealth(int) ilevel(int). Konstruktor przyjmuje name, maxHealth i level, a początkowo ustawia health na wartość maxHealth. Dodaj metody pobierające dla wszystkich pól. Dodaj chronioną metodęsetHealth(int health), która pilnuje, aby wartość health mieściła się w zakresie od 0 do maxHealth. Utwórz metodętakeDamage(int damage), która zmniejsza wartość health i zwraca"[name] takes [damage] damage! Health: [health]/[maxHealth]". Dodaj metodęisAlive(), która zwraca true, jeśli wartość health jest większa od 0. Zadeklaruj metodę abstrakcyjnągetCharacterClass(), która zwraca String.Warrior.java: Utwórz klasę rozszerzającą Character i implementującą Attackable. Dodaj prywatne polestrength(int). Konstruktor przyjmuje name, maxHealth, level i strength. ZaimplementujgetCharacterClass(), aby zwracała"Warrior". ZaimplementujgetDamageType(), aby zwracałaPHYSICAL. Zaimplementujattack(Character target), aby zadawała obrażenia równe sumie strength i level, wywoływała metodę takeDamage celu i zwracała"[name] strikes with [damageType description] for [damage] damage!", a następnie znak nowej linii i wynik wywołania takeDamage.Mage.java: Utwórz klasę rozszerzającą Character i implementującą zarówno Attackable, jak i Healable. Dodaj prywatne polaintelligence(int) imana(int). Konstruktor przyjmuje name, maxHealth, level, intelligence i mana. ZaimplementujgetCharacterClass(), aby zwracała"Mage". ZaimplementujgetDamageType(), aby zwracałaMAGICAL. Zaimplementujattack(Character target), aby zadawała obrażenia równe intelligence pomnożonemu przez 2, w tym samym formacie co w klasie Warrior. Zaimplementujheal(int amount), aby przywracała zdrowie (używając setHealth) i zwracała"[name] channels healing magic! Health: [health]/[maxHealth]".Main.java: Ożyw swój system gry! Otrzymasz ciąg poleceń rozdzielonych przecinkami:CREATE_WARRIOR:name:maxHealth:level:strengthCREATE_MAGE:name:maxHealth:level:intelligence:manaATTACK:attackerName:targetNameHEAL:mageName:amountSTATUS:characterName
Przechowuj kolekcję postaci. Przetwarzaj każde polecenie i wyświetlaj:
- CREATE_WARRIOR/CREATE_MAGE:
[name] the [characterClass] joins the battle! - ATTACK: Wyświetl wynik ataku (String zwrócony przez metodę attack)
- HEAL: Wyświetl wynik leczenia lub
[name] cannot heal, jeśli postać nie jest Magiem - STATUS:
[name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]
Po wykonaniu wszystkich poleceń wyświetl
--- Battle Summary ---, a następnie status każdej postaci.
Otrzymasz jedno wejście: ciąg poleceń rozdzielonych przecinkami.
Na przykład dla wejścia CREATE_WARRIOR:Thorin:100:5:15,CREATE_MAGE:Gandalf:80:7:12:50,ATTACK:Thorin:Gandalf,HEAL:Gandalf:25,STATUS:Gandalf wynikiem będzie:
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 - AliveTo wyzwanie łączy dziedziczenie (hierarchię Character), implementację wielu interfejsów (Mage implementuje zarówno Attackable, jak i Healable), typy wyliczeniowe z metodami (DamageType), polimorfizm (jednolite traktowanie różnych typów postaci) oraz enkapsulację (chronione zarządzanie zdrowiem) w angażującym systemie gry!
Spróbuj swoich sił
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: Użyj kolekcji do przechowywania postaci (LinkedHashMap zachowuje kolejność dodawania)
// LinkedHashMap<String, Character> characters = new LinkedHashMap<>();
// TODO: Podziel input według przecinków, aby uzyskać poszczególne polecenia
// String[] commands = input.split(",");
// TODO: Przetwórz każde polecenie:
// - CREATE_WARRIOR:name:maxHealth:level:strength
// Wypisz: "[name] the Warrior joins the battle!"
//
// - CREATE_MAGE:name:maxHealth:level:intelligence:mana
// Wypisz: "[name] the Mage joins the battle!"
//
// - ATTACK:attackerName:targetName
// Wypisz wynik ataku zwrócony przez metodę attack
//
// - HEAL:mageName:amount
// Wypisz wynik leczenia lub "[name] cannot heal", jeśli postać nie jest typu Mage
//
// - STATUS:characterName
// Wypisz: "[name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]"
// TODO: Po wykonaniu wszystkich poleceń wypisz "--- Battle Summary ---"
// Następnie wypisz stan każdej postaci
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe thisMetodyPola (atrybuty)Metoda konstruktoraPrzeciążanie konstruktoraPodsumowanie — prosty kalkulator4Dziedziczenie
Podstawy dziedziczenia (extends)Słowo kluczowe superPrzesłanianie metod (@Override)Łańcuch wywołań konstruktorówKlasa ObjectDziedziczenie jedno- i wielopoziomoweDlaczego Java nie obsługuje wielodziedziczenia klasPodsumowanie – hierarchia pracowników7Metody specjalne i klasa Object
Metoda toString()equals() i hashCode()Metoda clone()compareTo() i ComparableInterfejs ComparatorPodsumowanie — własne sortowanie10Obsługa wyjątków w programowaniu obiektowym
Hierarchia klas wyjątkówWłasne wyjątkiBłędy sprawdzane a niesprawdzaneWzorzec try-with-resourcesPodsumowanie – zweryfikowany użytkownik2Modyfikatory dostępu i enkapsulacja
Przegląd poziomów dostępuMetody pobierające i ustawiająceUkrywanie informacjiSłowo kluczowe finalPodsumowanie — menedżer kont bankowych5Polimorfizm
Podstawy przeciążania metodPrzesłanianie metod (w czasie wykonywania)Rzutowanie w górę i w dółOperator instanceofKlasy i metody abstrakcyjnePowtórka — kalkulator figur8Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieAgregacja a kompozycjaKlasy wewnętrzne, zagnieżdżone i anonimoweEnumy i metody enumówRekordy (Java 16+)Klasy zapieczętowane (Java 17+)11Wzorce projektowe — część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec BuilderWzorzec ObserverWzorzec Strategy14Końcowe wyzwania
Platforma e-learningowaSystem bankowyTworzenie postaci do gryWypożyczalnia pojazdów3Właściwości klas i składowe statyczne
Zmienne instancji a zmienne statyczneMetody statyczneBloki statyczneStałe (static final)Powtórka – Counter i Utility6Interfejsy i klasy abstrakcyjne
Wprowadzenie do interfejsówImplementowanie interfejsówImplementacja wielu interfejsówMetody domyślne i statyczne w interfejsieKlasy abstrakcyjne a interfejsyInterfejsy funkcyjnePodsumowanie — system płatnościPoćwicz samodzielnie: Kompilator Java online