Files

180 lines
6.7 KiB
Java
Raw Permalink Normal View History

2026-03-30 22:33:20 +02:00
import java.io.Serializable;
2026-04-12 16:40:07 +02:00
/**
* Gère la logique principale du Démineur (le plateau de jeu).
* Initialise les cases, place les mines et contient l'algorithme de révélation.
*/
2026-03-30 22:33:20 +02:00
public class Grille implements Serializable {
2026-04-12 16:40:07 +02:00
/** Tableau à deux dimensions contenant toutes les cases du jeu. */
2026-03-30 22:33:20 +02:00
private Case[][] plateau;
2026-04-12 16:40:07 +02:00
/** Nombre total de lignes de la grille. */
2026-03-30 22:33:20 +02:00
private int lignes;
2026-04-12 16:40:07 +02:00
/** Nombre total de colonnes de la grille. */
2026-03-30 22:33:20 +02:00
private int colonnes;
2026-04-12 16:40:07 +02:00
/** Nombre total de mines cachées dans la grille. */
2026-03-30 22:33:20 +02:00
private int mines;
2026-04-12 16:40:07 +02:00
/** Indique si la partie est bloquée (gagnée ou perdue). */
2026-04-07 16:21:33 +02:00
private boolean partieTerminee;
2026-03-30 22:33:20 +02:00
2026-04-12 16:40:07 +02:00
/**
* Constructeur de la grille.
* Crée le plateau, place les mines aléatoirement et calcule les voisins.
* @param nbLignes le nombre de lignes souhaité.
* @param nbColonnes le nombre de colonnes souhaité.
* @param nbMines le nombre de mines à placer.
*/
public Grille(int nbLignes, int nbColonnes, int nbMines) {
this.lignes = nbLignes;
this.colonnes = nbColonnes;
this.mines = nbMines;
2026-04-07 13:54:01 +02:00
this.partieTerminee = false;
2026-03-30 22:33:20 +02:00
this.plateau = new Case[this.lignes][this.colonnes];
2026-04-12 16:40:07 +02:00
for (int ligne = 0; ligne < this.lignes; ligne++) {
for (int colonne = 0; colonne < this.colonnes; colonne++) {
this.plateau[ligne][colonne] = new Case();
2026-03-30 22:33:20 +02:00
}
}
2026-04-03 18:41:45 +02:00
placerMines();
calculerVoisins();
2026-03-30 22:33:20 +02:00
}
2026-04-03 18:41:45 +02:00
2026-04-12 16:40:07 +02:00
/**
* Récupère le nombre de lignes de la grille.
* @return le nombre de lignes.
*/
2026-04-03 18:41:45 +02:00
public int getLignes() { return this.lignes; }
2026-04-12 16:40:07 +02:00
/**
* Récupère le nombre de colonnes de la grille.
* @return le nombre de colonnes.
*/
2026-04-03 18:41:45 +02:00
public int getColonnes() { return this.colonnes; }
2026-04-12 16:40:07 +02:00
/**
* Accède à une case spécifique du plateau.
* @param indexLigne la ligne de la case cible.
* @param indexColonne la colonne de la case cible.
* @return l'objet Case correspondant.
*/
public Case getCase(int indexLigne, int indexColonne) { return this.plateau[indexLigne][indexColonne]; }
/**
* Vérifie si la partie est verrouillée en état de fin.
* @return true si terminée, false si en cours.
*/
2026-04-07 13:54:01 +02:00
public boolean isPartieTerminee() { return this.partieTerminee; }
2026-04-12 16:40:07 +02:00
/**
* Modifie l'état de fin de partie (verrouillage de la grille).
* @param terminee true pour bloquer le jeu, false pour le débloquer.
*/
2026-04-07 13:54:01 +02:00
public void setPartieTerminee(boolean terminee) { this.partieTerminee = terminee; }
2026-04-03 18:41:45 +02:00
2026-04-12 16:40:07 +02:00
/**
* Calcule le nombre de mines restantes à trouver selon les drapeaux posés.
* @return la soustraction des mines totales par le nombre d'étoiles posées.
*/
2026-04-07 16:21:33 +02:00
public int getMinesRestantes() {
int drapeaux = 0;
2026-04-12 16:40:07 +02:00
for (int ligne = 0; ligne < this.lignes; ligne++) {
for (int colonne = 0; colonne < this.colonnes; colonne++) {
if (this.plateau[ligne][colonne].getMarqueur() == Case.MARQUEUR_ETOILE) {
2026-04-07 16:21:33 +02:00
drapeaux++;
}
}
}
return this.mines - drapeaux;
}
2026-04-12 16:40:07 +02:00
/**
* Place aléatoirement le nombre défini de mines sur le plateau vide.
*/
2026-04-03 18:41:45 +02:00
private void placerMines() {
int minesPlacees = 0;
while (minesPlacees < this.mines) {
2026-04-12 16:40:07 +02:00
int ligneAleatoire = (int) (Math.random() * this.lignes);
int colonneAleatoire = (int) (Math.random() * this.colonnes);
if (!this.plateau[ligneAleatoire][colonneAleatoire].isMinee()) {
this.plateau[ligneAleatoire][colonneAleatoire].setMinee(true);
2026-04-03 18:41:45 +02:00
minesPlacees++;
}
}
}
2026-04-12 16:40:07 +02:00
/**
* Parcourt la grille pour calculer le nombre de mines autour de chaque case non-minée.
*/
2026-04-03 18:41:45 +02:00
private void calculerVoisins() {
2026-04-12 16:40:07 +02:00
for (int ligne = 0; ligne < this.lignes; ligne++) {
for (int colonne = 0; colonne < this.colonnes; colonne++) {
if (!this.plateau[ligne][colonne].isMinee()) {
2026-04-03 18:41:45 +02:00
int compteMines = 0;
2026-04-12 16:40:07 +02:00
for (int decalageLigne = -1; decalageLigne <= 1; decalageLigne++) {
for (int decalageColonne = -1; decalageColonne <= 1; decalageColonne++) {
int voisinLigne = ligne + decalageLigne;
int voisinColonne = colonne + decalageColonne;
if (voisinLigne >= 0 && voisinLigne < this.lignes && voisinColonne >= 0 && voisinColonne < this.colonnes) {
if (this.plateau[voisinLigne][voisinColonne].isMinee()) {
2026-04-03 18:41:45 +02:00
compteMines++;
}
}
}
}
2026-04-12 16:40:07 +02:00
this.plateau[ligne][colonne].setNbMinesVoisines(compteMines);
2026-04-03 18:41:45 +02:00
}
}
}
}
2026-04-12 16:40:07 +02:00
/**
* Révèle une case et déclenche une réaction en chaîne récursive si elle vaut 0.
* @param cibleLigne la ligne de la case à révéler.
* @param cibleColonne la colonne de la case à révéler.
* @return true si une mine a explosé, false sinon.
*/
public boolean revelerCase(int cibleLigne, int cibleColonne) {
Case caseCliquee = this.plateau[cibleLigne][cibleColonne];
if (caseCliquee.isRevelee() || caseCliquee.getMarqueur() == Case.MARQUEUR_ETOILE) return false;
2026-04-03 18:41:45 +02:00
caseCliquee.setRevelee(true);
2026-04-07 16:21:33 +02:00
if (caseCliquee.isMinee()) return true;
2026-04-03 18:41:45 +02:00
if (caseCliquee.getNbMinesVoisines() == 0) {
2026-04-12 16:40:07 +02:00
for (int decalageLigne = -1; decalageLigne <= 1; decalageLigne++) {
for (int decalageColonne = -1; decalageColonne <= 1; decalageColonne++) {
int voisinLigne = cibleLigne + decalageLigne;
int voisinColonne = cibleColonne + decalageColonne;
if (voisinLigne >= 0 && voisinLigne < this.lignes && voisinColonne >= 0 && voisinColonne < this.colonnes) {
revelerCase(voisinLigne, voisinColonne);
2026-04-03 18:41:45 +02:00
}
}
}
}
2026-04-07 13:54:01 +02:00
return false;
2026-04-03 18:41:45 +02:00
}
2026-04-07 13:54:01 +02:00
2026-04-12 16:40:07 +02:00
/**
* Vérifie si le joueur a révélé toutes les cases non-minées du plateau.
* @return true si la partie est gagnée, false si elle est toujours en cours.
*/
2026-04-03 18:41:45 +02:00
public boolean estGagnee() {
int casesRevelees = 0;
2026-04-12 16:40:07 +02:00
for (int ligne = 0; ligne < this.lignes; ligne++) {
for (int colonne = 0; colonne < this.colonnes; colonne++) {
if (this.plateau[ligne][colonne].isRevelee()) casesRevelees++;
2026-04-03 18:41:45 +02:00
}
}
2026-04-07 16:21:33 +02:00
return casesRevelees == ((this.lignes * this.colonnes) - this.mines);
2026-04-03 18:41:45 +02:00
}
2026-04-07 13:54:01 +02:00
}