import javax.swing.*; import java.awt.*; /** * Fenêtre principale du jeu. * Gère l'interface de la partie en cours, la grille de boutons, les clics et les conditions de fin de partie. */ public class FenetreJeu { private JFrame fenetre; private JPanel panneauGrille; private JButton[][] boutons; private Grille grille; private boolean partieTerminee = false; private JLabel labelStatut; private JButton boutonSauver; /** * Constructeur de la fenêtre de jeu. * @param g La grille contenant les données des cases et des mines. */ public FenetreJeu(Grille g) { this.grille = g; int l = grille.getLigne(); int c = grille.getColonne(); fenetre = new JFrame("Demineur"); fenetre.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); fenetre.addWindowListener(new ActionFermerFenetre(this)); panneauGrille = new JPanel(); panneauGrille.setLayout(new GridLayout(l, c)); boutons = new JButton [l][c]; // Création de tous les boutons de la grille for (int i = 0; i < l; i++) { for (int j = 0; j < c; j++) { boutons[i][j] = new JButton(); boutons[i][j].setPreferredSize(new Dimension(45, 45)); boutons[i][j].setFont(new Font("Arial", Font.BOLD, 16)); boutons[i][j].addMouseListener(new ActionCase(this, i, j)); panneauGrille.add(boutons[i][j]); } } fenetre.setLayout(new BorderLayout()); fenetre.add(panneauGrille, BorderLayout.CENTER); // Panneau de contrôle en bas JPanel panneauBas = new JPanel(); panneauBas.setLayout(new BorderLayout()); labelStatut = new JLabel("Partie en cours...", SwingConstants.CENTER); labelStatut.setFont(new Font("Arial", Font.BOLD, 14)); JPanel conteneurBoutons = new JPanel(); JButton boutonMenu = new JButton("Menu Principal"); boutonMenu.addActionListener(new ActionRetourMenu(fenetre)); boutonSauver = new JButton("Sauver et Quitter"); boutonSauver.addActionListener(new ActionSauverQuitter(this)); conteneurBoutons.add(boutonMenu); conteneurBoutons.add(boutonSauver); panneauBas.add(labelStatut, BorderLayout.NORTH); panneauBas.add(conteneurBoutons, BorderLayout.SOUTH); fenetre.add(panneauBas, BorderLayout.SOUTH); fenetre.pack(); fenetre.setLocationRelativeTo(null); fenetre.setVisible(true); actualiserAffichage(); } /** * Vérifie si toutes les cases sans mine ont été révélées. * Si c'est le cas, déclenche l'état de victoire. */ public void verifierVictoire() { int casesAReveler = (grille.getLigne() * grille.getColonne()); int nbMines = 0; int nbRevelees = 0; for (int i = 0; i < grille.getLigne(); i++) { for (int j = 0; j < grille.getColonne(); j++) { if (grille.getCase(i, j).getEstMinee()) nbMines++; if (grille.getCase(i, j).getEstRevelee()) nbRevelees++; } } if (nbRevelees == (casesAReveler - nbMines)) { partieTerminee = true; bloquerSauvegarde(); System.out.println("Vous avez gagné !"); labelStatut.setFont(new Font("Arial", Font.BOLD, 24)); labelStatut.setForeground(new Color(0, 150, 0)); labelStatut.setText(" VICTOIRE ! Bien joué !"); } } /** * Révèle les cases adjacentes en cascade si la case actuelle n'a aucune mine autour. * Cette méthode est récursive. * @param l L'index de la ligne de la case actuelle. * @param c L'index de la colonne de la case actuelle. */ public void revelerCaseProche(int l, int c){ if (l < 0 || l >= grille.getLigne() || c < 0 || c >= grille.getColonne() ) return; Case caseActuelle = grille.getCase(l, c); if (caseActuelle.getMarqueur() != 0 || caseActuelle.getEstRevelee() == true ) return; caseActuelle.setEstRevelee(true); if(caseActuelle.getNbMinesautour() == 0){ for(int i = -1; i <= 1; i++){ for(int j = -1; j <= 1; j++){ int vL = l + i; int vC = c + j; revelerCaseProche(vL,vC); } } } } /** * Désactive le bouton de sauvegarde et supprime le fichier de sauvegarde existant. * Appelée lorsque la partie est terminée (victoire ou défaite). */ public void bloquerSauvegarde() { boutonSauver.setEnabled(false); java.io.File fichier = new java.io.File("sauvegarde.ser"); if (fichier.exists()) { fichier.delete(); } } /** @return true si la partie est terminée, false sinon. */ public boolean isPartieTerminee() { return partieTerminee; } /** @return La grille logique manipulée par cette fenêtre. */ public Grille getGrille() { return grille; } /** * Gère les événements de défaite. * Affiche le message de défaite et révèle toutes les mines et erreurs de la grille. */ public void partiePerdu(){ bloquerSauvegarde(); labelStatut.setFont(new Font("Arial", Font.BOLD, 24)); labelStatut.setForeground(Color.RED); labelStatut.setText(" DÉFAITE !"); for(int i =0; i 0) { btn.setText(String.valueOf(nb)); } else { btn.setText(""); } } } } else { btn.setEnabled(true); int mq = currentCase.getMarqueur(); if (mq == 1) btn.setText("★"); else if (mq == 2) btn.setText("?"); else btn.setText(""); } } } if (!partieTerminee) { int nbEtoiles = 0; for (int i = 0; i < l; i++) { for (int j = 0; j < c; j++) { if (grille.getCase(i, j).getMarqueur() == 1) { nbEtoiles++; } } } int progression = grille.getNbMinesTotales() - nbEtoiles; labelStatut.setText("Progression : " + progression + " mine(s) restante(s)"); } } }