Files
SAE21_2025/FenetreJeu.java
2026-04-12 16:40:07 +02:00

223 lines
8.5 KiB
Java

import javax.swing.*;
import java.awt.*;
/**
* Fenêtre affichant la partie en cours.
* Gère l'affichage de la grille, du compteur de mines et du bouton de sauvegarde.
*/
public class FenetreJeu extends JFrame {
/** Position X initiale de la fenêtre de jeu sur l'écran. */
private static final int POSITION_X = 100;
/** Position Y initiale de la fenêtre de jeu sur l'écran. */
private static final int POSITION_Y = 100;
/** Estimation de la taille en pixels d'une case pour la largeur de la fenêtre. */
private static final int LARGEUR_CASE_PIXELS = 50;
/** Estimation de la taille en pixels d'une case pour la hauteur de la fenêtre. */
private static final int HAUTEUR_CASE_PIXELS = 50;
/** Espace supplémentaire en hauteur pour afficher l'en-tête et le pied de page. */
private static final int MARGE_HAUTEUR_PIXELS = 100;
/** Référence vers le modèle logique du jeu. */
private Grille grille;
/** Tableau à deux dimensions stockant les composants graphiques des cases. */
private JButton[][] boutons;
/** Étiquette textuelle affichant le nombre de mines restantes à trouver. */
private JLabel labelCompteur;
/** Bouton dynamique en bas de la fenêtre (Sauvegarder ou Retour Menu). */
private JButton boutonActionBas;
/**
* Constructeur de la fenêtre de jeu.
* @param grilleJeu la grille logique initialisée à afficher.
*/
public FenetreJeu(Grille grilleJeu) {
super("Démineur - Partie en cours");
this.grille = grilleJeu;
this.boutons = new JButton[grilleJeu.getLignes()][grilleJeu.getColonnes()];
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
int largeurFenetre = grilleJeu.getColonnes() * LARGEUR_CASE_PIXELS;
int hauteurFenetre = (grilleJeu.getLignes() * HAUTEUR_CASE_PIXELS) + MARGE_HAUTEUR_PIXELS;
this.setSize(largeurFenetre, hauteurFenetre);
this.setLocation(POSITION_X, POSITION_Y);
initialiserEntete();
initialiserPanneauGrille();
initialiserBoutonBas();
}
/**
* Prépare et ajoute le compteur de mines en haut de la fenêtre.
*/
private void initialiserEntete() {
this.labelCompteur = new JLabel("Mines restantes : " + this.grille.getMinesRestantes());
this.labelCompteur.setHorizontalAlignment(JLabel.CENTER);
this.add(this.labelCompteur, BorderLayout.NORTH);
}
/**
* Prépare et ajoute la zone centrale contenant tous les boutons cliquables.
*/
private void initialiserPanneauGrille() {
JPanel panneauGrille = new JPanel();
panneauGrille.setLayout(new GridLayout(this.grille.getLignes(), this.grille.getColonnes()));
ControleurGrille controleurSouris = new ControleurGrille(this, this.grille);
for (int ligne = 0; ligne < this.grille.getLignes(); ligne++) {
for (int colonne = 0; colonne < this.grille.getColonnes(); colonne++) {
JButton boutonCase = new JButton("");
this.boutons[ligne][colonne] = boutonCase;
panneauGrille.add(boutonCase);
boutonCase.addMouseListener(controleurSouris);
}
}
this.add(panneauGrille, BorderLayout.CENTER);
}
/**
* Prépare et ajoute le bouton de contrôle général en bas de la fenêtre.
*/
private void initialiserBoutonBas() {
this.boutonActionBas = new JButton("Sauver et Quitter");
this.add(this.boutonActionBas, BorderLayout.SOUTH);
ControleurJeu controleurQuitter = new ControleurJeu(this);
this.boutonActionBas.addActionListener(controleurQuitter);
}
/**
* Récupère un bouton graphique spécifique de la grille.
* @param indexLigne la ligne du bouton.
* @param indexColonne la colonne du bouton.
* @return le bouton correspondant.
*/
public JButton getBouton(int indexLigne, int indexColonne) { return this.boutons[indexLigne][indexColonne]; }
/**
* Accède à l'instance de la grille logique.
* @return la grille du jeu.
*/
public Grille getGrille() { return this.grille; }
/**
* Transforme le bouton de sauvegarde en bouton de retour au menu.
*/
public void changerBoutonEnRetourMenu() {
this.boutonActionBas.setText("Retour au Menu");
}
/**
* Interroge la grille et rafraîchit le texte du compteur de mines.
*/
public void mettreAJourCompteur() {
this.labelCompteur.setText("Mines restantes : " + this.grille.getMinesRestantes());
}
/**
* Met à jour l'apparence visuelle d'un bouton selon son état logique.
* @param ligne la ligne du bouton à rafraîchir.
* @param colonne la colonne du bouton à rafraîchir.
*/
public void rafraichirCase(int ligne, int colonne) {
Case caseLogique = this.grille.getCase(ligne, colonne);
JButton bouton = this.boutons[ligne][colonne];
if (caseLogique.isRevelee()) {
appliquerStyleCaseRevelee(caseLogique, bouton);
} else {
appliquerStyleCaseCachee(caseLogique, bouton);
}
}
/**
* Applique les couleurs et le texte d'une case qui vient d'être révélée.
* @param caseLogique la donnée de la case.
* @param bouton le composant graphique associé.
*/
private void appliquerStyleCaseRevelee(Case caseLogique, JButton bouton) {
if (caseLogique.isMinee()) {
bouton.setText("M");
bouton.setBackground(Color.RED);
} else if (caseLogique.getNbMinesVoisines() > 0) {
bouton.setText("" + caseLogique.getNbMinesVoisines());
bouton.setBackground(Color.WHITE);
} else {
bouton.setText("");
bouton.setBackground(Color.LIGHT_GRAY);
}
}
/**
* Applique les symboles d'une case qui est encore masquée (marqueurs).
* @param caseLogique la donnée de la case.
* @param bouton le composant graphique associé.
*/
private void appliquerStyleCaseCachee(Case caseLogique, JButton bouton) {
if (caseLogique.getMarqueur() == Case.MARQUEUR_ETOILE) {
bouton.setText("*");
} else if (caseLogique.getMarqueur() == Case.MARQUEUR_INTERROGATION) {
bouton.setText("?");
} else {
bouton.setText("");
}
}
/**
* Force la mise à jour visuelle de toutes les cases de la grille.
*/
public void rafraichirTouteLaGrille() {
for (int ligne = 0; ligne < grille.getLignes(); ligne++) {
for (int colonne = 0; colonne < grille.getColonnes(); colonne++) {
rafraichirCase(ligne, colonne);
}
}
}
/**
* Affiche l'état de défaite en révélant les erreurs et les mines manquantes.
* @param ligneExplosion la ligne de la mine déclenchée.
* @param colonneExplosion la colonne de la mine déclenchée.
*/
public void afficherDefaite(int ligneExplosion, int colonneExplosion) {
for (int ligne = 0; ligne < grille.getLignes(); ligne++) {
for (int colonne = 0; colonne < grille.getColonnes(); colonne++) {
Case caseActuelle = grille.getCase(ligne, colonne);
JButton bouton = boutons[ligne][colonne];
appliquerStyleDefaite(caseActuelle, bouton, ligne, colonne, ligneExplosion, colonneExplosion);
}
}
}
/**
* Détermine la couleur spécifique d'une case en fin de partie (erreur, oubli, ou explosion).
* @param caseActuelle la donnée de la case.
* @param bouton le composant graphique.
* @param ligne la ligne en cours de parcours.
* @param colonne la colonne en cours de parcours.
* @param ligneExplosion la ligne de la mine fatale.
* @param colonneExplosion la colonne de la mine fatale.
*/
private void appliquerStyleDefaite(Case caseActuelle, JButton bouton, int ligne, int colonne, int ligneExplosion, int colonneExplosion) {
if (ligne == ligneExplosion && colonne == colonneExplosion) {
bouton.setText("BOUM");
bouton.setBackground(Color.RED);
} else if (caseActuelle.isMinee() && caseActuelle.getMarqueur() != Case.MARQUEUR_ETOILE) {
bouton.setText("M");
bouton.setBackground(Color.ORANGE);
} else if (!caseActuelle.isMinee() && caseActuelle.getMarqueur() == Case.MARQUEUR_ETOILE) {
bouton.setText("X");
bouton.setBackground(Color.YELLOW);
}
}
}