gioco del Tris

Analisi del problema
Scaricare le due immagini, formato jpg, nella stessa cartella in cui si scriverà l'applicazione. Assegnare i nomi indicati.
ics.jpgO.jpg

Per simulare il comportamento di un giocatore si deve realizzare un programma che adotti una strategia che cerca di vincere, osservando però, che se la scelta non è vincente, deve comunque impedire all'avversario di fare una mossa vincente, o deve bloccare il gioco vincente dell'avversario.

La strategia vincente può essere ripepilogata nel seguente comportamento:
Preferire, nell'ordine, le seguenti mosse:

Strutture dati impiegate
Le posizioni della griglia di gioco siano numerate a partire da 0, nel seguente ordine:
 0  1  2 
 3  4  5 
 6  7  8 
Si usano due variabili: in ognuna delle quali un bit a livello 1 indica la presenza della marca, X o O, nella corrispondente casella della griglia. Ad esempio se i bit nella variabile Ics sono disposti come segue:
 8  7  6   5  4  3   2  1  0 
Ics:    1  0  0   1  0  0   0  0  0 

e i bit nella variabile O sono disposti come segue:
 8  7  6   5  4  3   2  1  0 
O:    0  1  0   0  0  1   1  0  0 
vuol dire che sulla griglia le marche sono disposte nel modo seguente:
 0  1   
   4   
 6     
I 9 bit in ciascuna delle due variabili danno luogo a 512 possibili combinazioni. Si crea quindi un array, denominato Allineate di 512 elementi di tipo boolean dove i contenuti delle variabili X e O sono usati come indice per accedere all'array. Solo nelle locazioni il cui indice corrisponde a tre caselle allineate c'è true in tutte le altre locazioni dell'array c'è false.


Operatori di scorrimento
Un operatore di scorrimento che compare in un'espressione comporta che i bit di una variabile vengano spostati di una posizione verso destra o verso sinistra.

Gli operatori di scorrimento si indicano con i simboli: Ad esempio se la variabile Ics contiene i seguenti bit:
 8  7  6   5  4  3   2  1  0 
Ics:    0  0  0   1  0  1   0  0  0 
lo scorrimento di 1 bit verso sinistra si ottiene con l'istruzione:
Ics << 1
I bit della variabile si portano nella seguente configurazione:
 8  7  6   5  4  3   2  1  0 
Ics:    0  0  1   0  1  0   0  0  0 


lo scorrimento di 1 bit verso destra si ottiene con l'istruzione:
Ics >> 1

Proprietà della classe
Le librerie da includere nella compilazione comprendono, oltre ad awt, anche la libreria Applet:


Si dichiara una classe derivata da una classe Applet, che ridefinisce i gestori degli eventi generati dal mouse:

Le variabili Tondo e Ics codificano, con i loro bit a 1, le posizioni dei corrispondenti segni sulla griglia.
La variabile primo indica chi deve cominciare la partita.
I due riferimenti a Immagini verranno inizializzati nel costruttore.
La classe contiene un array di costanti intere che rappresentano l'ordine delle mosse da tentare di compiere.
Le altre costanti definite nella classe sono di ovvio significato.

Tra i metodi della classe viene definito quello che annota le configurazioni di caselle allineate, che se occupate da una stessa pedina, assegnano una vittoria.

La funzione segnaVincenti riceve come parametro un numero che ha 3 bit a 1 in uno dei possibili allineamenti.
La funzione scandisce tutti gli indici dell'array e se trova un indice che ha i 3 bit, passati come parametro, a livello 1, annota che quell'elemento è vincente.
la funzione segnaVincenti viene chiamata dal metodo init() ricevendo come parametro una configurazione vincente
ad esempio: la prima riga corrisponde alla configurazione 0000 0111, perché sono a 1 i bit in posizione 0, 1 e 2
risultano vincenti tutte le configurazioni con qualsiasi altro bit a 1:
0000 1111 (15),
0001 0111 (23),
0001 1111 (31)
0010 0111 (39),
0010 1111 (47),
0011 1111 (63)
ecc.

Applicare la strategia
La funzione mossaMigliore riceve due parametri, con cui decidere la mossa più favorevole per il computer. Usa una variabile intera per restituire il numero della casella in cui segnare la marca X o O, ed usa una variabile booleana per segnare le caselle in cui evitare di giocare perchè farebbero vincere l'avversario.


La funzione esamina ognuna delle mosse, nell'ordine consigliato, (vedere figura successiva: ciclo con i che varia da 0 a 8) prelevandole dall'array sequenzaMosse:
l'espressione: 1 << m0 fa scorrere un 1 di m0 bit a sinistra.
Per vedere se la posizione m0 è libera si applica l'operatore And come descritto nella seguente espressione:.

Se la posizione m0 è libera, cioè sia
Tondo And (1 << m0)
E
Ics And (1 << m0)
danno entrambe risultato 0,
Allora si simula la mossa in una variabile temporanea tmpO con la quale si accede all'array Allineate per vedere se la mossa è vincente.
se lo è si restituisce quella coordinata.
Altrimenti si esaminano tutte le posizioni occupate dal giocatore e se si trova che posizionando la marca O in posizione m0 l'avversario vince allora si passa alla successiva mossa consigliata.
se invece la mossa m0 non fa vincere l'avversario la si effettua.


Se si è trovata una posizione che non fa vincere nessuno, la si effettua comunque.


Altrimenti si restituisce la successiva mossa consigliata.

Viene restituito il valore -1 quando non ci sono più mosse possibili (il gioco è terminato).

Avanzamento del gioco
Muove il giocatore. Se la sua scelta è consentita, la funzione mossaGiocatore ritorna true


La funzione mossaMia esamina la scelta del computer. Se tutte le caselle sono piene ritorna false altrimenti cerca la mossa migliore e la effettua.


La funzione status riporta lo stato del gioco: Se nessuno ha vinto, il gioco continua.


La funzione init() è richiamata quando l'applet viene avviata. Quindi viene usata per assegnare i valori iniziali alle variabili.

All'interno della funzione init() vengono segnate tutte le configurazioni che corrispondono ad un allineamento.

Gestori di Evento
Quando l'applet termina il gestore del mouse viene eliminato dalla memoria.

la funzione paint() viene richiamata dopo init() per disegnare l'area occupata dall'applet.

Vengono dapprima calcolate le dimensioni riservate all'applet. Queste dimensioni vengono divise per 3 allo scopo di dividere l'area in 9 quadranti.

La funzione paint() viene anche richiamata con repaint() per disegnare le marche X e O nelle posizioni memorizzate nelle variabili Ics ed O.


Il gestore dell'evento mouse Released richiama repaint() dopo aver esaminato la legittimità della mossa.

Richiamare l'applet
L'applet viene ospitata in una pagina web:


Esempio
Prova il gioco.