From d907d2d52b64bb76d4ad940bea9941238fd29878 Mon Sep 17 00:00:00 2001 From: felix-vi Date: Sat, 31 Jan 2026 14:26:23 +0100 Subject: [PATCH 1/3] =?UTF-8?q?ajout=20du=20mode=20Arene=20o=C3=B9=20on=20?= =?UTF-8?q?choisi=20les=20bot=20qui=20s'affronte=20et=20le=20nombre=20de?= =?UTF-8?q?=20partie?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fr/iut_fbleau/Avalam/ArenaGame.java | 38 ++++ fr/iut_fbleau/Avalam/ArenaWindow.java | 246 ++++++++++++++++++++++++++ fr/iut_fbleau/Avalam/GameMode.java | 3 +- fr/iut_fbleau/Avalam/Main.java | 109 +++++++----- 4 files changed, 347 insertions(+), 49 deletions(-) create mode 100644 fr/iut_fbleau/Avalam/ArenaGame.java create mode 100644 fr/iut_fbleau/Avalam/ArenaWindow.java diff --git a/fr/iut_fbleau/Avalam/ArenaGame.java b/fr/iut_fbleau/Avalam/ArenaGame.java new file mode 100644 index 0000000..c115287 --- /dev/null +++ b/fr/iut_fbleau/Avalam/ArenaGame.java @@ -0,0 +1,38 @@ +package fr.iut_fbleau.Avalam; + +import fr.iut_fbleau.GameAPI.AbstractGame; +import fr.iut_fbleau.GameAPI.AbstractGamePlayer; +import fr.iut_fbleau.GameAPI.IBoard; +import fr.iut_fbleau.GameAPI.Player; + +import java.util.EnumMap; + +/** + * Classe pour jouer une partie entre deux bots sans interface graphique. + * Utilisée dans le mode Arène. + */ +public class ArenaGame extends AbstractGame { + + /** + * Construit une partie Arène entre deux bots. + * + * @param board plateau initial + * @param bot1 bot pour PLAYER1 + * @param bot2 bot pour PLAYER2 + */ + public ArenaGame(IBoard board, AbstractGamePlayer bot1, AbstractGamePlayer bot2) { + super(board, createPlayerMap(bot1, bot2)); + } + + /** + * Crée la map des joueurs pour AbstractGame. + */ + private static EnumMap createPlayerMap( + AbstractGamePlayer bot1, AbstractGamePlayer bot2) { + EnumMap map = new EnumMap<>(Player.class); + map.put(Player.PLAYER1, bot1); + map.put(Player.PLAYER2, bot2); + return map; + } +} + diff --git a/fr/iut_fbleau/Avalam/ArenaWindow.java b/fr/iut_fbleau/Avalam/ArenaWindow.java new file mode 100644 index 0000000..772cd8b --- /dev/null +++ b/fr/iut_fbleau/Avalam/ArenaWindow.java @@ -0,0 +1,246 @@ +package fr.iut_fbleau.Avalam; + +import fr.iut_fbleau.Bot.AlphaBetaBot; +import fr.iut_fbleau.Bot.IdiotBot; +import fr.iut_fbleau.GameAPI.AbstractGamePlayer; +import fr.iut_fbleau.GameAPI.Player; +import fr.iut_fbleau.GameAPI.Result; + +import javax.swing.*; +import javax.swing.table.DefaultTableModel; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +/** + * Fenêtre pour le mode Arène. + * Permet de sélectionner deux bots, le nombre de parties, et affiche les résultats. + */ +public class ArenaWindow extends JFrame { + + private JTable resultsTable; + private DefaultTableModel tableModel; + private List results; + + /** + * Construit la fenêtre Arène. + */ + public ArenaWindow() { + super("Arène - Bot vs Bot"); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + setLayout(new BorderLayout()); + + results = new ArrayList<>(); + + // Panneau de configuration + JPanel configPanel = createConfigPanel(); + add(configPanel, BorderLayout.NORTH); + + // Tableau des résultats + createResultsTable(); + JScrollPane scrollPane = new JScrollPane(resultsTable); + add(scrollPane, BorderLayout.CENTER); + + // Bouton pour lancer les parties + JButton startButton = new JButton("Lancer les parties"); + startButton.addActionListener(e -> showConfigDialog()); + add(startButton, BorderLayout.SOUTH); + + pack(); + setSize(600, 400); + setLocationRelativeTo(null); + setVisible(true); + } + + /** + * Crée le panneau de configuration (pour l'instant vide, sera rempli par le dialogue). + */ + private JPanel createConfigPanel() { + JPanel panel = new JPanel(); + panel.setBorder(BorderFactory.createTitledBorder("Configuration")); + panel.add(new JLabel("Utilisez le bouton 'Lancer les parties' pour configurer et démarrer.")); + return panel; + } + + /** + * Crée le tableau des résultats. + */ + private void createResultsTable() { + String[] columnNames = {"Partie", "Bot 1", "Bot 2", "Gagnant"}; + tableModel = new DefaultTableModel(columnNames, 0) { + @Override + public boolean isCellEditable(int row, int column) { + return false; + } + }; + resultsTable = new JTable(tableModel); + resultsTable.setFillsViewportHeight(true); + } + + /** + * Affiche le dialogue de configuration et lance les parties. + */ + private void showConfigDialog() { + // Choix du bot 1 + String[] botTypes = {"Bot Idiot", "Bot Alpha-Beta", "Bot Divin"}; + String bot1Choice = (String) JOptionPane.showInputDialog( + this, + "Choisissez le Bot 1 (Joueur 1) :", + "Configuration Arène - Bot 1", + JOptionPane.QUESTION_MESSAGE, + null, + botTypes, + botTypes[0] + ); + + if (bot1Choice == null) return; + + // Choix du bot 2 + String bot2Choice = (String) JOptionPane.showInputDialog( + this, + "Choisissez le Bot 2 (Joueur 2) :", + "Configuration Arène - Bot 2", + JOptionPane.QUESTION_MESSAGE, + null, + botTypes, + botTypes[0] + ); + + if (bot2Choice == null) return; + + // Profondeur pour Alpha-Beta et Divin + int depth = 4; + if (bot1Choice.contains("Alpha") || bot1Choice.contains("Divin") || + bot2Choice.contains("Alpha") || bot2Choice.contains("Divin")) { + String depthStr = JOptionPane.showInputDialog( + this, + "Profondeur de recherche pour les bots Alpha-Beta/Divin ?\n(Conseil: 4)", + "Profondeur", + JOptionPane.QUESTION_MESSAGE + ); + if (depthStr != null) { + try { + depth = Integer.parseInt(depthStr.trim()); + if (depth < 1) depth = 1; + } catch (Exception e) { + depth = 4; + } + } + } + + // Nombre de parties + String nbPartiesStr = JOptionPane.showInputDialog( + this, + "Combien de parties voulez-vous jouer ?", + "Nombre de parties", + JOptionPane.QUESTION_MESSAGE + ); + + if (nbPartiesStr == null) return; + + int nbParties; + try { + nbParties = Integer.parseInt(nbPartiesStr.trim()); + if (nbParties < 1) { + JOptionPane.showMessageDialog(this, "Le nombre de parties doit être au moins 1."); + return; + } + } catch (Exception e) { + JOptionPane.showMessageDialog(this, "Nombre invalide."); + return; + } + + // Lancer les parties + runArena(bot1Choice, bot2Choice, depth, nbParties); + } + + /** + * Lance les parties entre les deux bots. + */ + private void runArena(String bot1Type, String bot2Type, int depth, int nbParties) { + // Créer les bots + AbstractGamePlayer bot1 = createBot(bot1Type, Player.PLAYER1, depth); + AbstractGamePlayer bot2 = createBot(bot2Type, Player.PLAYER2, depth); + + if (bot1 == null || bot2 == null) { + JOptionPane.showMessageDialog(this, "Erreur lors de la création des bots."); + return; + } + + // Vider le tableau + tableModel.setRowCount(0); + results.clear(); + + // Charger le plateau initial + Tower[][] initialGrid = BoardLoader.loadFromFile("fr/iut_fbleau/Res/Plateau.txt"); + + // Lancer les parties + for (int i = 1; i <= nbParties; i++) { + AvalamBoard board = new AvalamBoard(initialGrid, Player.PLAYER1); + ArenaGame game = new ArenaGame(board, bot1, bot2); + + try { + Result result = game.run(); + String winner = getWinnerName(result, bot1Type, bot2Type); + + // Ajouter au tableau + tableModel.addRow(new Object[]{ + "Partie " + i, + bot1Type, + bot2Type, + winner + }); + } catch (Exception e) { + tableModel.addRow(new Object[]{ + "Partie " + i, + bot1Type, + bot2Type, + "Erreur: " + e.getMessage() + }); + } + } + + // Afficher un message de fin + JOptionPane.showMessageDialog( + this, + "Toutes les parties sont terminées !", + "Arène terminée", + JOptionPane.INFORMATION_MESSAGE + ); + } + + /** + * Crée un bot selon son type. + */ + private AbstractGamePlayer createBot(String botType, Player player, int depth) { + if (botType.equals("Bot Idiot")) { + return new IdiotBot(player); + } else if (botType.equals("Bot Alpha-Beta")) { + return new AlphaBetaBot(player, depth); + } else if (botType.equals("Bot Divin")) { + // Pour l'instant, le Bot Divin n'est pas implémenté, on utilise IdiotBot + 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; + } + + /** + * Détermine le nom du gagnant selon le résultat. + */ + private String getWinnerName(Result result, String bot1Type, String bot2Type) { + if (result == Result.WIN) { + return bot1Type + " (Joueur 1)"; + } else if (result == Result.LOSS) { + return bot2Type + " (Joueur 2)"; + } else { + return "Match nul"; + } + } +} + diff --git a/fr/iut_fbleau/Avalam/GameMode.java b/fr/iut_fbleau/Avalam/GameMode.java index 09c306a..b5a83d9 100644 --- a/fr/iut_fbleau/Avalam/GameMode.java +++ b/fr/iut_fbleau/Avalam/GameMode.java @@ -7,5 +7,6 @@ public enum GameMode { PVP, // joueur vs joueur PVBOT, // joueur vs bot idiot PVALPHA, // joueur vs bot alpha - PVGOD // joueur vs bot stratégique + PVGOD, // joueur vs bot stratégique + ARENA // bot vs bot (mode arène) } diff --git a/fr/iut_fbleau/Avalam/Main.java b/fr/iut_fbleau/Avalam/Main.java index 6cd72de..598e445 100644 --- a/fr/iut_fbleau/Avalam/Main.java +++ b/fr/iut_fbleau/Avalam/Main.java @@ -8,62 +8,75 @@ import javax.swing.*; public class Main { public static void main(String[] args) { - SwingUtilities.invokeLater(() -> { + showModeSelection(); + }); + } - String[] options = { - "joueur vs joueur", - "joueur vs botidiot", - "joueur vs bot alpha", - "joueur vs bot divin (NON IMPLEMENTE)" - }; + /** + * Affiche le menu de sélection du mode de jeu. + * Peut être appelé depuis d'autres fenêtres pour revenir au menu. + */ + public static void showModeSelection() { + String[] options = { + "joueur vs joueur", + "joueur vs botidiot", + "joueur vs bot alpha", + "joueur vs bot divin (NON IMPLEMENTE)", + "Arène" + }; - int choice = JOptionPane.showOptionDialog( + int choice = JOptionPane.showOptionDialog( + null, + "Choisissez un mode de jeu :", + "Avalam - Mode de jeu", + JOptionPane.DEFAULT_OPTION, + JOptionPane.QUESTION_MESSAGE, + null, + options, + options[0] + ); + + if (choice == -1) System.exit(0); + + // Mode Arène + if (choice == 4) { + new ArenaWindow(); + return; + } + + GameMode mode; + if (choice == 1) mode = GameMode.PVBOT; + else if (choice == 2) mode = GameMode.PVALPHA; + else if (choice == 3) mode = GameMode.PVGOD; + else mode = GameMode.PVP; + + // Pour ALPHA et GOD : demander une profondeur + if (mode == GameMode.PVALPHA || mode == GameMode.PVGOD) { + + String s = JOptionPane.showInputDialog( null, - "Choisissez un mode de jeu :", - "Avalam - Mode de jeu", - JOptionPane.DEFAULT_OPTION, - JOptionPane.QUESTION_MESSAGE, - null, - options, - options[0] + "Profondeur de recherche ?\n(Conseil 4)", + (mode == GameMode.PVGOD ? "Bot Divin (PVGOD)" : "Bot Alpha-Beta"), + JOptionPane.QUESTION_MESSAGE ); - if (choice == -1) System.exit(0); - - GameMode mode; - if (choice == 1) mode = GameMode.PVBOT; - else if (choice == 2) mode = GameMode.PVALPHA; - else if (choice == 3) mode = GameMode.PVGOD; - else mode = GameMode.PVP; - - // Pour ALPHA et GOD : demander une profondeur - if (mode == GameMode.PVALPHA || mode == GameMode.PVGOD) { - - String s = JOptionPane.showInputDialog( - null, - "Profondeur de recherche ?\n(Conseil 4)", - (mode == GameMode.PVGOD ? "Bot Divin (PVGOD)" : "Bot Alpha-Beta"), - JOptionPane.QUESTION_MESSAGE - ); - - int depth = 4; // défaut - if (s != null) { - try { depth = Integer.parseInt(s.trim()); } - catch (Exception ignored) { depth = 4; } - } else { - // Annulation : on revient en PVP - new AvalamWindow(GameMode.PVP); - return; - } - - if (depth < 1) depth = 1; - - new AvalamWindow(mode, depth); + int depth = 4; // défaut + if (s != null) { + try { depth = Integer.parseInt(s.trim()); } + catch (Exception ignored) { depth = 4; } + } else { + // Annulation : on revient en PVP + new AvalamWindow(GameMode.PVP); return; } - new AvalamWindow(mode); - }); + if (depth < 1) depth = 1; + + new AvalamWindow(mode, depth); + return; + } + + new AvalamWindow(mode); } } From be459707ce8f4ffe1d043d218e55ca7d1ee108ef Mon Sep 17 00:00:00 2001 From: felix-vi Date: Sat, 31 Jan 2026 14:28:05 +0100 Subject: [PATCH 2/3] =?UTF-8?q?commit=20rapide=20car=20j'avais=20d=C3=A9j?= =?UTF-8?q?=C3=A0=20le=20code=20mais=20que=20je=20n'avais=20pas=20push=20l?= =?UTF-8?q?e=20code=20d'avant?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fr/iut_fbleau/Avalam/ArenaWindow.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/fr/iut_fbleau/Avalam/ArenaWindow.java b/fr/iut_fbleau/Avalam/ArenaWindow.java index 772cd8b..99d6c87 100644 --- a/fr/iut_fbleau/Avalam/ArenaWindow.java +++ b/fr/iut_fbleau/Avalam/ArenaWindow.java @@ -41,10 +41,20 @@ public class ArenaWindow extends JFrame { JScrollPane scrollPane = new JScrollPane(resultsTable); add(scrollPane, BorderLayout.CENTER); - // Bouton pour lancer les parties + // Panneau des boutons + JPanel buttonPanel = new JPanel(new FlowLayout()); JButton startButton = new JButton("Lancer les parties"); startButton.addActionListener(e -> showConfigDialog()); - add(startButton, BorderLayout.SOUTH); + buttonPanel.add(startButton); + + JButton backButton = new JButton("Retour au menu"); + backButton.addActionListener(e -> { + dispose(); // Ferme la fenêtre Arène + Main.showModeSelection(); // Affiche le menu principal + }); + buttonPanel.add(backButton); + + add(buttonPanel, BorderLayout.SOUTH); pack(); setSize(600, 400); From b4f93e7647596366f73cff0341d9149afebeabcd Mon Sep 17 00:00:00 2001 From: felix-vi Date: Sun, 1 Feb 2026 17:24:43 +0100 Subject: [PATCH 3/3] =?UTF-8?q?j'avais=20oubli=C3=A9=20de=20faire=20la=20j?= =?UTF-8?q?avadoc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fr/iut_fbleau/Avalam/ArenaGame.java | 6 ++++++ fr/iut_fbleau/Avalam/ArenaWindow.java | 26 +++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/fr/iut_fbleau/Avalam/ArenaGame.java b/fr/iut_fbleau/Avalam/ArenaGame.java index c115287..aa27144 100644 --- a/fr/iut_fbleau/Avalam/ArenaGame.java +++ b/fr/iut_fbleau/Avalam/ArenaGame.java @@ -10,6 +10,8 @@ import java.util.EnumMap; /** * Classe pour jouer une partie entre deux bots sans interface graphique. * Utilisée dans le mode Arène. + * + * @version 1.0 */ public class ArenaGame extends AbstractGame { @@ -26,6 +28,10 @@ public class ArenaGame extends AbstractGame { /** * Crée la map des joueurs pour AbstractGame. + * + * @param bot1 bot pour PLAYER1 + * @param bot2 bot pour PLAYER2 + * @return une EnumMap associant chaque Player à son bot */ private static EnumMap createPlayerMap( AbstractGamePlayer bot1, AbstractGamePlayer bot2) { diff --git a/fr/iut_fbleau/Avalam/ArenaWindow.java b/fr/iut_fbleau/Avalam/ArenaWindow.java index 99d6c87..09982df 100644 --- a/fr/iut_fbleau/Avalam/ArenaWindow.java +++ b/fr/iut_fbleau/Avalam/ArenaWindow.java @@ -15,11 +15,18 @@ import java.util.List; /** * Fenêtre pour le mode Arène. * Permet de sélectionner deux bots, le nombre de parties, et affiche les résultats. + * + * @version 1.0 */ public class ArenaWindow extends JFrame { + /** Tableau affichant les résultats des parties. */ private JTable resultsTable; + + /** Modèle de données pour le tableau des résultats. */ private DefaultTableModel tableModel; + + /** Liste des résultats des parties (non utilisée actuellement). */ private List results; /** @@ -64,6 +71,8 @@ public class ArenaWindow extends JFrame { /** * Crée le panneau de configuration (pour l'instant vide, sera rempli par le dialogue). + * + * @return un JPanel contenant les informations de configuration */ private JPanel createConfigPanel() { JPanel panel = new JPanel(); @@ -73,7 +82,7 @@ public class ArenaWindow extends JFrame { } /** - * Crée le tableau des résultats. + * Crée le tableau des résultats avec les colonnes : Partie, Bot 1, Bot 2, Gagnant. */ private void createResultsTable() { String[] columnNames = {"Partie", "Bot 1", "Bot 2", "Gagnant"}; @@ -166,6 +175,11 @@ public class ArenaWindow extends JFrame { /** * Lance les parties entre les deux bots. + * + * @param bot1Type type du bot 1 (Joueur 1) + * @param bot2Type type du bot 2 (Joueur 2) + * @param depth profondeur de recherche pour les bots Alpha-Beta/Divin + * @param nbParties nombre de parties à jouer */ private void runArena(String bot1Type, String bot2Type, int depth, int nbParties) { // Créer les bots @@ -221,6 +235,11 @@ public class ArenaWindow extends JFrame { /** * Crée un bot selon son type. + * + * @param botType type de bot ("Bot Idiot", "Bot Alpha-Beta", "Bot Divin") + * @param player joueur contrôlé par ce bot (PLAYER1 ou PLAYER2) + * @param depth profondeur de recherche pour Alpha-Beta/Divin + * @return une instance de AbstractGamePlayer correspondant au type, ou null si le type est invalide */ private AbstractGamePlayer createBot(String botType, Player player, int depth) { if (botType.equals("Bot Idiot")) { @@ -242,6 +261,11 @@ public class ArenaWindow extends JFrame { /** * Détermine le nom du gagnant selon le résultat. + * + * @param result résultat de la partie (WIN, LOSS, ou DRAW du point de vue de PLAYER1) + * @param bot1Type nom du bot 1 + * @param bot2Type nom du bot 2 + * @return une chaîne indiquant le gagnant ou "Match nul" */ private String getWinnerName(Result result, String bot1Type, String bot2Type) { if (result == Result.WIN) {