lunedì 18 aprile 2016

Progetto Java: Humans vs Zombies








In questo post spiegherò le specifiche dell'esercizio sul gioco "HumasVsZombie".

Lo scopo dell'esercizio è in linea con quelli già svolti durante il corso e consiste nell'aggiungere alcune funzionalità ad un progetto Java che implementa il gioco "Humans vs Zombies".

I sorgenti del progetto possono essere scaricati dal seguente link SORGENTI PROGETTO

Humans vs Zombies

HumansVsZombie è un gioco a turni in cui due schieramenti, umani e zombie, si combattono tra di loro al fine di affermare la propria sopravvivenza. Il gioco è costituito da un numero arbitrario di turni e termina quando tutti i turni sono stati completati o quando rimane in vita un solo schieramento (zombie o umani).
All'inizio del gioco gli attori di ogni schieramento vengono creati e posizionati in maniera casuale all'interno di un campo formato da una matrice (n x m). Il numero degli attori dipenderà dalla probabilità di creazione associata ad ogni schieramento. Ogni casella della matrice rappresenta una posizione del campo e in ogni posizione può esserci un solo attore: naturalmente alcune posizioni possono rimanere vuote.
Ad ogni turno, gli attori del sistema (umani e zombie) compiono una determinata azione:
  • gli umani possono spostarsi alla ricerca di zombie e ucciderli
  • gli zombie possono spostarsi alla ricerca di umani da infettare
Gli umani sono sempre i primi ad iniziare il turno e una volta che hanno concluso le proprie azioni è possibile eseguire quelle degli zombie. Se un umano uccide uno zombie prima dell'inizio dell'azione di quest'ultimo allora lo zombie verrà rimosso dal campo da gioco. Viceversa, se uno zombie infetta un umano, quell'umano verrà rimosso dal gioco solamente al turno successivo e prima che possa compiere qualsiasi azione. Quando tutti gli umani e tutti gli zombie avranno compiuto la propria azione il turno finisce ed è possibile passare a quello successivo.
La posizione dell'attore di un determinato schieramento stabilisce l'ordine con cui gli attori possono eseguire la propria azione: il campo da gioco viene perlustrato a partire dalla prima casella in alto a sinistra e si prosegue con le caselle appartenenti alla stessa riga, una volta perlustrata la prima riga si passa alla successiva fino ad arrivare all'ultima. Quando in una casella è presente un attore e quell'attore appartiene allo schieramento che può agire in quel frangente di turno allora l'attore potrà eseguire la sua azione.

Struttura del gioco


1. Campo da gioco

Il gioco si svolge all'interno di un campo rappresentato da un matrice (n x m) dove ogni posizione è una casella del campo. Ogni casella è identificata attraverso il numero di riga e di colonna della matrice.
Il campo da gioco è costituito dalla classe Field che contiene tutti gli attori presenti nel gioco. Una casella del campo può essere vuota o può essere occupata, in maniera esclusiva, da uno zombie o da un umano. Ad ogni attore verrà associato un oggetto, chiamato Location, nel quale sono contenute le coordinate dell'attore all'interno del Field (numero di riga, numero di colonna).
Il posizionamento degli attori del gioco viene effettuata contestualmente alla loro creazione . Per ogni casella del gioco viene estratto un numero e se questo numero è minore di una certa probabilità (ogni attore ha associata una probabilità di creazione) viene creato un attore e posizionato in quella casella.

La visualizzazione del campo da gioco avviene tramite l'uso delle librerie di Java Swing. La creazione del campo e la sua gestione avvengono tramite l'utilizzo della classe GameView.





La figura precedente mostra un esempio del campo di gioco. Ogni quadratino colorato rappresenta un attore del sistema all'interno dei fields.

2. Attori

Ogni attore del gioco è rappresentata da una classe: Humans per gli umani e Zombie per gli zombie. Ognuna di queste classe ha associato un attributo Location. La location rappresenta la posizione di un singolo attore del gioco all'interno del campo da gioco Field. Ogni attore ha a disposizione, per ogni turno di gioco, una serie di azioni che può intraprendere.

Gli esseri umani hanno a disposizione due azioni:
  • Uccidi uno zombie che si trova nelle posizioni adiacenti a quelle dell'umano.
  • Una volta ucciso lo zombie, l'umano può spostarsi in una posizione libera adiacente a quella in cui si trova in cerca di altri zombie da uccidere.
Gli zombie hanno a disposizione due azioni:
  • Cerca degli umani da infettare. Durante ogni turno di gioco  uno zombie può infettare un solo umano adiacente alla sua posizione. Una volta che l'umano è stato infettato, al successivo turno si trasformerà in uno zombie.
  • Dopo avere infettato un umano, lo zombie può spostarsi in una posizione adiacente libera.

    3. Turni

    Il gioco si sviluppa tramite l'esecuzione di un numero di turni arbitrario. Ad ogni step vengono eseguite l'azioni associate ad ogni attore del gioco. La gestione dei turni e dell'esecuzione delle azioni è delegata alla classe Game.

    Obiettivi del progetto

    Gli obiettivi del progetto consistono nell'aggiunta di alcune funzionalità all'insieme di quelle preesistenti. In particolare devono essere implementate le seguenti funzionalità:
    1. Aggiungere una nuova classe di personaggi chiamati HuberZombie: questi zombie possono infettare tutti gli umani che si trovano nelle posizioni adiacenti a quella in cui si trova lo zombie.
    2. Modificare la modalità di uccisione degli zombie da parte degli umani: gli umani hanno a disposizione una pistola con un numero limitato di proiettili (pari a 5 proiettili durante tutto il gioco).
    3. Aggiungere la possibilità di raccogliere degli oggetti: in una casella, oltre agli zombie o agli umani, possono esserci delle munizioni che possono essere raccolte.
    4. (Opzionale) Modificare l'interfaccia grafica in maniera tale da aggiungere un piccolo pannello che permette di specificare il numero dei turni del gioco, di far partire il gioco e di fermarlo.
    5. All'interno del codice sono state inseriti, in maniera volontaria, alcuni "cattivi" pattern di programmazione, alcuni dei quali sono stati mostrati nei precedenti post di questo blog.
    Suggerimenti.... 

    Per lo sviluppo dei primi tre punti è utile pensare all'utilizzo di classi astratte e/o di interfacce (ponete particolare attenzione al codice duplicato il quale è indice di qualche problema di progettazione).

    Il punto quattro richiede qualche sforzo in più per essere implementato in quanto è necessario avere delle conoscenze minime delle librerie di Java Swing. Delle slide che possono aiutare per lo sviluppo dell'interfaccia grafica possono essere reperite dal seguente link Slide Java Swing. Su queste slide è utile studiare la parte relativa agli ActionListener e alla progettazione dei JPanel.
    La parte di codice da cui dovete partire si trova all'interno del costruttore della classe GameView:


    Container contents = getContentPane();
    //al posto di stepLabel inserire un JPanel
    contents.add(stepLabel, BorderLayout.NORTH);
    contents.add(fieldView, BorderLayout.CENTER);
    contents.add(population, BorderLayout.SOUTH);
    pack();
    setVisible(true);
    

    dove bisogna inserire un JPanel che al suo interno contiene i vari pulsanti o textfield che servono per gestire l'esecuzione del gioco.

    Per eventuali chiarimenti potete lasciare un commento sotto il post: cercherò di rispondervi il prima possibile.

    Altre informazioni utili
    Il progetto deve essere compilato con Maven per potere essere eseguito. La classe principale che contiene il metodo main() è App.java .