Esercitazione di laboratorio del corso di
Interazione Uomo-Macchina: Interfacce Grafiche
Modalita' di lavoro
A gruppi composti da non piu' di tre persone.
I gruppi possono non essere gli stessi delle esercitazioni guidate.
Inoltre e' possibile farla a casa, anche per conto proprio (non in gruppo).
Per favore segnalatemi qualsiasi variazione o aggiunta
rispetto ai gruppi delle esercitazioni guidate.
Data di consegna
- 5 giugno 2001 per chi intende sostenere lo scritto a giugno (giorno 11)
- 15 giugno 2001 per gli altri
Indice
Lavoro da svolgere
Realizzare un'interfaccia grafica per un "gioco del labirinto", descritto
sotto.
Descrizione del gioco
In questo gioco si ha un labirinto dove si muovono due personaggi:
Teseo e il minotauro.
Lo scopo di Teseo e' di raggiungere il minotauro prima che questo
trovi l'uscita del labirinto.
Lo scopo del minotauro e' di trovare l'uscita del labirinto
prima di essere raggiunto da Teseo.
Il gioco finisce quando Teseo raggiunge il minotauro (e allora ha
vinto Teseo) oppure quando il minotauro trova l'uscita (e allora
ha vinto il minotauro).
Il labirinto e' strutturato come una griglia bidimensionale
di NxN caselle.
Ogni parete di confine fra due caselle puo' essere:
- muro = non attraversabile
- libera = attraversabile in una mossa
- muretto = attraversabile in due mosse (bisogna scavalcarlo)
- muro forato = attraversabile in tre mosse (bisogna
passare attraverso il buco)
Le pareti di contorno della griglia sono tutte muri tranne una
che e' libera.
La casella che confina con questa parete e' l'uscita del
labirinto.
Le pareti del labirinto sono configurate in modo tale che
da qualsiasi casella della griglia sia possibile raggiungere l'uscita.
Sono possibili tre modalita' di gioco:
- L'utente manovra Teseo, il minotauto e' manovrato dal sistema
- L'utente manovra il minotauro, Teseo e' manovrato dal sistema
- Entrambi i personaggi sono manovrati dal sistema
Inizialmente Teseo e' collocato all'uscita
e il minotauro e' collocato al centro del labirinto.
Il primo a muovere e' Teseo.
Nel seguito uso la parola "personaggio" per indicare intercambiabilmente
Teseo o il minotauro.
In ogni momento un personaggio ha una posizione e una
direzione di marcia.
Alla prossima mossa puo' decidere di:
- tentare di avanzare nella direzione corrente
- cambiare direzione e tentare di avanzare nella nuova direzione
Se nella direzione del tentato avanzamento c'e' un muro, oppure
se si esce dal labirinto, allora la mossa non e' valida.
Quando il personaggio e' manovrato dal sistema, non vengono
mai generate mosse non valide.
Se il personaggio e' manovrato dall'utente, allora
il sistema informa l'utente che la mossa non e' valida
con un segnale opportuno: l'utente ha consumato una mossa inutilmente.
Se nella direzione del tentato avanzamento c'e' libero, allora
il personaggio avanza effettivamente, spostandosi nella casella accanto.
Se nella direzione del tentato avanzamento c'e' un muretto, allora
sara' necessaria un'altra mossa nella stessa direzione per
poter avanzare. Il personaggio potra' dunque terminare la scavalcata del
muretto al prossimo turno.
Se nella direzione del tentato avanzamento c'e' un muro forato,
allora saranno necessarie altre due mosse nella stessa direzione
per poter avanzare. Il personaggio potra' dunque completare il passaggio
attraverso il foro nei prossimi due turni.
Se entrambi i personaggi sono manovrati dal sistema, allora eseguono
alternativamente una mossa per uno.
Se uno dei personaggi e' manovrato dall'utente, allora sono possibili
vari livelli di difficolta':
- il sistema e l'utente eseguono alternativamente una mossa ciascuno
(il sistema aspetta che l'utente abbia mosso prima di muovere
un'altra volta)
- il sistema esegue comunque una mossa ogni K unita' di tempo,
senza aspettare che l'utente abbia mosso (la variabile K puo'
essere impostata per regolare il livello di difficolta')
Funzionalita' dell'interfaccia
Prima di iniziare il gioco, l'utente puo' impostare:
- la dimensione N della griglia del labirinto
- la modalita' di gioco (l'utente manovra Teseo, il minotauro,
o nessuno dei due)
- se necessario, il livello di difficolta' per l'utente
(come spiegato sopra)
In ogni caso il sistema fornisce dei valori di default sensati.
Il gioco puo' avere inizio solo per esplicita richiesta dell'utente.
In ogni momento deve essere possibile uscire dall'applicazione
(interrompendo il gioco se e' il caso).
In ogni momento deve essere possibile sospendere il gioco e poi
riprenderlo dal punto in cui si era rimasti.
La visualizzazione dello stato attuale del gioco avviene nel modo
seguente:
-
In una parte dell'interfaccia e' mostrato il labirinto in visione 2D
dall'alto.
In questa visione 2D devono essere riconoscibili i tipi delle pareti,
e devono essere indicate la posizione e la
direzione di marcia corrente di ciascuno personaggio.
-
In un'altra parte dell'interfaccia e' mostrata una visione 3D del
labirinto da uno dei seguenti punti di vista
- punto di vista di Teseo
- punto di vista del minotauro
- visione volo d'uccello
In ogni momento e' possibile passare da uno dei tre punti di vista ad un
altro.
I tre punti di vista sono di default rispettivamente quando
l'utente manovra Teseo, per quando l'utente manovra il minotauro e per
quando entrambi sono manovrati dal sistema.
Entrambe le visioni 2D e 3D sono aggiornate in modo da riflettere
istante per istante lo stato del gioco.
E' compito degli sviluppatori dell'interfaccia stabilire l'aspetto
grafico da dare ai vari tipi di pareti e ai due personaggi.
Il sistema deve fornire segnali all'utente (in una qualche forma
opportuna) almeno in corrispondenza delle seguenti situazioni:
-
il personaggio manovrato dall'utente ha tentato una mossa non valida
-
il gioco e' terminato (in questo caso deve anche
essere reso noto il vincitore)
Nota: Puo' essere che le due condizioni di terminazione del gioco
si verifichino contemporaneamente
(Teseo si trova nella casella di uscita e il
minotauro muove sulla casella di uscita).
In questo caso la partita e' pari.
Materiale fornito
Viene fornita una classe Java Labirinto che implementa
le strutture dati e le funzioni
dell'applicazione relative alla creazione del labirinto e alla gestione
dei movimenti di Teseo e del minotauro.
La classe e' contenuto nel file Java (gia' compilato)
Labirinto.class.
La classe Labirinto e' cosi' strutturata.
Variabili
-
NORD, SUD, EST, OVEST
Costanti intere che indicano le quattro direzioni possibili.
-
MURO, LIBERO, MURETTO, FORO
Costanti intere che indicano i quattro possibili tipi di pareti.
Metodi
-
Labirinto(int N)
Costrutture della classe. Crea un labirinto di dimensione NxN.
Le caselle del labirinto saranno identificate da coppie di
interi (x,y) dove sia x che y variano fra 0 ed N-1.
-
int dimensione()
Restituisce il numero N tale che il labirinto e' una griglia NxN.
-
int tipoParete(int x, int y, int direzione)
Ritorna il tipo di parete che delimita la casella (x,y) nella direzione
data.
La direzione e' una fra
Labirinto.NORD, Labirinto.SUD, Labirinto.EST, Labirinto.OVEST.
Il tipo di parete ritornato e' uno fra
Labirinto.MURO, Labirinto.LIBERO, Labirinto.MURETTO,
Labirinto.FORO.
-
int xTeseo(), int yTeseo()
Ritornano le coordinate x ed y (rispettivamente)
della casella in cui si trova Teseo.
-
int xMinotauro(), int yMinotauro()
Ritornano le coordinate x ed y (rispettivamente)
della casella in cui si trova il minotauro.
-
int dirTeseo(), int dirMinotauro()
Ritornano la direzione di marcia corrente rispettivamente
di Teseo e del minotauro.
Il valore di ritorno e' uno fra
Labirinto.NORD, Labirinto.SUD, Labirinto.EST, Labirinto.OVEST.
-
boolean mossaValida(int x, int y, int direzione)
Ritorna true se un personaggio collocato in (x,y) puo'
muovere nella direzione indicata. Non puo' muovere se c'e'
un muro oppure se c'e' l'uscita del labirinto.
-
void cambiaDirTeseo(int direzione),
void cambiaDirMinotauro(int direzione)
Assegnano la direzione di marcia a Teseo e al minotauro, rispettivamente.
La direzione e' una fra
Labirinto.NORD, Labirinto.SUD, Labirinto.EST, Labirinto.OVEST.
-
boolean tentaMossaTeseo()
Tenta di muovere Teseo nella sua direzione di marcia corrente.
Il valore di ritorno e' true se Teseo si muove effettivamente
(la parete e' libera, oppure
e' un muretto e questo e' il secondo tentativo eseguito per
scavalcarlo, oppure e' un buco e questo e' il terzo tentativo
eseguito per attraversarlo).
Altrimenti il valore di ritorno e' false.
In questo caso,
chiamando mossaValida(xTeseo(),yTeseo(),dirTeseo()) si puo'
capire se la mossa e' fallita perche'
non era valida.
-
boolean tentaMossaMinotauro()
Tenta di muovere il minotauro nella sua direzione di marcia corrente.
Analoga alla precedente.
-
boolean muoviAutomTeseo()
Fa eseguire automaticamente una mossa a Teseo.
La mossa e' sempre valida.
Il valore di ritorno e' true Teseo si muove effettivamente,
false altrimenti (cioe' se nella direzione corrente
c'e' un muretto o un buco e non e' stato fatto ancora un numero
sufficiente di tentativi).
-
boolean fineGioco()
Ritorna true se e solo se e' finito il gioco.
-
boolean haVintoTeseo(), boolean haVintoMinotauro()
Ritornano true se il gioco e' finito e se il vincitore e'
Teseo o il minotauro, rispettivamente.
-
void disegnaLabirinto()
Metodo che puo' essere utile per debug.
Disegna su standard output una rappresentazione del labirinto.
I muri sono indicati con sequenze di #, i muretti con sequenze di -,
i muri forati con sequenze di # interrotte al centro.
Le posizioni di Teseo e del minotauro sono indicate con T e M
rispettivamente.
La mossa di un personaggio da parte dell'utente si implementa
chiamando cambiaDirXXX seguita da tentaMossaXXX.
Se tentaMossaXXX ritorna false e mossaValida
ritorna anch'essa false, allora bisogna generare un segnale
di avvertimento all'utente.
La mossa di un personaggio da parte del sistema si implementa
chiamando muoviAutomXXX.
In ogni caso, dopo che il personaggio si e' mosso occorre chiamare
fineGioco per controllare se il gioco e' finito.
Se il gioco e' finito il vincitore si ottiene chiamando
haVintoXXX.
Nota: Il controllo di fine gioco e' necessario
perche' eventuali chiamate a
tentaMossaXXX o muoviAutomXXX continuano ad
avere effetto sui personaggi anche se il gioco e' finito.
Avvertenze
Il meccanismo automatico di movimento dei personaggi e' molto grezzo:
non e' stata implementata nessuna strategia di gioco,
semplicemente si sceglie di avanzare in una direzione a caso.
Quindi non preoccupatevi se il sistema sembra giocare in modo stupido.
Se invece riscontrate anomalie di comportamento o
malfunzionamenti, per favore segnalatemeli.
Raccomandazioni
Questo e' un progetto di interfacce grafiche.
Pertanto, sara' tenuto conto non solo del fatto che tutte le
funzioni richieste siano presenti nell'interfaccia
sviluppata, ma anche e di quanto facile e gradevole
risulta l'uso dell'interfaccia stessa per l'utente.
Materiale da consegnare
-
Il sorgente .java ed il compilato .class di ciascuna classe
sviluppata per creare l'interfaccia.
-
Brevissime istruzioni per l'uso scritte in formato di testo ASCII
o HTML.
Queste istruzioni devono essere pensate per una persona che
conosce bene il gioco e vuole imparare velocemente a giocarci
usando la vostra interfaccia.
Il materiale puo' essere consegnato su dischetto o spedito per EMAIL
all'indirizzo magillo@disi.unige.it.
Indicare chiaramente i nomi dei componenti del gruppo
e l'elenco dei file.