140 lines
3.3 KiB
Java
140 lines
3.3 KiB
Java
|
/**
|
||
|
* ModeleMorpionSimple est une réalisation de l'interface ModeleMorpion en
|
||
|
* utilisant un damier (tableau 3 par 3) pour stocker les symboles...
|
||
|
*
|
||
|
* @author Xavier Crégut
|
||
|
* @version $Revision: 1.2 $
|
||
|
*/
|
||
|
|
||
|
public class ModeleMorpionSimple implements ModeleMorpion {
|
||
|
|
||
|
/** La zone de jeu */
|
||
|
private Etat[][] cases;
|
||
|
|
||
|
/** Le joueur dont c'est le tour de jouer */
|
||
|
private Etat joueur;
|
||
|
|
||
|
/** Le nombres de cases cochées */
|
||
|
private int nbCoups;
|
||
|
|
||
|
/** Est-ce que la partie est gagnée ? */
|
||
|
private boolean gagnee;
|
||
|
|
||
|
public ModeleMorpionSimple() {
|
||
|
// Créer le damier
|
||
|
this.cases = new Etat[ModeleMorpion.TAILLE][ModeleMorpion.TAILLE];
|
||
|
|
||
|
// Commencer une partie
|
||
|
initialiser();
|
||
|
}
|
||
|
|
||
|
/** Est-ce que la partie est terminée ? */
|
||
|
public boolean estTerminee() {
|
||
|
return estGagnee()
|
||
|
|| this.nbCoups >= ModeleMorpion.TAILLE * ModeleMorpion.TAILLE;
|
||
|
}
|
||
|
|
||
|
/** Est-ce qu'il y a un gagnant ? */
|
||
|
public boolean estGagnee() {
|
||
|
return gagnee;
|
||
|
}
|
||
|
|
||
|
/** Est-ce que la case (i,j) est vide ? */
|
||
|
private boolean estVide(int i, int j) {
|
||
|
return getValeur(i,j) == Etat.VIDE;
|
||
|
}
|
||
|
|
||
|
public Etat getValeur(int x, int y) {
|
||
|
return this.cases[x][y];
|
||
|
}
|
||
|
|
||
|
/** Initialiser le jeu pour faire une nouvelle partie */
|
||
|
private void initialiser() {
|
||
|
// Initialiser les cases
|
||
|
for (int i = 0; i < this.cases.length; i++) {
|
||
|
for (int j = 0; j < this.cases[i].length; j++) {
|
||
|
this.cases[i][j] = Etat.VIDE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Initialiser le nb de coups
|
||
|
this.nbCoups = 0;
|
||
|
|
||
|
// Initialiser gagnée
|
||
|
gagnee = false;
|
||
|
|
||
|
// Initialiser le joueur
|
||
|
this.joueur = Etat.CROIX;
|
||
|
}
|
||
|
|
||
|
public Etat getJoueur() {
|
||
|
return this.joueur;
|
||
|
}
|
||
|
|
||
|
/** Changer de joueur */
|
||
|
private void changer() {
|
||
|
if (this.joueur == Etat.CROIX) {
|
||
|
this.joueur = Etat.ROND;
|
||
|
} else {
|
||
|
this.joueur = Etat.CROIX;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** Jouer en (i,j) pour le joueur */
|
||
|
//@ requires estVide(i,j);
|
||
|
//@ ensures getValeur(i,j) == joueur;
|
||
|
private void jouer(int i, int j) {
|
||
|
this.cases[i][j] = this.joueur;
|
||
|
this.nbCoups++;
|
||
|
|
||
|
// Mettre à jour gagnee
|
||
|
// XXX: Ceci ne marche que pour un Morpion de taille 3 !
|
||
|
gagnee = gagnee ||
|
||
|
((cases[i][0] == cases[i][1] // ligne pleine
|
||
|
&& cases[i][1] == cases[i][2])
|
||
|
|| (cases[0][j] == cases[1][j] // colonne pleine
|
||
|
&& cases[1][j] == cases[2][j])
|
||
|
|| (i == j // première diagonale pleine
|
||
|
&& cases[0][0] == cases[1][1]
|
||
|
&& cases[1][1] == cases[2][2])
|
||
|
|| (i + j == 2 // deuxième diagonale pleine
|
||
|
&& cases[0][2] == cases[1][1]
|
||
|
&& cases[1][1] == cases[2][0]));
|
||
|
}
|
||
|
|
||
|
|
||
|
/////// « Événements » de haut niveau déclenchées par l'utilisateur ////////////
|
||
|
|
||
|
|
||
|
// Remarque : dans cette partie j'ai laissé le paramètre implicite this car
|
||
|
// il me semble qu'il faudrait mettre tout ceci dans une classe spécifique,
|
||
|
// par exemple LogiqueMorpion. Dans ce cas, this serait remplacé par
|
||
|
// getModele() ou getMorpion().
|
||
|
|
||
|
|
||
|
public void quitter() {
|
||
|
}
|
||
|
|
||
|
public void recommencer() {
|
||
|
this.initialiser();
|
||
|
}
|
||
|
|
||
|
public void cocher(int x, int y) throws CaseOccupeeException {
|
||
|
if (!this.estTerminee()) { // La partie est en cours
|
||
|
if (this.estVide(x, y)) {
|
||
|
// Jouer la case
|
||
|
this.jouer(x, y);
|
||
|
|
||
|
// Passer à la suite
|
||
|
if (! this.estTerminee()) {
|
||
|
// Faire jouer l'autre joueur
|
||
|
this.changer();
|
||
|
}
|
||
|
} else {
|
||
|
throw new CaseOccupeeException("Impossible, la case est occupée !");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|