#include <stdio.h>
#include <conio.h>
int InKey
( void );
void Maschera ( int );
void ValutaMossa ( int *, int, int, int *, int * );
/*--------------------------- T R I S ---------------------------------------
Programmma per il gioco del Tris tra due giocatori scelti tra:
-) Umano ( tramite keyboard )
-) PC ( tramite sub di valutazione mossa )
La tavola di gioco (una scacchiera 3x3) viene allocata in un vettore;
ogni casella della Tavola vale 0 se vuota, 1 se occupata dal giocatore 1,
2 se occupata dal giocatore 2.
La valutazione della mossa migliore in ogni fase del gioco viene affidata
ad una funzione ricorsiva, che deve essere in grado di valutare la mossa
perfetta.
---------------------------------------------------------------------------*/
void main ( void )
{ int Giocatori, // giocatori attivi:
// 0 : Umano - Umano
// 1 : Computer - Umano
// 2 : Umano - Computer
Who,
// giocatore che deve muovere: 1(primo) o 2
Tavola[10], // scacchiera di gioco
Nvuote,
// numero delle caselle vuote (con valore 0)
DoveGioco, // mossa da fare da parte di Who
QuantoVale, // valore della mossa (vista da Who)
Finito,
// -1 = configurazione iniziale
// 0 = gioco in corso
// 1 = gioco finito (vinto 1)
// 2 = gioco finito (vinto 2)
// 3 = gioco finito in pareggio
// 27 = gioco finito per abbandono
i;
Maschera (-1); //------------------- Visualizza il campo di gioco
Finito = -1;
do
{ switch ( i=InKey() )
{ case 27 : Giocatori = 0; Finito = 27; break; // Abbandono
case 315 : Giocatori = 0; Finito = 0; break; // Umano - Umano
case 316 : Giocatori = 1; Finito = 0; break; // Computer - Umano
case 317 : Giocatori = 2; Finito = 0; break; // Umano - Computer
}
}
while (Finito < 0);
for (i=0; i<10; Tavola[i++]=0 ); // pulizia scacchiera
Maschera (Giocatori);
Who = 1;
Nvuote = 9;
textcolor(2); gotoxy ( 2, 16); cprintf("9 Caselle Vuote");
//=============================== ciclo delle mosse ======================
while (!Finito)
{ textcolor(13+Who); gotoxy (32, 23);
cprintf ("Muove il giocatore %d \n", Who);
DoveGioco = -1;
if (Giocatori == Who) // mossa decisa dalla funzione di valutazione
{ gotoxy (2, 18); textcolor(12); cprintf(" ATTENDERE ! ");
ValutaMossa (Tavola, Nvuote, Who, &DoveGioco, &QuantoVale);
textcolor(13+Who);
gotoxy (2, 18); cprintf("\aMossa %c ", DoveGioco+48);
if (QuantoVale < 0)
cprintf("perdente");
else if (QuantoVale > 0) cprintf("vincente");
else
cprintf("pareggio");
}
else // mossa del giocatore umano tramite keyboard
{ if ( (i = InKey() ) == 27)
Finito = 27;
else if (i>=49 && i<=57 && Tavola[i-48]==0) // 123456789
DoveGioco = i-48;
else if (i==319) // F5 help mossa migliore
{ gotoxy (2, 18); textcolor(12); cprintf(" ATTENDERE ! ");
ValutaMossa (Tavola, Nvuote, Who, &DoveGioco, &QuantoVale);
textcolor(13+Who);
gotoxy (2, 18); cprintf("\aMossa %c ", DoveGioco+48);
if (QuantoVale < 0)
cprintf("perdente");
else if (QuantoVale > 0) cprintf("vincente");
else
cprintf("pareggio");
DoveGioco = -1;
}
}
if (DoveGioco >= 0)
{ Tavola[DoveGioco] = Who; Nvuote --; // occupa la casella
if ( Tavola[1] & Tavola[2] & Tavola[3] ||
// 1° rigo
Tavola[4] & Tavola[5] & Tavola[6] ||
// 2° rigo
Tavola[7] & Tavola[8] & Tavola[9] ||
// 3° rigo
Tavola[1] & Tavola[4] & Tavola[7] ||
// 1° colonna
Tavola[2] & Tavola[5] & Tavola[8] ||
// 2° colonna
Tavola[3] & Tavola[6] & Tavola[9] ||
// 3° colonna
Tavola[1] & Tavola[5] & Tavola[9] ||
// diagonale /
Tavola[7] & Tavola[5] & Tavola[3] )
// diagonale \
Finito = Who; // mossa vincente
else if ( Nvuote == 0 ) Finito = 3;
// pareggio
else
Who ^= 3;
// passa all'avversario
for (i=9; i; i--) // Visualizza le pedine sul campo di gioco
if (Tavola[i]) gotoxy (49+((i-1)%3)*10, 16-((i-1)/3)*4 ),
textcolor (16-Tavola[i]),
cprintf ("%c", 97-Tavola[i]*9 );
textcolor(2); gotoxy(2,16); cprintf("%2d Caselle Vuote",Nvuote);
}
}
textbackground(0); textcolor(12); gotoxy (30, 23);
switch (Finito)
{ case 1: cprintf (" Vittoria al giocatore X
\n"); break;
case 2: cprintf (" Vittoria al giocatore O
\n"); break;
case 3: cprintf (" Partita pareggiata
\n"); break;
case 27: cprintf (" Conclusione per Abbandono \n"); break;
}
while (getch()!= 27); // ESC per uscire dal gioco
}
/*===========================================================================
Funzione per la valutazione della mossa migliore in un dato stato del gioco
supponendo che ciascuno giochi 'al meglio':
La mossa vincente vale maggiormente se fatta a inizio partita.
--------------------------------------------------------------------------*/
void ValutaMossa
( int *Tavola, // scacchiera di gioco
int Nvuote, // numero delle caselle vuote
int Who, // giocatore che deve muovere: 1 o 2
int *DoveMeglio, // casella della mossa migliore
int *MaxVale // valore della scacchiera vista da Who:
// <=-1 sconfitta, 0 pareggio, >=1 vittoria.
)
{ int i, // indice sulle caselle della scacchiera
Dove, // miglior contromossa dell'avversario
Vale; // valore della contromossa
// valuta tutte le mosse possibili;
for (*MaxVale= -99, i=9; i ; i--)
if (Tavola[i]==0) // se la casella Š vuota
{ Tavola[i] = Who; // occupa la casella
if ( Tavola[1] & Tavola[2] & Tavola[3] || // 1° rigo
Tavola[4] & Tavola[5] & Tavola[6] || // 2° rigo
Tavola[7] & Tavola[8] & Tavola[9] || // 3° rigo
Tavola[1] & Tavola[4] & Tavola[7] || // 1° colonna
Tavola[2] & Tavola[5] & Tavola[8] || // 2° colonna
Tavola[3] & Tavola[6] & Tavola[9] || // 3° colonna
Tavola[1] & Tavola[5] & Tavola[9] || // diagonale /
Tavola[7] & Tavola[5] & Tavola[3] ) // diagonale \
{ Vale = Nvuote;
// mossa vincente
}
else if (Nvuote == 1) // se era l'unica casella vuota, pareggio
{ Vale = 0;
}
else // situazione ancora tutta da valutare
{ // chiede il parere dell'avversario, e poi considera il suo
// miglior punteggio (Vale) cambiato di segno (strategia NegMax)
ValutaMossa (Tavola, Nvuote-1, Who^3, &Dove, &Vale);
Vale = -Vale;
}
if (Vale > *MaxVale) *MaxVale = Vale, *DoveMeglio = i;
Tavola[i] = 0; // libera la casella
}
}
/*===========================================================================
Maschera di gioco
--------------------------------------------------------------------------*/
void Maschera
( int Gioc // -1 maschera per la configurazione iniziale
// 0 maschera gioco Umano - Umano
// 1 maschera gioco Computer - Umano
// 2 maschera gioco Umano - Computer
)
{ int i;
clrscr();
textbackground(4); textcolor(0);
gotoxy( 2, 1); for (i=2; i<=79; cprintf(" "),i++);
gotoxy(37, 1); cprintf("T R I S");
gotoxy( 2,25); for (i=2; i<=79; cprintf(" "),i++);
gotoxy(58,25); cprintf("di Luigi Lamberti");
textbackground(0); textcolor(2);
gotoxy (44, 6); cprintf ("+---------+---------+---------+");
gotoxy (44, 7); cprintf ("|
| |
|");
gotoxy (44, 8); cprintf ("|
| |
|");
gotoxy (44, 9); cprintf ("|7
|8 |9
|");
gotoxy (44, 10); cprintf ("+---------+---------+---------+");
gotoxy (44, 11); cprintf ("|
| |
|");
gotoxy (44, 12); cprintf ("|
| |
|");
gotoxy (44, 13); cprintf ("|4 |5
|6 |");
gotoxy (44, 14); cprintf ("+---------+---------+---------+");
gotoxy (44, 15); cprintf ("|
| |
|");
gotoxy (44, 16); cprintf ("|
| |
|");
gotoxy (44, 17); cprintf ("|1 |2
|3 |");
gotoxy (44, 18); cprintf ("+---------+---------+---------+");
if (Gioc == -1)
{ textcolor(11);
gotoxy (2, 3); cprintf ("F1 : Umano - Umano");
gotoxy (2, 5); cprintf ("F2 : Computer - Umano");
gotoxy (2, 7); cprintf ("F3 : Umano - Computer");
gotoxy (2,13); cprintf ("ESC : interrompe gioco");
textcolor(1);
gotoxy (2, 9); cprintf ("F5 : help mossa migliore");
gotoxy (2,11); cprintf ("123..789 : inserisci mossa");
}
else
{ textcolor(1);
gotoxy (2, 3); cprintf ("F1 : Umano - Umano");
gotoxy (2, 5); cprintf ("F2 : Computer - Umano");
gotoxy (2, 7); cprintf ("F3 : Umano - Computer");
textcolor(11);
gotoxy (2, 9); cprintf ("F5 : help mossa migliore");
gotoxy (2,11); cprintf ("123..789 : inserisci mossa");
gotoxy (2,13); cprintf ("ESC : interrompe gioco");
switch (Gioc)
{ case 0: gotoxy (13, 3); cprintf ("Umano - Umano"); break;
case 1: gotoxy (13, 5); cprintf ("Computer - Umano"); break;
case 2: gotoxy (13, 7); cprintf ("Umano - Computer");
}
}
}
/*============================================================= InKey ======
Lettura di un carattere da tastiera: attende che venga battuto;
OUT: Il codice Ascii oppure, il codice del tasto speciale:
Return:13 Esc:27 F1:315 F2:316 F3:317 F5:319 ecc...
-------------------------------------------------------------------------*/
int InKey (void)
{ int Tast; // codice numerico del tasto premuto;
Tast = getch();
if (Tast == 0) Tast = getch() + 256;
return ( Tast );
}
|