Ordine di valutazione delle scelte per una strategia ottimale del gioco del tris:
Vincere: Il giocatore che trova una casella libera allineata con due pedine sue, deve giocare in quella casella
Bloccare: Se l'avversario ha una casella libera allineata con due caselle occupate dalle sue pedine, giocare in quella casella per impedirgli di vincere.
Doppia opportunità: Scegliere la casella libera dove si possono creare due opportunità di vincere.
Impedire all'avversario di giocare in una casella dove crea due opportunità di realizzare un allineamento:
Allineare due pedine, per obbligare l'avversario a difendersi, a meno che non si crea un vantaggio per l'vversario. Ad esempio, se "X" ha un angolo, "O" ha il centro, ed "X" ha l'angolo opposto, "O" non deve occupare un angolo per vincere. (Giocando in un angolo, si consente a X di creare du opportunità di vincere.)
Se esiste una possibilità che l'avversario si crei due possibilità di allineare le pedine, bloccare.
Centro: mettere la pedina nella casella centrale.
Angoli opposti: Se l'avversario si trova in un angolo, mettere una pedina nell'angolo opposto.
Angolo vuoto: mettere la pedina in un angolo vuoto.
Lato vuoto: mettere la pedina in una casella laterale vuota.
Un tipico algoritmo per il gioco del tris usa i seguenti dati:
Griglia: un vettore di 9 elementi. Un elemento del vettore contiene
2 per rappresentare una casella vuota,
3 per indicare una casella occupata da X
5 per indicare una casella occupata da O.
Turno: un intero che specifica quale dei due giocatori deve segnare una scelta. La prima mossa è indicata con 1, l'ultima mossa con 9.
L'Algoritmo principale usa tre funzioni:
ottieniDoppia (possibilità di allineare le pedine): restituisce 5 se la casella centrale della griglia è vuota, cioè se Griglia[5]=2. Altrimenti questa funzione restituisce una qualsiasi casella laterale (2,4,6 o 8), cioè esclude gli angoli.
vince(g): restituisce 0 se il giocatore g non può vincere alla prossima mossa, altrimenti restituisce il numero della casella che costituise una mossa vincente per lui. Questa funzione permette al programma sia di vincere, sia di bloccare la mossa vincente dell'avversario. Questa funzione controlla le righe, le colonne e le diagonali. Moltiplicando i valori delle celle allineate, si possono valutare le possibili vittorie. Se il prodotto è 18 (3 x 3 x 2), allora X può vincere. Se il prodotto è 50 (5 x 5 x 2), allora O può vincere. Se si trova che g può creare un allineamento, la funzione deve restituire il numero della cella vuota.
giocaIn(n): Scrive nella cella n il numero 3 (Griglia[n] = 3), se il Turno è dispari, scrive 5 se il turno è pari. Incrementa il turno di 1.
In questo algoritmo le mosse dispari sono effettuate da X, le mosse pari sono effettuate da O.
Turno = 1 giocaIn(0) (angolo superiore sinistro).
Turno = 2 Se griglia[4] è vuota, giocaIn(4), altrimenti giocaIn(0).
Turno = 3 Se griglia[8] è vuota, giocaIn(8), altrimenti giocaIn(2).
Turno = 4 Se vince(X) ritorna ? 0, allora giocaIn(vince(X)) cioè blocca la vittoria dell'avversario, altrimenti giocaIn(ottieniDoppia).
Turno = 5 Se vince(X) ritorna ? 0 allora giocaIn(vince(X)), cioè X vince, altrimenti se vince(O) ritorna ? 0 allora giocaIn(vince(O)) [cioè blocca la vittoria dell'avversario, altrimenti se griglia[6] è libera, allora giocaIn(6), altrimenti giocaIn(2).
Turno = 6 Se vince(O) ritorna ? 0 allora giocaIn(vince(O)), altrimenti se vince(X) ritorna ? 0, allora giocaIn(vince(X)), altrimenti giocaIn(ottieniDoppia()).
Turno = 7 Se vince(X) ritorna ? 0 allora giocaIn(vince(X)), altrimenti se vince(O) ritorna ? 0, allora giocaIn(vince(O)) altrimenti gioca in una qualsiasi casella vuota.
Turno = 8 Se vince(O) ritorna ? 0 allora giocaIn(vince(O)), altrimenti se vince(X) ritorna ? 0, allora giocaIn(vince(X)), altrimenti gioca in una qualsiasi casella vuota.
Turno = 9 identico a Turno = 7.
Resta da definire altre variabili:
stato del gioco: finito (true o false),
esito della partita: vinta da X, vinta da O, pareggiata.
La griglia del gioco viene riprodotta anche in memoria. Le celle della griglia di gioco siano numerate a partire da 0, nel seguente ordine:
0 | 1 | 2 |
3 | 4 | 5 |
6 | 7 | 8 |
Creare un nuovo progetto: nome=TrisControC.
Clic sull'icona Create New Class swing: nome classe=Tris. Modificare le proprietà title e iconImage del frame.
Creare un nuovo package all'interno della cartella src. Denominarla img.
Creare le immagini (dimensioni 70x70) che rappresentano la casella vuota, la casella marcata da X e la casella marcata da O.
![]() | ![]() | |
2.png | 1.png | 0.png |
Memorizzare le immagini nella cartella src/img.
Clic destro nella casella "Package Explorer" e, dal menu a comparsa, scegliere Refresh.
Collocare un componente JButton sul Frame. Modificare la proprietà Variable in C1. Clic sul pulsante con i puntini a destra della proprietà icon. Nella finestra che si apre scegliere la prima opzione (Classpath resource). Nella casella Parameters, aprire la cartella src/img e selezionare l'immagine della casella vuota (0.png). Ok.
Ripetere l'operazione precedente per collocare gli altri 8 JButton sul frame. Cambiare la proprietà variable assegnando i nomi C2, C3, ai pulsanti da sinistra a destra della prima riga, i nomi C4, C5, C6, ai pulsanti da sinistra a destra della seconda riga e C7, C8, C9 ai pulsanti della terza riga.
Creare una nuova classe: File → New → Class (name = Gioco) → Finish.
Aggiungere le proprietà: turno e griglia[] di tipo intero.
public class Gioco {Aggiungere il costruttore.
public Gioco() {Aggiungere il metodo svuota():
private void svuota() {Aggiungere il metodo di accesso alla proprietà:
public int getTurno() {Aggiungere il metodo per individuare se esiste una casella vuota che crea una doppia possibilità di vincere:
public int ottieniDoppia() {Il metodo coppia() valuta per ogni riga, colonna e diagonale se c'è una casella vuota allineata con due caselle occupate dal giocatore XoO. Riceve i parametri a, b e c che rappresentano le coordinate delle celle di una riga, di una colonna o di una diagonale, e il parametro XoO che può assumere il valore 18 corrispondente alle pedine di X o il valore 50 corrispondetente alle pedine di O.
private int coppia(int a, int b, int c, int XoO) {Il metodo vince(g) restituisce la cella in cui il giocatore g può vincere, se non può vincere restituisce -1:
public int vince(int g) {Il metodo giocaIn(casella) scrive 3 per posizionare la pedina X in una cella oppure scrive 5 per mettere la pedina O. Incrementa il turno.
public void giocaIn(int casella) {Applicazione dell'algoritmo:
public int partita() {Passare alla scheda design dell'applicazione Tris (JFrame).
Aggiungere la proprietà alla classe:
private Gioco gioco = new Gioco();
Associare il gestore di evento actionPerformed al pulsante C1. Automaticamente si apre la scheda Source, con il cursore posizionato sull'intestazione del metodo. Completarlo con l'istruzione:
gestore(C1, 0);il primo parametro è il nome della variabile del pulsante su cui si fa clic. Il secondo parametro è l'indice della cella in cui si deve marcare il codice della pedina giocata
Associare i gestori a tutti i pulsanti e completarli come il gestore del pulsante C1.
gestore(C2, 1); // gestore evento actionPerformed del pulsante C2Nella sezione metodi della classe scrivere il metodo gestore:
private void gestore(JButton C, int casella) {Nella sezione metodi della classe aggiungere il metodo:
private void marcaCasella(int cella) {Rendere proprietà della classe i pulsanti dichiarati nel costruttore.
Provare il funzionamento del programma.
Problemi:
Riconoscere la fine di una partita e fermare il gioco.
Comunicare l'esito di una partita.
Consentire di iniziare una nuova partita
Contare le vittorie del computer, del giocatore e le partite pareggiate.