Sviluppo del personaggio di un gioco
Fa parte della sezione Programmazione orientata agli oggetti del percorso Java di Coddy. Lezione 86 di 87.
Questa sfida ti fa costruire un sistema di sviluppo dei personaggi di gioco che mette in mostra la potenza della programmazione orientata agli oggetti nel modellare entità complesse e interattive.
Progetta una gerarchia di personaggi in cui una classe Character di base definisce attributi comuni come salute, nome e livello. Classi specializzate come Warrior, Mage e Archer estendono questa base con abilità e stili di combattimento unici.
Le interfacce funzionano in modo naturale qui: Attackable potrebbe definire metodi di combattimento, mentre Healable gestisce le abilità di ripristino. Un Mage potrebbe implementarle entrambe, mentre un Warrior si concentra solo sull’attacco.
Valuta l'uso del pattern Strategy per i diversi comportamenti di attacco, consentendo ai personaggi di cambiare dinamicamente stile di combattimento. Il pattern State potrebbe gestire condizioni del personaggio come gli stati normale, avvelenato o stordito, che ne influenzano il comportamento.
Rifletti sulla composizione nei sistemi di equipaggiamento, in cui i personaggi "hanno" armi e armature invece di ereditarle. Usa gli enum per le classi dei personaggi o i tipi di danno e applica l'incapsulamento per proteggere le statistiche da modifiche non valide.
Sfida
FacileCostruiamo un sistema di sviluppo dei personaggi di un gioco che mostri la potenza della POO nella modellazione di entità di gioco complesse e interattive! Creerai una gerarchia di personaggi con diversi stili di combattimento, abilità speciali e un sistema di stato che influisce sul comportamento dei personaggi.
Organizzerai il codice in sette file:
DamageType.java: crea un enum che rappresenta i diversi tipi di danno nel gioco. Includi i valoriPHYSICAL,MAGICALeRANGED. Aggiungi un campo privatodescription(String), un costruttore che lo imposta e un getter. Il danno fisico deve avere la descrizione "brute force", quello magico "arcane energy" e quello a distanza "precision strike".Attackable.java: crea un'interfaccia che definisce le capacità di combattimento. Dichiara i metodiattack(Character target), che restituisce una String che descrive l'attacco, egetDamageType(), che restituisce un DamageType.Healable.java: crea un'interfaccia per le capacità di ripristino. Dichiara un metodoheal(int amount)che restituisce una String che descrive l'azione di cura.Character.java: crea una classe base astratta per tutti i personaggi del gioco. Includi i campi privatiname(String),health(int),maxHealth(int) elevel(int). Il costruttore accetta name, maxHealth e level e inizialmente imposta health uguale a maxHealth. Includi i getter per tutti i campi. Aggiungi un metodo protettosetHealth(int health)che assicura che health rimanga tra 0 e maxHealth. Crea un metodotakeDamage(int damage)che riduce health e restituisce"[name] takes [damage] damage! Health: [health]/[maxHealth]". Aggiungi un metodoisAlive()che restituisce true se health è maggiore di 0. Dichiara un metodo astrattogetCharacterClass()che restituisce una String.Warrior.java: crea una classe che estende Character e implementa Attackable. Aggiungi un campo privatostrength(int). Il costruttore accetta name, maxHealth, level e strength. ImplementagetCharacterClass()in modo che restituisca"Warrior". ImplementagetDamageType()in modo che restituiscaPHYSICAL. Implementaattack(Character target)in modo che infligga un danno pari a strength più level, chiami il metodo takeDamage del bersaglio e restituisca"[name] strikes with [damageType description] for [damage] damage!", seguito da una nuova riga e dal risultato di takeDamage.Mage.java: crea una classe che estende Character e implementa sia Attackable sia Healable. Aggiungi i campi privatiintelligence(int) emana(int). Il costruttore accetta name, maxHealth, level, intelligence e mana. ImplementagetCharacterClass()in modo che restituisca"Mage". ImplementagetDamageType()in modo che restituiscaMAGICAL. Implementaattack(Character target)in modo che infligga un danno pari a intelligence moltiplicato per 2, seguendo lo stesso formato di Warrior. Implementaheal(int amount)in modo che ripristini health (usando setHealth) e restituisca"[name] channels healing magic! Health: [health]/[maxHealth]".Main.java: dai vita al tuo sistema di gioco! Riceverai una stringa di comandi separati da virgole:CREATE_WARRIOR:name:maxHealth:level:strengthCREATE_MAGE:name:maxHealth:level:intelligence:manaATTACK:attackerName:targetNameHEAL:mageName:amountSTATUS:characterName
Mantieni una raccolta di personaggi. Elabora ogni comando e stampa:
- CREATE_WARRIOR/CREATE_MAGE:
[name] the [characterClass] joins the battle! - ATTACK: stampa il risultato dell'attacco (la String restituita dal metodo attack)
- HEAL: stampa il risultato della cura oppure
[name] cannot healse il personaggio non è un Mage - STATUS:
[name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]
Dopo tutti i comandi, stampa
--- Battle Summary ---seguito dallo stato di ogni personaggio.
Riceverai un input: la stringa di comandi separati da virgole.
Per esempio, con l'input CREATE_WARRIOR:Thorin:100:5:15,CREATE_MAGE:Gandalf:80:7:12:50,ATTACK:Thorin:Gandalf,HEAL:Gandalf:25,STATUS:Gandalf, il tuo output sarà:
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 - AliveQuesta sfida combina l'ereditarietà (gerarchia Character), l'implementazione di più interfacce (Mage implementa sia Attackable sia Healable), gli enum con metodi (DamageType), il polimorfismo (trattare in modo uniforme diversi tipi di personaggi) e l'incapsulamento (gestione protetta della salute) in un coinvolgente sistema di gioco!
Provalo tu
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: Usa una collezione per memorizzare i personaggi (LinkedHashMap mantiene l'ordine di inserimento)
// LinkedHashMap<String, Character> characters = new LinkedHashMap<>();
// TODO: Dividi input usando la virgola per ottenere i singoli comandi
// String[] commands = input.split(",");
// TODO: Elabora ogni comando:
// - CREATE_WARRIOR:name:maxHealth:level:strength
// Stampa: "[name] the Warrior joins the battle!"
//
// - CREATE_MAGE:name:maxHealth:level:intelligence:mana
// Stampa: "[name] the Mage joins the battle!"
//
// - ATTACK:attackerName:targetName
// Stampa il risultato dell'attacco restituito dal metodo attack
//
// - HEAL:mageName:amount
// Stampa il risultato della cura oppure "[name] cannot heal" se non è un Mage
//
// - STATUS:characterName
// Stampa: "[name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]"
// TODO: Dopo tutti i comandi, stampa "--- Battle Summary ---"
// Poi stampa lo stato di ogni personaggio
}
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione a oggetti
File esterniIntroduzione alla programmazione a oggettiClassi e oggettiLa parola chiave thisMetodiCampi (attributi)Metodo costruttoreSovraccarico dei costruttoriRipasso - Calcolatrice semplice4Ereditarietà
Ereditarietà di base (extends)La parola chiave superSovrascrittura dei metodi (@Override)Concatenamento dei costruttoriLa classe ObjectEreditarietà singola e multilivelloPerché non esiste l'ereditarietà multipla delle classiRiepilogo: gerarchia dei dipendenti7Metodi speciali e classe Object
Metodo toString()equals() e hashCode()Metodo clone()compareTo() e ComparableInterfaccia ComparatorRiepilogo - Ordinamento personalizzato2Modificatori di accesso e incapsulamento
Panoramica dei livelli di accessoMetodi getter e setterNascondimento delle informazioniLa parola chiave finalRiepilogo - Gestore di conti bancari5Polimorfismo
Nozioni di base sull'overloading dei metodiOverride dei metodi (a runtime)Upcasting e downcastingL'operatore instanceofClassi e metodi astrattiRiepilogo - Calcolatore di forme8Concetti avanzati di OOP
Composizione vs ereditarietàAggregazione vs composizioneClassi interne, annidate e anonimeEnum e metodi degli EnumRecord (Java 16+)Classi sealed (Java 17+)11Modelli di progettazione Parte 1
Introduzione ai modelli di progettazionePattern SingletonPattern FactoryPattern BuilderPattern ObserverPattern Strategy14Sfide finali
Piattaforma di e-learningSistema bancarioSviluppo del personaggio di un giocoServizio di noleggio veicoli3Proprietà di classe e membri statici
Variabili di istanza e staticheMetodi staticiBlocchi staticiCostanti (static final)Riepilogo - Contatore e utility6Interfacce e classi astratte
Introduzione alle interfacceImplementazione delle interfacceImplementazione di più interfacceMetodi default e static nelle interfacceClassi astratte e interfacce a confrontoInterfacce funzionaliRiepilogo: sistema di pagamento9Tipi generici
Introduzione ai tipi genericiClassi genericheMetodi genericiParametri di tipo con limitiCaratteri jolly (?, extends, super)Riepilogo - Contenitore generico12Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositePattern IteratorEsercitati da solo: Compilatore Java online