3 Commits

Author SHA1 Message Date
felix-vi
b52badad31 mise à jour de la javadoc 2026-02-05 16:24:56 +01:00
felix-vi
88c65bc194 ajout d'un menu de fin et de pouvoir quitter 2026-02-05 16:21:09 +01:00
felix-vi
6226f4254a mise en place du bot divin dans l'arène et modification de la javadoc 2026-02-04 13:22:17 +01:00
4 changed files with 238 additions and 71 deletions

View File

@@ -1,6 +1,7 @@
package fr.iut_fbleau.Avalam; package fr.iut_fbleau.Avalam;
import fr.iut_fbleau.Bot.AlphaBetaBot; import fr.iut_fbleau.Bot.AlphaBetaBot;
import fr.iut_fbleau.Bot.DivineBot;
import fr.iut_fbleau.Bot.IdiotBot; import fr.iut_fbleau.Bot.IdiotBot;
import fr.iut_fbleau.GameAPI.AbstractGamePlayer; import fr.iut_fbleau.GameAPI.AbstractGamePlayer;
import fr.iut_fbleau.GameAPI.Player; import fr.iut_fbleau.GameAPI.Player;
@@ -13,10 +14,14 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* Fenêtre pour le mode Arène. * Fenêtre pour le mode Arène (bots vs bots).
* Permet de sélectionner deux bots, le nombre de parties, et affiche les résultats. *
* * Elle permet :
* @version 1.0 * - de sélectionner deux bots parmi Idiot, Alpha-Beta et Divin ;
* - de configurer la profondeur de recherche pour les bots intelligents ;
* - de choisir le nombre de parties à jouer ;
* - dafficher, dans un tableau, le résultat de chaque partie (gagnant ou erreur) ;
* - de revenir au menu principal ou de quitter entièrement le jeu.
*/ */
public class ArenaWindow extends JFrame { public class ArenaWindow extends JFrame {
@@ -53,14 +58,19 @@ public class ArenaWindow extends JFrame {
JButton startButton = new JButton("Lancer les parties"); JButton startButton = new JButton("Lancer les parties");
startButton.addActionListener(e -> showConfigDialog()); startButton.addActionListener(e -> showConfigDialog());
buttonPanel.add(startButton); buttonPanel.add(startButton);
JButton backButton = new JButton("Retour au menu"); JButton backButton = new JButton("Retour au menu");
backButton.addActionListener(e -> { backButton.addActionListener(e -> {
dispose(); // Ferme la fenêtre Arène dispose(); // Ferme la fenêtre Arène
Main.showModeSelection(); // Affiche le menu principal Main.showModeSelection(); // Affiche le menu principal
}); });
buttonPanel.add(backButton); buttonPanel.add(backButton);
// Nouveau bouton pour quitter entièrement le jeu
JButton quitButton = new JButton("Quitter");
quitButton.addActionListener(e -> System.exit(0));
buttonPanel.add(quitButton);
add(buttonPanel, BorderLayout.SOUTH); add(buttonPanel, BorderLayout.SOUTH);
pack(); pack();
@@ -224,13 +234,22 @@ public class ArenaWindow extends JFrame {
} }
} }
// Afficher un message de fin // Afficher un message de fin avec possibilité de quitter directement
JOptionPane.showMessageDialog( Object[] options = {"OK", "Quitter le jeu"};
int choice = JOptionPane.showOptionDialog(
this, this,
"Toutes les parties sont terminées !", "Toutes les parties sont terminées !",
"Arène terminée", "Arène terminée",
JOptionPane.INFORMATION_MESSAGE JOptionPane.DEFAULT_OPTION,
JOptionPane.INFORMATION_MESSAGE,
null,
options,
options[0]
); );
if (choice == 1) {
System.exit(0);
}
} }
/** /**
@@ -247,14 +266,7 @@ public class ArenaWindow extends JFrame {
} else if (botType.equals("Bot Alpha-Beta")) { } else if (botType.equals("Bot Alpha-Beta")) {
return new AlphaBetaBot(player, depth); return new AlphaBetaBot(player, depth);
} else if (botType.equals("Bot Divin")) { } else if (botType.equals("Bot Divin")) {
// Pour l'instant, le Bot Divin n'est pas implémenté, on utilise IdiotBot return new DivineBot(player, depth);
JOptionPane.showMessageDialog(
this,
"Le Bot Divin n'est pas encore implémenté. Utilisation du Bot Idiot à la place.",
"Avertissement",
JOptionPane.WARNING_MESSAGE
);
return new IdiotBot(player);
} }
return null; return null;
} }

View File

@@ -1,7 +1,6 @@
package fr.iut_fbleau.Avalam; package fr.iut_fbleau.Avalam;
import fr.iut_fbleau.Bot.AlphaBetaBot; import fr.iut_fbleau.Bot.AlphaBetaBot;
// A FAIRE PLUS TARD (PVGOD)
import fr.iut_fbleau.Bot.DivineBot; import fr.iut_fbleau.Bot.DivineBot;
import fr.iut_fbleau.Bot.IdiotBot; import fr.iut_fbleau.Bot.IdiotBot;
import fr.iut_fbleau.GameAPI.AbstractPly; import fr.iut_fbleau.GameAPI.AbstractPly;
@@ -14,22 +13,25 @@ import java.awt.*;
/** /**
* La classe <code>AvalamWindow</code> * La classe <code>AvalamWindow</code>
* *
* Fenêtre principale (interface graphique) du jeu Avalam. * Fenêtre principale (interface graphique) du jeu Avalam pour tous les modes
* Elle contient : * hors Arène :
* - le plateau (BoardView) * - joueur vs joueur (PVP)
* - laffichage du score (ScoreView) * - joueur vs bot idiot (PVBOT)
* - laffichage du joueur courant (TurnView) * - joueur vs bot alpha (PVALPHA)
*
* Elle pilote un objet <code>AvalamBoard</code> (moteur du jeu).
* Elle peut fonctionner en mode :
* - joueur vs joueur
* - joueur vs bot idiot (aléatoire)
* - joueur vs bot alpha (cut-off)
* - joueur vs bot divin (PVGOD) * - joueur vs bot divin (PVGOD)
* *
* @version 1.0 * Elle contient :
* Date : * - le plateau (<code>BoardView</code>)
* Licence : * - laffichage du score (<code>ScoreView</code>)
* - laffichage du joueur courant (<code>TurnView</code>)
*
* Elle pilote un objet <code>AvalamBoard</code> (moteur du jeu) et,
* en fonction du {@link GameMode}, instancie le bot approprié
* (idiot, alpha-bêta ou divin).
*
* En fin de partie, elle ouvre une fenêtre de fin (<code>EndGameDialog</code>)
* affichant le gagnant, les scores et proposant les actions :
* « Rejouer », « Menu principal » ou « Quitter le jeu ».
*/ */
public class AvalamWindow extends JFrame { public class AvalamWindow extends JFrame {
@@ -50,6 +52,9 @@ public class AvalamWindow extends JFrame {
/** Mode de jeu sélectionné. */ /** Mode de jeu sélectionné. */
private final GameMode mode; private final GameMode mode;
/** Profondeur de recherche utilisée (utile pour les modes avec bot intelligent et pour rejouer). */
private final int searchDepth;
/** Joueur contrôlé par le bot (si actif). */ /** Joueur contrôlé par le bot (si actif). */
private final Player botPlayer = Player.PLAYER2; private final Player botPlayer = Player.PLAYER2;
@@ -59,18 +64,9 @@ public class AvalamWindow extends JFrame {
/** Bot Alpha-Beta (utilisé si mode PVALPHA). */ /** Bot Alpha-Beta (utilisé si mode PVALPHA). */
private final AlphaBetaBot alphaBot; private final AlphaBetaBot alphaBot;
/** Bot Divin (utilisé si mode PVGOD). */
private final DivineBot divineBot; private final DivineBot divineBot;
// A FAIRE PLUS TARD (PVGOD)
// /** Bot Divin (utilisé si mode PVGOD). */
// private final DivineBot divineBot;
/**
* A FAIRE PLUS TARD (PVGOD)
* On garde l'attribut à null pour ne pas casser la compilation,
* mais toute la logique PVGOD est désactivée/commentée.
*/
/** Indique si une animation de tour de bot est en cours. */ /** Indique si une animation de tour de bot est en cours. */
private boolean botAnimating = false; private boolean botAnimating = false;
@@ -87,7 +83,7 @@ public class AvalamWindow extends JFrame {
* Construit la fenêtre en fonction du mode choisi. * Construit la fenêtre en fonction du mode choisi.
* Pour PVALPHA/PVGOD, la profondeur par défaut est 4. * Pour PVALPHA/PVGOD, la profondeur par défaut est 4.
* *
* @param mode mode de jeu * @param mode mode de jeu (PVP, PVBOT, PVALPHA ou PVGOD)
*/ */
public AvalamWindow(GameMode mode) { public AvalamWindow(GameMode mode) {
this(mode, 4); this(mode, 4);
@@ -95,22 +91,23 @@ public class AvalamWindow extends JFrame {
/** /**
* Construit la fenêtre en fonction du mode choisi. * Construit la fenêtre en fonction du mode choisi.
* Si le mode est PVALPHA ou PVGOD, la profondeur est utilisée comme cut-off. * Si le mode est PVALPHA ou PVGOD, la profondeur est utilisée comme cut-off
* pour les bots Alpha-Beta et Divin.
* *
* @param mode mode de jeu * @param mode mode de jeu
* @param alphaDepth profondeur de recherche pour Alpha-Beta / Bot Divin * @param alphaDepth profondeur de recherche pour Alpha-Beta / Bot Divin
*/ */
public AvalamWindow(GameMode mode, int alphaDepth) { public AvalamWindow(GameMode mode, int alphaDepth) {
super("Avalam"); super("Avalam");
this.mode = mode; this.mode = mode;
this.searchDepth = Math.max(1, alphaDepth);
this.idiotBot = (mode == GameMode.PVBOT) ? new IdiotBot(botPlayer) : null; this.idiotBot = (mode == GameMode.PVBOT) ? new IdiotBot(botPlayer) : null;
int depth = Math.max(1, alphaDepth); int depth = this.searchDepth;
this.alphaBot = (mode == GameMode.PVALPHA) ? new AlphaBetaBot(botPlayer, depth) : null; this.alphaBot = (mode == GameMode.PVALPHA) ? new AlphaBetaBot(botPlayer, depth) : null;
// A FAIRE PLUS TARD (PVGOD)
this.divineBot = (mode == GameMode.PVGOD) ? new DivineBot(botPlayer, depth) : null; this.divineBot = (mode == GameMode.PVGOD) ? new DivineBot(botPlayer, depth) : null;
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
@@ -169,28 +166,30 @@ public class AvalamWindow extends JFrame {
if (board.isGameOver()) { if (board.isGameOver()) {
Result res = board.getResult(); Result res = board.getResult();
String msg; int scoreJaune = computeScore(Color.YELLOW);
switch (res) { int scoreRouge = computeScore(Color.RED);
case WIN:
msg = "Le joueur jaune a gagné !";
break;
case LOSS:
msg = "Le joueur rouge a gagné !";
break;
case DRAW:
msg = "Égalité !";
break;
default:
msg = "Fin de partie.";
break;
}
JOptionPane.showMessageDialog( EndGameDialog dialog = new EndGameDialog(
this, this,
msg, res,
"Partie terminée", scoreJaune,
JOptionPane.INFORMATION_MESSAGE scoreRouge,
mode,
searchDepth,
// Rejouer : on ferme la fenêtre actuelle et on relance une nouvelle partie avec le même mode/profondeur
() -> SwingUtilities.invokeLater(() -> {
dispose();
new AvalamWindow(mode, searchDepth);
}),
// Menu principal : on ferme la fenêtre actuelle et on réaffiche le menu de mode de jeu
() -> SwingUtilities.invokeLater(() -> {
dispose();
Main.showModeSelection();
}),
// Quitter complètement l'application
() -> System.exit(0)
); );
dialog.setVisible(true);
return; return;
} }
@@ -220,12 +219,8 @@ public class AvalamWindow extends JFrame {
if (mode == GameMode.PVBOT && idiotBot == null) return; if (mode == GameMode.PVBOT && idiotBot == null) return;
if (mode == GameMode.PVALPHA && alphaBot == null) return; if (mode == GameMode.PVALPHA && alphaBot == null) return;
// A FAIRE PLUS TARD (PVGOD)
if (mode == GameMode.PVGOD && divineBot == null) return; if (mode == GameMode.PVGOD && divineBot == null) return;
// A FAIRE PLUS TARD (PVGOD)
// Pour l'instant, si PVGOD est sélectionné, on ne joue pas de coup bot.
botAnimating = true; botAnimating = true;
// Désactiver les interactions du joueur pendant le tour du bot. // Désactiver les interactions du joueur pendant le tour du bot.

View File

@@ -0,0 +1,160 @@
package fr.iut_fbleau.Avalam;
import fr.iut_fbleau.GameAPI.Result;
import javax.swing.*;
import java.awt.*;
/**
* Fenêtre de fin de partie.
*
* Elle est ouverte par {@link AvalamWindow} lorsque le moteur signale
* que la partie est terminée. Elle affiche :
* - le résultat (gagnant ou égalité) à partir du {@link Result} ;
* - le score détaillé (tours contrôlées par Jaune et Rouge) ;
* - le mode de jeu courant (PVP, PVBOT, PVALPHA, PVGOD, avec profondeur pour les bots intelligents).
*
* Elle propose également trois actions sous forme de boutons :
* - « Rejouer » : relancer une partie avec la même configuration ;
* - « Menu principal » : retourner au menu de sélection de mode ;
* - « Quitter » : fermer complètement lapplication.
*/
public class EndGameDialog extends JDialog {
/**
* Construit la fenêtre de fin de partie.
*
* @param parent fenêtre principale (généralement une {@link AvalamWindow})
* @param result résultat de la partie (WIN / LOSS / DRAW du point de vue de PLAYER1 / Jaune)
* @param scoreJaune score du joueur jaune (nombre de tours contrôlées)
* @param scoreRouge score du joueur rouge (nombre de tours contrôlées)
* @param mode mode de jeu courant (pour linformation et le « Rejouer »)
* @param depth profondeur utilisée (pour les modes avec bot intelligent)
* @param onReplay action à exécuter lorsque lutilisateur clique sur « Rejouer »
* @param onMenu action à exécuter lorsque lutilisateur clique sur « Menu principal »
* @param onQuit action à exécuter lorsque lutilisateur clique sur « Quitter »
*/
public EndGameDialog(
JFrame parent,
Result result,
int scoreJaune,
int scoreRouge,
GameMode mode,
int depth,
Runnable onReplay,
Runnable onMenu,
Runnable onQuit
) {
super(parent, "Fin de partie", true);
setLayout(new BorderLayout(10, 10));
// Panel principal d'information
JPanel infoPanel = new JPanel();
infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.Y_AXIS));
infoPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
JLabel titre = new JLabel("Partie terminée");
titre.setFont(titre.getFont().deriveFont(Font.BOLD, 18f));
titre.setAlignmentX(Component.CENTER_ALIGNMENT);
String gagnant;
switch (result) {
case WIN:
gagnant = "Le joueur JAUNE a gagné !";
break;
case LOSS:
gagnant = "Le joueur ROUGE a gagné !";
break;
case DRAW:
gagnant = "Égalité parfaite !";
break;
default:
gagnant = "Fin de partie.";
}
JLabel gagnantLabel = new JLabel(gagnant);
gagnantLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
JLabel scoreLabel = new JLabel(
"Score - Jaune : " + scoreJaune + " | Rouge : " + scoreRouge
);
scoreLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
JLabel modeLabel = new JLabel("Mode : " + modeToString(mode, depth));
modeLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
infoPanel.add(titre);
infoPanel.add(Box.createVerticalStrut(10));
infoPanel.add(gagnantLabel);
infoPanel.add(Box.createVerticalStrut(5));
infoPanel.add(scoreLabel);
infoPanel.add(Box.createVerticalStrut(5));
infoPanel.add(modeLabel);
add(infoPanel, BorderLayout.CENTER);
// Panel des boutons d'action
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 10));
JButton replayButton = new JButton("Rejouer");
replayButton.addActionListener(e -> {
if (onReplay != null) {
onReplay.run();
}
dispose();
});
JButton menuButton = new JButton("Menu principal");
menuButton.addActionListener(e -> {
if (onMenu != null) {
onMenu.run();
}
dispose();
});
JButton quitButton = new JButton("Quitter");
quitButton.addActionListener(e -> {
if (onQuit != null) {
onQuit.run();
}
dispose();
});
buttonPanel.add(replayButton);
buttonPanel.add(menuButton);
buttonPanel.add(quitButton);
add(buttonPanel, BorderLayout.SOUTH);
pack();
setResizable(false);
setLocationRelativeTo(parent);
}
/**
* Retourne une description lisible du mode de jeu courant.
*
* @param mode mode de jeu
* @param depth profondeur (pour les bots intelligents)
* @return chaîne décrivant le mode
*/
private String modeToString(GameMode mode, int depth) {
switch (mode) {
case PVP:
return "Joueur vs Joueur";
case PVBOT:
return "Joueur vs Bot idiot";
case PVALPHA:
return "Joueur vs Bot Alpha (profondeur " + depth + ")";
case PVGOD:
return "Joueur vs Bot Divin (profondeur " + depth + ")";
case ARENA:
return "Arène (bots)"; // normalement non utilisé ici
default:
return mode.name();
}
}
}

View File

@@ -22,7 +22,7 @@ public class Main {
"joueur vs joueur", "joueur vs joueur",
"joueur vs botidiot", "joueur vs botidiot",
"joueur vs bot alpha", "joueur vs bot alpha",
"joueur vs bot divin (NON IMPLEMENTE)", "joueur vs bot divin",
"Arène" "Arène"
}; };