diff --git a/fr/iut_fbleau/Avalam/AvalamWindow.java b/fr/iut_fbleau/Avalam/AvalamWindow.java
index 36492e5..d0e6304 100644
--- a/fr/iut_fbleau/Avalam/AvalamWindow.java
+++ b/fr/iut_fbleau/Avalam/AvalamWindow.java
@@ -1,5 +1,7 @@
package fr.iut_fbleau.Avalam;
+import fr.iut_fbleau.Bot.IdiotBot;
+import fr.iut_fbleau.GameAPI.AbstractPly;
import fr.iut_fbleau.GameAPI.Player;
import fr.iut_fbleau.GameAPI.Result;
@@ -12,10 +14,18 @@ import java.awt.*;
* Fenêtre principale (interface graphique) du jeu Avalam.
* Elle contient :
* - le plateau (BoardView)
-* - l'affichage du score (ScoreView)
-* - l'affichage du joueur courant (TurnView)
+* - l’affichage du score (ScoreView)
+* - l’affichage du joueur courant (TurnView)
*
* Elle pilote un objet AvalamBoard (moteur du jeu).
+* Elle peut fonctionner en mode :
+* - joueur vs joueur
+* - joueur vs bot idiot (aléatoire)
+* - joueur vs bot alpha (préparé)
+*
+* @version 1.0
+* Date :
+* Licence :
*/
public class AvalamWindow extends JFrame {
@@ -24,36 +34,57 @@ public class AvalamWindow extends JFrame {
/** Moteur du jeu (état + règles). */
private AvalamBoard board;
- /** Vue affichant le score des deux couleurs. */
+ /** Vue affichant le score. */
private ScoreView scoreView;
- /** Vue affichant le joueur dont c'est le tour. */
+ /** Vue affichant le joueur courant. */
private TurnView turnView;
- /** Vue affichant le plateau et gérant les interactions de jeu. */
+ /** Vue affichant le plateau. */
private BoardView boardView;
+ /** Mode de jeu sélectionné. */
+ private final GameMode mode;
+
+ /** Joueur contrôlé par le bot (si actif). */
+ private final Player botPlayer = Player.PLAYER2;
+
+ /** Bot idiot (utilisé si mode PVBOT). */
+ private final IdiotBot idiotBot;
+
+ /** Indique si une animation de tour de bot est en cours. */
+ private boolean botAnimating = false;
+
//Constructeur
/**
- * Construit la fenêtre et initialise l’interface :
- * - charge le plateau initial depuis Plateau.txt
- * - construit les vues (score, tour, plateau)
- * - affiche la fenêtre
+ * Construit la fenêtre en mode joueur vs joueur.
*/
public AvalamWindow() {
+ this(GameMode.PVP);
+ }
+
+ /**
+ * Construit la fenêtre en fonction du mode choisi.
+ *
+ * @param mode mode de jeu
+ */
+ public AvalamWindow(GameMode mode) {
super("Avalam");
+ this.mode = mode;
+ this.idiotBot = (mode == GameMode.PVBOT) ? new IdiotBot(botPlayer) : null;
+
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
- // Chargement du plateau initial depuis Plateau.txt
+ // Chargement du plateau initial
Tower[][] initialGrid = BoardLoader.loadFromFile("fr/iut_fbleau/Res/Plateau.txt");
// Initialisation du moteur (PLAYER1 commence)
board = new AvalamBoard(initialGrid);
- // Création du panneau supérieur (score + tour)
+ // Panneau supérieur (score + tour)
JPanel topPanel = new JPanel(new GridLayout(2, 1));
topPanel.setBackground(new java.awt.Color(200, 200, 200));
@@ -69,7 +100,7 @@ public class AvalamWindow extends JFrame {
add(topPanel, BorderLayout.NORTH);
- // Création de la vue plateau (avec callback de mise à jour)
+ // Plateau
boardView = new BoardView(board, this::onBoardUpdated);
add(boardView, BorderLayout.CENTER);
@@ -77,35 +108,30 @@ public class AvalamWindow extends JFrame {
setResizable(false);
setLocationRelativeTo(null);
setVisible(true);
+
+ // Si un jour le bot doit commencer, on peut déclencher ici.
+ maybePlayBotTurn();
}
//Méthodes
/**
- * Méthode appelée automatiquement après chaque coup (via BoardView).
- * Elle rafraîchit :
- * - les scores
- * - le joueur courant
- * et affiche un message si la partie est terminée.
+ * Appelée après chaque coup (humain ou bot).
+ * Met à jour score, tour, et affiche la fin de partie.
*/
public void onBoardUpdated() {
- // Mise à jour du score
scoreView.updateScores(
computeScore(Color.YELLOW),
computeScore(Color.RED)
);
- // Mise à jour du joueur courant
turnView.setTurn(turnMessage());
- // Détection de fin de partie
if (board.isGameOver()) {
Result res = board.getResult();
String msg;
-
- // Correction : ajout des "break" pour éviter le fall-through.
switch (res) {
case WIN:
msg = "Le joueur jaune a gagné !";
@@ -127,11 +153,80 @@ public class AvalamWindow extends JFrame {
"Partie terminée",
JOptionPane.INFORMATION_MESSAGE
);
+ return;
}
+
+ // Si on est contre un bot et que c’est son tour, on déclenche son animation.
+ maybePlayBotTurn();
}
/**
- * Calcule le score d'une couleur : nombre de tours contrôlées (sommet de la tour).
+ * Fait jouer le bot en deux étapes visibles :
+ * 1) sélection de la tour (affiche les coups légaux)
+ * 2) attente 1 seconde
+ * 3) déplacement vers la destination
+ *
+ * Le tout sans bloquer l'interface (Timer Swing).
+ */
+ private void maybePlayBotTurn() {
+
+ if (mode != GameMode.PVBOT) return;
+ if (board.isGameOver()) return;
+ if (board.getCurrentPlayer() != botPlayer) return;
+ if (botAnimating) return;
+
+ botAnimating = true;
+
+ // Désactiver les interactions du joueur pendant le tour du bot.
+ boardView.setInteractionEnabled(false);
+
+ // Choix d’un coup sur une copie sûre
+ AbstractPly botMove = idiotBot.giveYourMove(board.safeCopy());
+ if (botMove == null) {
+ botAnimating = false;
+ boardView.setInteractionEnabled(true);
+ return;
+ }
+
+ if (!(botMove instanceof AvalamPly)) {
+ botAnimating = false;
+ boardView.setInteractionEnabled(true);
+ return;
+ }
+
+ AvalamPly ap = (AvalamPly) botMove;
+
+ // Étape 1 : sélection (comme un clic humain)
+ InteractionController ctrl = boardView.getController();
+ ctrl.onPieceClicked(ap.getXFrom(), ap.getYFrom());
+ boardView.refresh();
+
+ // Étape 2 : attendre puis cliquer la destination
+ javax.swing.Timer t = new javax.swing.Timer(1000, e -> {
+
+ // Sécurité : si la partie a changé entre temps
+ if (board.isGameOver() || board.getCurrentPlayer() != botPlayer) {
+ botAnimating = false;
+ boardView.setInteractionEnabled(true);
+ ((javax.swing.Timer) e.getSource()).stop();
+ return;
+ }
+
+ ctrl.onPieceClicked(ap.getXTo(), ap.getYTo());
+ boardView.refresh();
+
+ botAnimating = false;
+ boardView.setInteractionEnabled(true);
+
+ ((javax.swing.Timer) e.getSource()).stop();
+ });
+
+ t.setRepeats(false);
+ t.start();
+ }
+
+ /**
+ * Calcule le score d'une couleur : nombre de tours contrôlées.
*
* @param c couleur à compter
* @return nombre de tours appartenant à la couleur c
@@ -150,12 +245,14 @@ public class AvalamWindow extends JFrame {
}
/**
- * Retourne le message correspondant au joueur dont c'est le tour.
+ * Retourne le message affiché pour le joueur courant.
*
- * @return message d’affichage du tour
+ * @return message du tour
*/
private String turnMessage() {
return "Tour du joueur : " +
(board.getCurrentPlayer() == Player.PLAYER1 ? "Jaune" : "Rouge");
}
+
+ //Affichage
}
diff --git a/fr/iut_fbleau/Avalam/BoardView.java b/fr/iut_fbleau/Avalam/BoardView.java
index 208f79b..382c5e6 100644
--- a/fr/iut_fbleau/Avalam/BoardView.java
+++ b/fr/iut_fbleau/Avalam/BoardView.java
@@ -1,8 +1,5 @@
package fr.iut_fbleau.Avalam;
-import fr.iut_fbleau.Avalam.AvalamBoard;
-import fr.iut_fbleau.Avalam.Tower;
-
import javax.swing.*;
import java.awt.*;
@@ -14,33 +11,37 @@ import java.awt.*;
* - l’affichage des tours (PieceLayer)
* - l’affichage des coups possibles (HighlightLayer)
* - l’affichage du fond graphique
-* - la gestion des interactions via InteractionController
+* - les clics via InteractionController
*
-* Cette classe ne contient aucune logique de jeu.
+* Cette classe ne contient aucune logique de règles du jeu.
+*
+* @version 1.0
+* Date :
+* Licence :
*/
public class BoardView extends JLayeredPane {
//Attributs
- /** Référence au moteur du jeu Avalam. */
+ /** Référence au moteur Avalam. */
private AvalamBoard board;
- /** Couche graphique du fond du plateau. */
+ /** Couche d’affichage du fond. */
private BackgroundLayer backgroundLayer;
- /** Couche graphique des déplacements possibles. */
+ /** Couche d’affichage des coups possibles. */
private HighlightLayer highlightLayer;
- /** Couche graphique des pièces (tours). */
+ /** Couche d’affichage des pièces. */
private PieceLayer pieceLayer;
- /** Contrôleur des interactions utilisateur. */
+ /** Contrôleur des interactions. */
private InteractionController controller;
/** Taille d’un pion en pixels. */
private final int size = 50;
- /** Espacement entre deux cases du plateau. */
+ /** Espacement entre les cases. */
private final int spacing = 70;
/** Décalage horizontal du plateau. */
@@ -49,16 +50,16 @@ public class BoardView extends JLayeredPane {
/** Décalage vertical du plateau. */
private final int yBase = 60;
- /** Callback vers AvalamWindow pour mettre à jour l’interface (score, tour, fin). */
+ /** Callback vers AvalamWindow pour mise à jour (score, tour, fin). */
private Runnable boardUpdateCallback;
//Constructeur
/**
- * Construit la vue du plateau Avalam.
+ * Construit la vue du plateau.
*
- * @param board moteur du jeu Avalam
- * @param boardUpdateCallback fonction de rappel après un coup
+ * @param board moteur du jeu
+ * @param boardUpdateCallback callback à appeler après un coup
*/
public BoardView(AvalamBoard board, Runnable boardUpdateCallback) {
this.board = board;
@@ -66,19 +67,19 @@ public class BoardView extends JLayeredPane {
setLayout(null);
- // --- Contrôleur ---
+ // Contrôleur
this.controller = new InteractionController(board, this);
- // --- Couche fond ---
+ // Couche fond
backgroundLayer = new BackgroundLayer("fr/iut_fbleau/Res/BackgroundAvalam.png");
backgroundLayer.setBounds(0, 0, 725, 725);
add(backgroundLayer, JLayeredPane.FRAME_CONTENT_LAYER);
- // --- Couche highlight ---
+ // Couche highlight
highlightLayer = new HighlightLayer(xBase, yBase, spacing, size);
add(highlightLayer, JLayeredPane.DEFAULT_LAYER);
- // --- Couche des pièces ---
+ // Couche pièces
pieceLayer = new PieceLayer();
add(pieceLayer, JLayeredPane.PALETTE_LAYER);
@@ -89,6 +90,29 @@ public class BoardView extends JLayeredPane {
//Méthodes
+ /**
+ * Retourne le contrôleur d'interactions (utile pour simuler les clics du bot).
+ *
+ * @return contrôleur
+ */
+ public InteractionController getController() {
+ return controller;
+ }
+
+ /**
+ * Active/désactive les interactions utilisateur sur le plateau.
+ * Utile pendant l'animation du bot pour éviter des clics concurrents.
+ *
+ * @param enabled true pour activer, false pour désactiver
+ */
+ public void setInteractionEnabled(boolean enabled) {
+ // Désactive la couche des pièces (boutons) principalement
+ pieceLayer.setEnabled(enabled);
+ for (Component c : pieceLayer.getComponents()) {
+ c.setEnabled(enabled);
+ }
+ }
+
/**
* Appelé par le contrôleur après un coup.
*/
@@ -99,7 +123,7 @@ public class BoardView extends JLayeredPane {
}
/**
- * Rafraîchit l’affichage du plateau.
+ * Rafraîchit les couches visuelles.
*/
public void refresh() {
@@ -118,7 +142,7 @@ public class BoardView extends JLayeredPane {
}
/**
- * Récupère la grille actuelle du moteur de jeu.
+ * Récupère la grille depuis le moteur.
*
* @return grille 9x9 de tours
*/
@@ -136,24 +160,26 @@ public class BoardView extends JLayeredPane {
//Affichage
/**
- * Classe interne représentant la couche graphique du fond.
+ * Composant affichant l’image de fond.
*/
private static class BackgroundLayer extends JComponent {
private Image img;
/**
- * Construit une couche de fond à partir d’une image.
+ * Construit une couche de fond.
*
- * @param resourcePath chemin de l’image
+ * @param resourcePath chemin de l'image de fond
*/
public BackgroundLayer(String resourcePath) {
img = Toolkit.getDefaultToolkit().getImage(
- getClass().getClassLoader().getResource(resourcePath)
+ getClass().getClassLoader().getResource(resourcePath)
);
}
/**
- * Dessine l’image de fond.
+ * Dessine l'image de fond.
+ *
+ * @param g contexte graphique
*/
@Override
protected void paintComponent(Graphics g) {
diff --git a/fr/iut_fbleau/Avalam/GameMode.java b/fr/iut_fbleau/Avalam/GameMode.java
new file mode 100644
index 0000000..8d5ac1b
--- /dev/null
+++ b/fr/iut_fbleau/Avalam/GameMode.java
@@ -0,0 +1,10 @@
+package fr.iut_fbleau.Avalam;
+
+/**
+ * Mode de jeu au lancement.
+ */
+public enum GameMode {
+ PVP, // joueur vs joueur
+ PVBOT, // joueur vs bot idiot
+ PVALPHA // joueur vs bot alpha (préparé)
+}
diff --git a/fr/iut_fbleau/Avalam/Main.java b/fr/iut_fbleau/Avalam/Main.java
index 4257f02..91bb0aa 100644
--- a/fr/iut_fbleau/Avalam/Main.java
+++ b/fr/iut_fbleau/Avalam/Main.java
@@ -1,28 +1,50 @@
package fr.iut_fbleau.Avalam;
+import javax.swing.*;
+
/**
-* La classe Main
-*
-* Point d’entrée du programme.
-* Lance l’interface graphique principale (AvalamWindow).
-*/
+ * Point d’entrée : propose un menu de sélection de mode, puis lance la fenêtre Avalam.
+ */
public class Main {
- //Attributs
-
- //Constructeur
- public Main() {
-
- }
-
- //Méthodes
-
- /**
- * Méthode principale : démarre l’application.
- *
- * @param args arguments de la ligne de commande (non utilisés)
- */
public static void main(String[] args) {
- new AvalamWindow();
+
+ SwingUtilities.invokeLater(() -> {
+
+ String[] options = {
+ "joueur vs joueur",
+ "joueur vs botidiot",
+ "joueur vs bot alpha"
+ };
+
+ int choice = JOptionPane.showOptionDialog(
+ null,
+ "Choisissez un mode de jeu :",
+ "Avalam - Mode de jeu",
+ JOptionPane.DEFAULT_OPTION,
+ JOptionPane.QUESTION_MESSAGE,
+ null,
+ options,
+ options[0]
+ );
+
+ GameMode mode;
+ if (choice == 1) mode = GameMode.PVBOT;
+ else if (choice == 2) mode = GameMode.PVALPHA;
+ else mode = GameMode.PVP;
+
+ // Si alpha choisi : non implémenté, on prévient et on lance en PVP (préparation).
+ if (mode == GameMode.PVALPHA) {
+ JOptionPane.showMessageDialog(
+ null,
+ "Bot Alpha-Beta non implémenté pour l'instant.\nLancement en joueur vs joueur.",
+ "Information",
+ JOptionPane.INFORMATION_MESSAGE
+ );
+ mode = GameMode.PVP;
+ }
+
+ new AvalamWindow(mode);
+ });
}
}
diff --git a/fr/iut_fbleau/Bot/AlphaBetaBot.java b/fr/iut_fbleau/Bot/AlphaBetaBot.java
new file mode 100644
index 0000000..459b99f
--- /dev/null
+++ b/fr/iut_fbleau/Bot/AlphaBetaBot.java
@@ -0,0 +1,22 @@
+package fr.iut_fbleau.Bot;
+
+import fr.iut_fbleau.GameAPI.AbstractGamePlayer;
+import fr.iut_fbleau.GameAPI.AbstractPly;
+import fr.iut_fbleau.GameAPI.IBoard;
+import fr.iut_fbleau.GameAPI.Player;
+
+/**
+ * Bot Alpha-Beta (préparé).
+ * Pour l'instant non implémenté.
+ */
+public class AlphaBetaBot extends AbstractGamePlayer {
+
+ public AlphaBetaBot(Player p) {
+ super(p);
+ }
+
+ @Override
+ public AbstractPly giveYourMove(IBoard board) {
+ throw new UnsupportedOperationException("AlphaBetaBot non implémenté pour l'instant.");
+ }
+}
diff --git a/fr/iut_fbleau/Bot/IdiotBot.java b/fr/iut_fbleau/Bot/IdiotBot.java
new file mode 100644
index 0000000..ffd5135
--- /dev/null
+++ b/fr/iut_fbleau/Bot/IdiotBot.java
@@ -0,0 +1,43 @@
+package fr.iut_fbleau.Bot;
+
+import fr.iut_fbleau.GameAPI.AbstractGamePlayer;
+import fr.iut_fbleau.GameAPI.AbstractPly;
+import fr.iut_fbleau.GameAPI.IBoard;
+import fr.iut_fbleau.GameAPI.Player;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Bot idiot : choisit un coup légal au hasard parmi ceux retournés par IBoard.iterator().
+ * Compatible avec n'importe quel jeu respectant GameAPI (dont AvalamBoard).
+ */
+public class IdiotBot extends AbstractGamePlayer {
+
+ private final Random rng;
+
+ public IdiotBot(Player p) {
+ super(p);
+ this.rng = new Random();
+ }
+
+ @Override
+ public AbstractPly giveYourMove(IBoard board) {
+
+ // Si la partie est terminée ou qu'il n'y a pas de coups, on ne joue rien.
+ if (board == null || board.isGameOver()) return null;
+
+ Iterator it = board.iterator();
+ List moves = new ArrayList<>();
+
+ while (it.hasNext()) {
+ moves.add(it.next());
+ }
+
+ if (moves.isEmpty()) return null;
+
+ return moves.get(rng.nextInt(moves.size()));
+ }
+}