fin mode de jeu a peu pres
This commit is contained in:
+57
-5
@@ -1,15 +1,18 @@
|
|||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fenêtre principale pendant une partie de Démineur.
|
||||||
|
*/
|
||||||
public class FenetreJeu extends JFrame {
|
public class FenetreJeu extends JFrame {
|
||||||
|
|
||||||
private Grille grille;
|
private Grille grille;
|
||||||
|
private JButton[][] boutons;
|
||||||
|
|
||||||
public FenetreJeu(Grille g) {
|
public FenetreJeu(Grille g) {
|
||||||
super("Démineur - Partie en cours");
|
super("Démineur - Partie en cours");
|
||||||
this.grille = g;
|
this.grille = g;
|
||||||
|
this.boutons = new JButton[g.getLignes()][g.getColonnes()];
|
||||||
|
|
||||||
this.setSize(600, 600);
|
this.setSize(600, 600);
|
||||||
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
@@ -18,18 +21,67 @@ public class FenetreJeu extends JFrame {
|
|||||||
JPanel panneauGrille = new JPanel();
|
JPanel panneauGrille = new JPanel();
|
||||||
panneauGrille.setLayout(new GridLayout(g.getLignes(), g.getColonnes()));
|
panneauGrille.setLayout(new GridLayout(g.getLignes(), g.getColonnes()));
|
||||||
|
|
||||||
|
ControleurGrille controleurSouris = new ControleurGrille(this, this.grille);
|
||||||
|
|
||||||
for (int i = 0; i < g.getLignes(); i++) {
|
for (int i = 0; i < g.getLignes(); i++) {
|
||||||
for (int j = 0; j < g.getColonnes(); j++) {
|
for (int j = 0; j < g.getColonnes(); j++) {
|
||||||
JButton boutonCase = new JButton("?");
|
JButton boutonCase = new JButton("");
|
||||||
|
this.boutons[i][j] = boutonCase;
|
||||||
panneauGrille.add(boutonCase);
|
panneauGrille.add(boutonCase);
|
||||||
|
|
||||||
|
boutonCase.addMouseListener(controleurSouris);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.add(panneauGrille, BorderLayout.CENTER);
|
this.add(panneauGrille, BorderLayout.CENTER);
|
||||||
|
|
||||||
JButton btnSauverQuitter = new JButton("Sauver et Quitter");
|
JButton btnSauverQuitter = new JButton("Sauver et Quitter");
|
||||||
this.add(btnSauverQuitter, BorderLayout.SOUTH);
|
this.add(btnSauverQuitter, BorderLayout.SOUTH);
|
||||||
|
ControleurJeu controleurQuitter = new ControleurJeu(this);
|
||||||
|
btnSauverQuitter.addActionListener(controleurQuitter);
|
||||||
|
}
|
||||||
|
|
||||||
ControleurJeu controleur = new ControleurJeu(this);
|
public JButton getBouton(int l, int c) {
|
||||||
btnSauverQuitter.addActionListener(controleur);
|
return this.boutons[l][c];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Met à jour le visuel d'un bouton en fonction de l'état de sa Case logique.
|
||||||
|
*/
|
||||||
|
public void rafraichirCase(int l, int c) {
|
||||||
|
Case caseLogique = this.grille.getCase(l, c);
|
||||||
|
JButton btn = this.boutons[l][c];
|
||||||
|
|
||||||
|
if (caseLogique.isRevelee()) {
|
||||||
|
btn.setEnabled(false);
|
||||||
|
|
||||||
|
if (caseLogique.isMinee()) {
|
||||||
|
btn.setText("M");
|
||||||
|
btn.setBackground(Color.RED);
|
||||||
|
} else if (caseLogique.getNbMinesVoisines() > 0) {
|
||||||
|
btn.setText("" + caseLogique.getNbMinesVoisines());
|
||||||
|
} else {
|
||||||
|
btn.setText("");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (caseLogique.getMarqueur() == 1) {
|
||||||
|
btn.setText("★");
|
||||||
|
} else if (caseLogique.getMarqueur() == 2) {
|
||||||
|
btn.setText("?");
|
||||||
|
} else {
|
||||||
|
btn.setText("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rafraîchit l'affichage de tous les boutons de la grille d'un seul coup.
|
||||||
|
* Indispensable après une réaction en chaîne.
|
||||||
|
*/
|
||||||
|
public void rafraichirTouteLaGrille() {
|
||||||
|
for (int i = 0; i < grille.getLignes(); i++) {
|
||||||
|
for (int j = 0; j < grille.getColonnes(); j++) {
|
||||||
|
rafraichirCase(i, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // <--- L'accolade finale est bien ici maintenant !
|
||||||
|
|||||||
+136
-4
@@ -1,16 +1,18 @@
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Représente le plateau de jeu contenant les cases.
|
||||||
|
*/
|
||||||
public class Grille implements Serializable {
|
public class Grille implements Serializable {
|
||||||
private Case[][] plateau;
|
private Case[][] plateau;
|
||||||
private int lignes;
|
private int lignes;
|
||||||
private int colonnes;
|
private int colonnes;
|
||||||
private int mines;
|
private int mines;
|
||||||
|
|
||||||
public int getLignes() { return this.lignes; }
|
/**
|
||||||
public int getColonnes() { return this.colonnes; }
|
* 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;
|
||||||
@@ -18,11 +20,141 @@ public class Grille implements Serializable {
|
|||||||
|
|
||||||
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();
|
||||||
|
calculerVoisins();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Les Getters ---
|
||||||
|
public int getLignes() { return this.lignes; }
|
||||||
|
public int getColonnes() { return this.colonnes; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet d'accéder à une case spécifique de la grille.
|
||||||
|
*/
|
||||||
|
public Case getCase(int l, int c) {
|
||||||
|
return this.plateau[l][c];
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Les algorithmes du jeu ---
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Place les mines aléatoirement dans le tableau.
|
||||||
|
*/
|
||||||
|
private void placerMines() {
|
||||||
|
Random rand = new Random();
|
||||||
|
int minesPlacees = 0;
|
||||||
|
|
||||||
|
// Tant qu'on n'a pas placé toutes les mines demandées...
|
||||||
|
while (minesPlacees < this.mines) {
|
||||||
|
int l = rand.nextInt(this.lignes);
|
||||||
|
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()) {
|
||||||
|
this.plateau[l][c].setMinee(true);
|
||||||
|
minesPlacees++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calcule le nombre de mines autour de chaque case.
|
||||||
|
*/
|
||||||
|
private void calculerVoisins() {
|
||||||
|
for (int i = 0; i < this.lignes; i++) {
|
||||||
|
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()) {
|
||||||
|
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 dj = -1; dj <= 1; dj++) {
|
||||||
|
int voisinI = i + di;
|
||||||
|
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 (this.plateau[voisinI][voisinJ].isMinee()) {
|
||||||
|
compteMines++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// On enregistre le chiffre dans la case
|
||||||
|
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) {
|
||||||
|
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) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// On révèle la case
|
||||||
|
caseCliquee.setRevelee(true);
|
||||||
|
|
||||||
|
// Si c'est une mine, c'est perdu !
|
||||||
|
if (caseCliquee.isMinee()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RÉACTION EN CHAÎNE : Si c'est un 0, on révèle les voisins
|
||||||
|
if (caseCliquee.getNbMinesVoisines() == 0) {
|
||||||
|
for (int di = -1; di <= 1; di++) {
|
||||||
|
for (int dj = -1; dj <= 1; dj++) {
|
||||||
|
int voisinL = l + di;
|
||||||
|
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) {
|
||||||
|
// LA RÉCURSIVITÉ EST ICI : la fonction s'appelle elle-même
|
||||||
|
revelerCase(voisinL, voisinC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
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 j = 0; j < this.colonnes; j++) {
|
||||||
|
if (this.plateau[i][j].isRevelee()) {
|
||||||
|
casesRevelees++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
return casesRevelees == casesVidesTotales;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
JC = javac
|
JC = javac
|
||||||
JFLAGS = -implicit:none
|
JFLAGS = -implicit:none
|
||||||
|
|
||||||
all: MenuPrincipal.class Grille.class
|
all: MenuPrincipal.class
|
||||||
|
|
||||||
Case.class: Case.java
|
Case.class: Case.java
|
||||||
$(JC) $(JFLAGS) Case.java
|
$(JC) $(JFLAGS) Case.java
|
||||||
@@ -9,8 +9,9 @@ Case.class: Case.java
|
|||||||
Grille.class: Grille.java Case.class
|
Grille.class: Grille.java Case.class
|
||||||
$(JC) $(JFLAGS) Grille.java
|
$(JC) $(JFLAGS) Grille.java
|
||||||
|
|
||||||
FenetreJeu.class: FenetreJeu.java Grille.class ControleurJeu.java
|
|
||||||
$(JC) $(JFLAGS) FenetreJeu.java ControleurJeu.java
|
FenetreJeu.class: FenetreJeu.java ControleurJeu.java ControleurGrille.java Grille.class
|
||||||
|
$(JC) $(JFLAGS) FenetreJeu.java ControleurJeu.java ControleurGrille.java
|
||||||
|
|
||||||
MenuPrincipal.class: MenuPrincipal.java ControleurMenu.java FenetreJeu.class
|
MenuPrincipal.class: MenuPrincipal.java ControleurMenu.java FenetreJeu.class
|
||||||
$(JC) $(JFLAGS) MenuPrincipal.java ControleurMenu.java
|
$(JC) $(JFLAGS) MenuPrincipal.java ControleurMenu.java
|
||||||
|
|||||||
Reference in New Issue
Block a user