Ciao
Questa è una breve implementazione che ho fatto io, manca ancora la parte grafica ma a quella ci penseremo più avanti. Dovresti assicurarti di capire bene come funziona il codice, tenendo anche da conto che questa è una mia interpretazione e potrebbe non rispecchiare le tue richieste...
public enum Players
{
Nessuno = 0,
X,
O,
GiocatoreUno = X,
GiocatoreDue = O
}
public enum DirezioneDiagonale
{
NordOvest_SudEst,
NordEst_SudOvest,
SudOvest_NordEst = NordEst_SudOvest,
SudEst_NordOvest = NordOvest_SudEst
}
public class Griglia
{
/// <summary>
/// Ogni cella della griglia è rappresentata da un elemento di questo array
/// </summary>
private Players[,] celle;
public Griglia()
{
//Inizializza l'array delle celle (per default sono impostate a 0 = Vuoto)
this.celle = new Players[3, 3];
}
/// <summary>
/// Ottiene il valore della cella in posizioni [x, y]
/// </summary>
/// <param name="x">Indice della colonna</param>
/// <param name="y">Indice della riga</param>
public Players this[int x, int y]
{
get
{
CheckBounds(x, y);
//Ottiene il valore della casella richiesta
return celle[x, y];
}
set
{
CheckBounds(x, y);
//Imposta il valore della casella richiesta
celle[x, y] = value;
}
}
public Players[] Riga(int indice)
{
CheckBounds(indice);
//Costruisce la riga e la ottiene
Players[] riga = new Players[3];
for (int x = 0; x < 3; x++)
{
riga[x] = celle[x, indice];
}
return riga;
}
public Players[] Colonna(int indice)
{
CheckBounds(indice);
//Costruisce la colonna e la ottiene
Players[] colonna = new Players[3];
for (int y = 0; y < 3; y++)
{
colonna[y] = celle[indice, y];
}
return colonna;
}
public Players[] Diagonale(DirezioneDiagonale direzione)
{
//Costruisce la diagonale e la ottiene
Players[] diagonale = new Players[3];
if (direzione == DirezioneDiagonale.NordOvest_SudEst)
{
for (int i = 0; i < 3; i++)
{
diagonale[i] = celle[i, i];
}
}
else if (direzione == DirezioneDiagonale.NordEst_SudOvest)
{
for (int i = 0; i < 3; i++)
{
diagonale[i] = celle[2 - i, i];
}
}
else
{
throw new ArgumentException("direzione");
}
return diagonale;
}
/// <summary>
/// Controlla che i valori siano tutti indici validi (0..2),
/// in caso contrario solleva un'eccezione
/// </summary>
private void CheckBounds(params int[] values)
{
foreach (int i in values)
{
if (i < 0 || i >= 3)
throw new IndexOutOfRangeException(
String.Format("\"{0}\" non è un valore corretto.\r\n" +
"Previsto un indice compreso fra 0 e 2", i));
}
}
public void Reset()
{
//Azzera il proprietario di ogni cella
for (int x = 0; x < 3; x++)
{
for (int y = 0; y < 3; y++)
{
this.celle[x, y] = Players.Nessuno;
}
}
}
}
public class Controllo
{
private Griglia griglia;
public Controllo(Griglia griglia)
{
this.griglia = griglia;
}
public Players ControllaVincitore()
{
if (griglia == null)
return Players.Nessuno;
//Cicla fra le tre righe e colonne e le duagonali,
//controllando se uno dei giocatori ha vinto
Players player = Players.Nessuno;
for (int i = 0; i < 3; i++)
{
player = ControllaLista(griglia.Riga(i));
if (player != Players.Nessuno)
return player;
player = ControllaLista(griglia.Colonna(i));
if (player != Players.Nessuno)
return player;
}
player = ControllaLista(griglia.Diagonale(DirezioneDiagonale.NordOvest_SudEst));
if (player != Players.Nessuno)
return player;
player = ControllaLista(griglia.Diagonale(DirezioneDiagonale.NordEst_SudOvest));
return player;
}
private Players ControllaLista(Players[] lista)
{
//Se almeno due valori sono diversi, non c'è un vincitore
if (lista[0] != lista[1] || lista[1] != lista[2])
return Players.Nessuno;
//Se sono tutti uguali, ottiene il vincitore
return lista[0];
}
}
public class Partita
{
private Griglia griglia;
private Controllo controllo;
private int numMossa;
private Players primoGiocatore;
private Point[] storia;
private Players giocatore;
public Partita()
{
this.griglia = new Griglia();
this.controllo = new Controllo(griglia);
this.numMossa = 0;
this.storia = new Point[9];
this.giocatore = Players.Nessuno;
this.primoGiocatore = Players.Nessuno;
}
/// <summary>
/// Esegue una mossa, e ritorna l'id del giocatore che ha vinto la partita
/// </summary>
public Players FaiMossa(int x, int y)
{
//Se la partita non è ancora iniziata, solleva un'eccezione
if (this.giocatore == Players.Nessuno)
throw new Exception("La partita non è ancora iniziata o è finita.");
//Controlla se la casella è libera
if (griglia[x, y] != Players.Nessuno)
throw new Exception(String.Format(
"La casella in posizione [{0},{1}] è già occupata.", x, y));
//Imposta la casella sul giocatore corrente
griglia[x, y] = giocatore;
//Imposta la mossa nella storia
this.storia[this.numMossa++] = new Point(x, y);
//Controlla se c'è un vincitore
Players winner = this.controllo.ControllaVincitore();
if (winner != Players.Nessuno)
{
//Giocatore corrente: nessuno
this.giocatore = Players.Nessuno;
//Ottiene il vincitore
return winner;
}
//Controlla se era l'ultima mossa. Se sì, la partita è finita con un pareggio
if (numMossa == 9)
{
this.giocatore = Players.Nessuno;
return Players.Nessuno;
}
//Passa al giocatore successivo
this.giocatore = (this.giocatore == Players.O ? Players.X : Players.O);
//Nessun vincitore
return Players.Nessuno;
}
/// <summary>
/// Inizia una nuova partita
/// </summary>
public void NuovaPartita(Players primoGiocatore)
{
if (primoGiocatore != Players.O && this.giocatore != Players.X)
throw new Exception("primoGiocatore");
//Resetta la griglia
this.griglia.Reset();
//Imposta il numero di mosse a 0
this.numMossa = 0;
//Imposta il giocatore corrente e il primo giocatore
this.giocatore = this.primoGiocatore = primoGiocatore;
}
/// <summary>
/// Ritorna true se il gioco è concluso, altrimenti false
/// </summary>
public bool FineDelGioco
{
get
{
return (this.giocatore == Players.Nessuno);
}
}
/// <summary>
/// Ottiene il giocatore che ha segnato la cella [x, y]
/// </summary>
public Players Cella(int x, int y)
{
return this.griglia[x, y];
}
public Point[] Storia(out Players primoGiocatore)
{
//Se la partita non è ancora cominciata solleva un'eccezione
if (this.primoGiocatore == Players.Nessuno)
throw new Exception("Non è stata ancora cominciata nessuna partita");
//Crea un array di Point, e copia le posizioni delle caselle in ordine cronologico
Point[] res = new Point[this.numMossa];
for (int i = 0; i < numMossa; i++)
{
res[i] = this.storia[i];
}
//Ottiene in uscita il giocatore che ha fatto la prima mossa
primoGiocatore = this.primoGiocatore;
//Ottiene il risultato
return res;
}
}
Luca