Specifiche
informali.
Questa animazione ripetuta spero aiuti a comprendere ciò che vogliamo
realizzare:
Per scambiare i numeri sulla scacchiera è possibile
usare i tasti freccia o usare il mouse. Usando i tasti freccia, si può
portare il numero adiacente alla posizione libera nella casella vuota; il
numero si sposterà nella direzione della freccia. Usando il mouse,
si può fare clic su un numero adiacente alla posizione libera ed esso
si sposterà nella casella vuota. Attraverso un'adeguata combinazione
di spostamenti dei numeri si deve ordinare l'intera scacchiera nel minor
numero di mosse.
Il pulsante "New Game" serve per far ripartire un nuovo gioco che inizia
con tutti i numeri disordinati casualmente.
- Specifiche generali del
software:
- Il gioco deve poter essere eseguito on-line sulla
rete Internet.
- Deve essere codificato in un linguaggio object-oriented.
La scelta cade inevitabilmente, per le sue caratteristiche, su Java.
- Deve avere una presentazione grafica.
- Specifiche del
gioco:
- La scacchiera
deve essere composta da celle che possono contenere numeri da 1 a 24 e una
cella vuota.
- Obiettivo del gioco è ordinare i numeri in modo crescente,
dalla prima riga fino alla quinta e da sinistra verso destra attraverso
spostamenti successivi.
- Può essere spostato solo un numero adiacente alla posizione vuota
(un numero a destra, a sinistra, in alto o in basso rispetto
alla posizione vuota).
- Vi è un pulsante "New Game" che consente di iniziare un nuovo
gioco che parte con tutti i numeri disordinati casualmente. Appena compare
la prima volta il gioco è già inizializzato. Il pulsante "New
Game" viene attivato attraverso il mouse.
- L'utente deve poter interagire con il gioco sia attraverso il mouse
che con i tasti freccia.
- Durante l'esecuzione devono essere visualizzati sia il numero di mosse
che il punteggio.
- Specifiche del punteggio del
gioco:
- Il giocatore ha a disposizione 800 mosse per terminare il gioco.
- Durante il gioco, dopo ogni 80 mosse, vi è una penalizzazione
di 350 punti; inoltre, le righe non ancora ordinate, subiscono un rimescolamento
casuale, la cui intensità è proporzionale al numero di mosse
compiute fino a quel momento.
- Il punteggio viene assegnato dopo l'ordinamento di una singola riga,
e sommato progressivamente ai punteggi assegnati per l'ordinamento di precedenti
righe, secondo la seguente tabella:
Riga ordinata |
Punti(*) |
riga 1 -
|
1.000 |
riga 2 -
|
2.000 |
riga 3 -
|
3.000 |
riga 4 -
|
4.000 |
riga 5 -
|
8.000 |
- Dal punteggio complessivo viene sottratto il numero di mosse compiute sino
a quel momento.
- Specifiche dei
suoni:
- Un suono sarà emesso dopo ogni mossa.
- Un suono sarà emesso quando i numeri
della scacchiera vengono rimescolati.
- Un suono sarà emesso all'inizio di un nuovo gioco o quando
il gioco viene completato con successo.
- Un suono sarà emesso al completamento di una riga.
Disegno software object-oriented.
L'inizio della progettazione software, seguendo i principi esposti nel primo articolo, inizia analizzando la definizione del problema e le specifiche precedentemente indicate. Gli oggetti vengono individuati sia analizzando il testo del problema, che le specifiche prodotte.
Gli oggetti saranno preceduti dal simbolo *, gli attributi dal simbolo +, mentre i metodi dal simbolo --, i nomi delle classi dal simbolo §.
- Identificazione degli oggetti
principali:
Dalle specifiche dei requisiti si possono individuare i seguenti oggetti
principali:
* Il Puzzle
L'oggetto puzzle è l'astrazione dell'intero gioco. E' l'oggetto
che conterrà tutti gli altri oggetti. Esso è composto da una
scacchiera (composta a sua volte da celle), dal pulsante "New Game",
dagli indicatori del numero di mosse e di punti. Un puzzle può
essere Inizializzato, Eseguito, Interrotto ecc.
* La Scacchiera
La scacchiera dei numeri è un altro oggetto principale. Essa
è una matrice di celle ed ha un certo numero di righe e colonne.
Poichè ogni cella ha la stessa dimensione, attributi della
scacchiera saranno anche la larghezza e l'altezza in pixel di ogni
cella. Altro metodo è ScambioCelle che consente lo scambio di una
cella che contiene un numero con la cella vuota adiacente.
* La Calcolatrice
Attraverso questo oggetto si realizza la gestione del numero di mosse compiute
e del punteggio durante il gioco. Operazioni della nostra calcolatrice sono
Reset per azzerarla, Incremento e Decremento (in caso di penalizzazione)
Punti e Incremento Mosse.
- Individuazione degli attributi
degli oggetti principali:
* Il Puzzle
+ TheScac: la scacchiera del gioco.
+ Calc: La calcolatrice del gioco.
+ Mossa : suono emesso dopo ogni mossa.
+ Vittoria: suono emesso quando il gioco viene completato o quando
viene inizializzato.
+ RigaOrdinata: suono emesso quando una riga viene ordinata.
+ Disordine: suono emesso al momento del rimescolamento dei numeri.
+ g: l'ambiente grafico del gioco.
+ bNewGame: il pulsante "New Game".
+ fileIm: vettore contenente i nomi dei file delle immagini delle
celle in ordine (vettore di costanti).
* La Scacchiera
+ Larghezza: un numero che indica la larghezza
in pixel di ogni cella della scacchiera.
+ Altezza: un numero che indica
l'altezza in pixel di ogni cella della scacchiera.
+ NumRigh: numero di righe della
scacchiera.
+ NumCol: numero di colonne della
scacchiera.
+ Mappa: una matrice che contiene
le celle con i numeri. (cella è un
oggetto secondario da definire)
* La Calcolatrice
+ Mosse:
numero corrente di mosse compiute.
+ Punti:
numero di punti del gioco.
- Identificazione degli oggetti secondari e dei relativi attributi:
* La Cella
+ col: la coordinata colonna
della cella nella scacchiera.
+ rig: la coordinata riga della cella
nella scacchiera.
+ immagine: l'immagine contenuta nella
cella.
+ NomeFile: il nome del file contenente
l'immagine della cella.
+ IsNumero: un valore boolean che indica
se la cella contiene un numero (true) o una cella vuota (false).
- Sviluppo di una gerarchia
delle classi:
Alcune precisazioni sulla terminologia: finora abbiamo
parlato di oggetti, ora invece iniziamo a parlare di classi. Come è
noto una classe è un modello, mentre un oggetto viene generato
da una classe attraverso una sua istanza. Ora definiremo le classi a
partire dalle quali saranno generati gli oggetti di cui abbiamo parlato,
oggetti che serviranno in effetti per far "girare" il
programma.
La gerarchia inizia con la super-classe Java "Object"
dalla quale discende ogni altra classe. Component, Container e
Panel sono, così come Object, classi predefinite Java che sono
state indicate per completezza. La classe principale §Puzzle, dovendo
il programma essere integrato in una pagina Web, sarà una sottoclasse
della classe Applet. Gli attributi identificati nel progetto sono racchiusi
tra le parentesi.
§Object
§Component
§Container
§Panel
§Applet
§Puzzle(TheScac,
Calc, Mossa, Vittoria, RigaOrdinata,
Disordine, g, bNewGame,
fileIm)
§Scacchiera(Larghezza, Altezza,
NumRigh, NumCol, Mappa)
§Calcolatrice(Mosse, Punti)
§Cella(col, rig, immagine,
NomeFile, IsNumero)
- Identificazione e definizione
dei principali metodi per gli oggetti principali e
secondari.
* Il Puzzle
-- Init: L'inizializzazione del Puzzle, e
quindi dell'applet, avverrà con questo metodo. Tale inizializzazione
si verificherà quando il Puzzle sarà caricato. Prevede la creazione
e inizializzazione della Scacchiera con l'assegnazione delle immagini
alle sue celle, la creazione di una Calcolatrice. Infine il metodo
rimescolerà le righe della scacchiera.
-- Run: L'esecuzione del Puzzle avverrà attraverso questo metodo. In effetti il metodo non fa nulla, ma aspetta che l'utente premi un tasto freccia o faccia click su un numero. Quando si verificherà uno di questi eventi, allora sarà eseguito o il metodo handleEvent o keyDown.
-- handleEvent: Questo metodo è un metodo fondamentale perchè avrà il compito di catturare l'evento click del mouse e richiamerà il metodo di ScambioCelle della Scacchiera. Questo metodo intercetterà anche la pressione del pulsante "New Game".
-- keyDown: Questo metodo realizza una funzione analoga a quella del metodo precedente, ma invece che catturare un evento provocato dalla tastiera, rileverà la pressione di un tasto freccia.
-- stop: Questo metodo fermerà il
gioco.
* La Scacchiera
-- Create: Questo metodo serve per creare
nuovi oggetti Scacchiera (è il metodo costruttore)
-- ScambioCelle: Scambia di due celle le immagini, le proprietà "Isnumero" e i files contenenti le immagini. Questo metodo sarà richiamato ogni volta che si dovrà spostare un numero nella posizione libera (cella vuota).
-- Casuale(rig): Dispone casualmente i numeri della scacchiera a partire dalla riga successiva a quella specificata dal parametro rig.
-- Fatto(VetIm): La scacchiera, con questo metodo, restituirà True se i nomi dei file delle immagini del vettore VetIm, passato come parametro, coincideranno, nell'ordine, con i nomi dei file delle immagini delle celle. In tal caso la scacchiera sarà ordinata, in caso contrario restituirà False. Il parametro effettivamente passato al momento dell'invocazione del metodo sarà l'attributo fileIm dell'oggetto Puzzle.
* La Cella
-- Create: Questo metodo serve per creare
nuovi oggetti Cella (è il metodo costruttore).
* La Calcolatrice
-- Create: Questo metodo serve per creare nuovi oggetti Calcolatrice(è
il metodo costruttore). Questo metodo genererà una nuova calcolatrice
con Mosse =0 e Punti =0.
-- DecPunteggio(valore): Diminuisce il punteggio di una quantità pari al parametro "valore". Questo metodo sarà usato per realizzare le penalizzazioni di punteggio.
-- IncPunteggio(valore): Incrementa il punteggio di una quantità pari al parametro "valore".Questo metodo sarà usato per l'incremento di punteggio quando sarà completata una riga.
-- IncMosse: Incrementa di 1 il numero di mosse. Sarà richiamato dopo ogni mossa eseguita.
-- Reset: Resetta la calcolatrice azzerando Mosse e
Punti. Sarà richiamato alla partenza di un nuovo gioco, ovvero quando
l'utente farà click sul pulsante "New Game".
- Sviluppo di un prototipo di
soluzione utilizzando i metodi degli oggetti.
Utilizzando un approccio top-down si possono utilizzare i metodi principali dell'oggetto Puzzle(il gioco) per definire uno scheletro della soluzione software che generata nella fase di codifica. Questo passo rappresenta la linea di confine tra la fase di progettazione e quella di codifica. Si possono prevedere più livelli.
Ad un primo livello il prototipo di soluzione
sarà:
Puzzle.Init
Puzzle.Run
Puzzle.stop
Ad un secondo livello possiamo specificare meglio cosa accadrà con l'esecuzione dei precedenti metodi:
Puzzle.Init:
TheScac = new Scacchiera //crea la scacchiera
TheScac
inizializzazione delle immagini della scacchiera creata
TheScac.Casuale(0)
emette il suono del disordine
Calc = new Calcolatrice()
//crea la calcolatrice Calc
Puzzle.Run:
In effetti questo metodo non fa proprio nulla! Ovvero
sono i metodi handleEvent e keyDown che intercettano rispettivamente
il click del mouse e la pressione di un tasto all'interno del riquadro
del gioco.
Ad un terzo livello del prototipo possiamo specificare i due metodi Puzzle.handleEvent e Puzzle.keyDown:
Puzzle.handleEvent
Intercetta le coordinate della cella
dove si è fatto click
TheScac.ScambioCelle //scambio celle
Calc.IncMosse
// Incrementa le mosse
emette il suono della mossa
Se è stata completata una riga allora
Calc.IncPunteggio(valore)
//Incrementa il punteggio
emette il suono della riga
completata
Se Calc.Mosse è un multiplo di 80 allora
Calc.DecPunteggio(350) //
Penalizzazione
Casuale(riga); //
Rimescola le righe non ordinate
emette il suono del disordine
Se TheScac.Fatto(fileIm) = true allora
emette il suono del completamento gioco
stop // fine
gioco
Puzzle.keyDown
Le operazioni realizzate da questo metodo sono identiche
al metodo Puzzle.hendleEvent con la differenza che sono svolte in funzione
del tipo di tasto freccia premuto.
- Rielaborazione delle classi per renderle più generiche, possibilmente riusabili e per raggrupparle in moduli.
Le classi Scacchiera, Calcolatrice e Cella vengono,
in questo passo, riunite in un Package Java.
Questo è tutto. Nel prossimo articolo analizzeremo il codice delle
classi racchiuse nel package chiamato PuzzleClass e il codice dell'applet
Puzzle.