fonctionnalite pour perdre

This commit is contained in:
lecointre
2026-04-07 13:54:01 +02:00
parent dc266ea40f
commit a5d3c87427
2 changed files with 44 additions and 54 deletions
+34
View File
@@ -84,4 +84,38 @@ public class FenetreJeu extends JFrame {
} }
} }
} }
/**
* Affiche la grille de fin de partie en cas de défaite, comme demandé dans le sujet.
* @param lExplose la ligne de la mine qui a fait BOUM
* @param cExplose la colonne de la mine qui a fait BOUM
*/
public void afficherDefaite(int lExplose, int cExplose) {
for (int i = 0; i < grille.getLignes(); i++) {
for (int j = 0; j < grille.getColonnes(); j++) {
Case c = grille.getCase(i, j);
JButton btn = boutons[i][j];
// On désactive le bouton pour empêcher de cliquer dessus
btn.setEnabled(false);
// 1. La case dont la mine a "sauté"
if (i == lExplose && j == cExplose) {
btn.setText("BOUM");
btn.setBackground(Color.RED);
}
// 2. Les cases minées non marquées (les bombes oubliées)
else if (c.isMinee() && c.getMarqueur() != 1) {
btn.setText("M");
btn.setBackground(Color.ORANGE);
}
// 3. Les cases marquées non minées (les fausses pistes)
else if (!c.isMinee() && c.getMarqueur() == 1) {
btn.setText("X"); // Un X pour dire "Erreur"
btn.setBackground(Color.YELLOW);
}
// Si la case ne rentre pas dans ces cas, on la laisse tranquille
}
}
}
} // <--- L'accolade finale est bien ici maintenant ! } // <--- L'accolade finale est bien ici maintenant !
+9 -53
View File
@@ -9,55 +9,42 @@ public class Grille implements Serializable {
private int lignes; private int lignes;
private int colonnes; private int colonnes;
private int mines; private int mines;
private boolean partieTerminee; // <--- LE FAMEUX VERROU !
/**
* Initialise une nouvelle grille et place les mines.
*/
public Grille(int l, int c, int m) { public Grille(int l, int c, int m) {
this.lignes = l; this.lignes = l;
this.colonnes = c; this.colonnes = c;
this.mines = m; this.mines = m;
this.partieTerminee = false;
this.plateau = new Case[this.lignes][this.colonnes]; this.plateau = new Case[this.lignes][this.colonnes];
// 1. Initialisation : on remplit avec des cases vides
for (int i = 0; i < this.lignes; i++) { for (int i = 0; i < this.lignes; i++) {
for (int j = 0; j < this.colonnes; j++) { for (int j = 0; j < this.colonnes; j++) {
this.plateau[i][j] = new Case(); this.plateau[i][j] = new Case();
} }
} }
// 2. On appelle nos nouvelles méthodes
placerMines(); placerMines();
calculerVoisins(); calculerVoisins();
} }
// --- Les Getters --- // --- Les Getters et Setters ---
public int getLignes() { return this.lignes; } public int getLignes() { return this.lignes; }
public int getColonnes() { return this.colonnes; } public int getColonnes() { return this.colonnes; }
public Case getCase(int l, int c) { return this.plateau[l][c]; }
/** // <--- LES DEUX MÉTHODES QUI TE MANQUAIENT ICI --->
* Permet d'accéder à une case spécifique de la grille. public boolean isPartieTerminee() { return this.partieTerminee; }
*/ public void setPartieTerminee(boolean terminee) { this.partieTerminee = terminee; }
public Case getCase(int l, int c) {
return this.plateau[l][c];
}
// --- Les algorithmes du jeu --- // --- Les algorithmes du jeu ---
/**
* Place les mines aléatoirement dans le tableau.
*/
private void placerMines() { private void placerMines() {
Random rand = new Random(); Random rand = new Random();
int minesPlacees = 0; int minesPlacees = 0;
// Tant qu'on n'a pas placé toutes les mines demandées...
while (minesPlacees < this.mines) { while (minesPlacees < this.mines) {
int l = rand.nextInt(this.lignes); int l = rand.nextInt(this.lignes);
int c = rand.nextInt(this.colonnes); int c = rand.nextInt(this.colonnes);
// Si la case n'est pas déjà minée, on y met une mine
if (!this.plateau[l][c].isMinee()) { if (!this.plateau[l][c].isMinee()) {
this.plateau[l][c].setMinee(true); this.plateau[l][c].setMinee(true);
minesPlacees++; minesPlacees++;
@@ -65,25 +52,15 @@ public class Grille implements Serializable {
} }
} }
/**
* Calcule le nombre de mines autour de chaque case.
*/
private void calculerVoisins() { private void calculerVoisins() {
for (int i = 0; i < this.lignes; i++) { for (int i = 0; i < this.lignes; i++) {
for (int j = 0; j < this.colonnes; j++) { for (int j = 0; j < this.colonnes; j++) {
// Si la case elle-même n'est pas une mine
if (!this.plateau[i][j].isMinee()) { if (!this.plateau[i][j].isMinee()) {
int compteMines = 0; int compteMines = 0;
// On parcourt les 8 cases autour (de -1 à +1 en ligne et colonne)
for (int di = -1; di <= 1; di++) { for (int di = -1; di <= 1; di++) {
for (int dj = -1; dj <= 1; dj++) { for (int dj = -1; dj <= 1; dj++) {
int voisinI = i + di; int voisinI = i + di;
int voisinJ = j + dj; int voisinJ = j + dj;
// On vérifie qu'on ne sort pas du tableau !
// (Pour éviter l'ArrayIndexOutOfBoundsException vu dans ton cours)
if (voisinI >= 0 && voisinI < this.lignes && voisinJ >= 0 && voisinJ < this.colonnes) { if (voisinI >= 0 && voisinI < this.lignes && voisinJ >= 0 && voisinJ < this.colonnes) {
if (this.plateau[voisinI][voisinJ].isMinee()) { if (this.plateau[voisinI][voisinJ].isMinee()) {
compteMines++; compteMines++;
@@ -91,60 +68,41 @@ public class Grille implements Serializable {
} }
} }
} }
// On enregistre le chiffre dans la case
this.plateau[i][j].setNbMinesVoisines(compteMines); this.plateau[i][j].setNbMinesVoisines(compteMines);
} }
} }
} }
} }
/**
* Révèle une case et déclenche une réaction en chaîne si elle vaut 0.
* C'est l'algorithme récursif principal du jeu !
* @return true si on a cliqué sur une mine (défaite), false sinon.
*/
public boolean revelerCase(int l, int c) { public boolean revelerCase(int l, int c) {
Case caseCliquee = this.plateau[l][c]; Case caseCliquee = this.plateau[l][c];
// Conditions d'arrêt : on s'arrête si la case est déjà révélée ou a une étoile
if (caseCliquee.isRevelee() || caseCliquee.getMarqueur() == 1) { if (caseCliquee.isRevelee() || caseCliquee.getMarqueur() == 1) {
return false; return false;
} }
// On révèle la case
caseCliquee.setRevelee(true); caseCliquee.setRevelee(true);
// Si c'est une mine, c'est perdu !
if (caseCliquee.isMinee()) { if (caseCliquee.isMinee()) {
return true; return true;
} }
// RÉACTION EN CHAÎNE : Si c'est un 0, on révèle les voisins
if (caseCliquee.getNbMinesVoisines() == 0) { if (caseCliquee.getNbMinesVoisines() == 0) {
for (int di = -1; di <= 1; di++) { for (int di = -1; di <= 1; di++) {
for (int dj = -1; dj <= 1; dj++) { for (int dj = -1; dj <= 1; dj++) {
int voisinL = l + di; int voisinL = l + di;
int voisinC = c + dj; int voisinC = c + dj;
// On vérifie qu'on ne sort pas des bords du tableau
if (voisinL >= 0 && voisinL < this.lignes && voisinC >= 0 && voisinC < this.colonnes) { if (voisinL >= 0 && voisinL < this.lignes && voisinC >= 0 && voisinC < this.colonnes) {
// LA RÉCURSIVITÉ EST ICI : la fonction s'appelle elle-même
revelerCase(voisinL, voisinC); revelerCase(voisinL, voisinC);
} }
} }
} }
} }
return false;
return false; // Pas de mine explosée
} }
/**
* Vérifie si le joueur a gagné la partie.
* @return true si toutes les cases sans mine sont révélées, false sinon.
*/
public boolean estGagnee() { public boolean estGagnee() {
int casesRevelees = 0; int casesRevelees = 0;
// On compte combien de cases le joueur a réussi à révéler
for (int i = 0; i < this.lignes; i++) { for (int i = 0; i < this.lignes; i++) {
for (int j = 0; j < this.colonnes; j++) { for (int j = 0; j < this.colonnes; j++) {
if (this.plateau[i][j].isRevelee()) { if (this.plateau[i][j].isRevelee()) {
@@ -152,8 +110,6 @@ public class Grille implements Serializable {
} }
} }
} }
// C'est gagné si le nombre de cases révélées correspond au total des cases vides
int casesVidesTotales = (this.lignes * this.colonnes) - this.mines; int casesVidesTotales = (this.lignes * this.colonnes) - this.mines;
return casesRevelees == casesVidesTotales; return casesRevelees == casesVidesTotales;
} }