Files
BUT3ProjetJeuGroupe/fr/iut_fbleau/Avalam/AvalamWindow.java
2026-01-26 13:41:48 +01:00

259 lines
7.0 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
import javax.swing.*;
import java.awt.*;
/**
* La classe <code>AvalamWindow</code>
*
* Fenêtre principale (interface graphique) du jeu Avalam.
* Elle contient :
* - le plateau (BoardView)
* - laffichage du score (ScoreView)
* - laffichage du joueur courant (TurnView)
*
* 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 (préparé)
*
* @version 1.0
* Date :
* Licence :
*/
public class AvalamWindow extends JFrame {
//Attributs
/** Moteur du jeu (état + règles). */
private AvalamBoard board;
/** Vue affichant le score. */
private ScoreView scoreView;
/** Vue affichant le joueur courant. */
private TurnView turnView;
/** 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 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
Tower[][] initialGrid = BoardLoader.loadFromFile("fr/iut_fbleau/Res/Plateau.txt");
// Initialisation du moteur (PLAYER1 commence)
board = new AvalamBoard(initialGrid);
// Panneau supérieur (score + tour)
JPanel topPanel = new JPanel(new GridLayout(2, 1));
topPanel.setBackground(new java.awt.Color(200, 200, 200));
scoreView = new ScoreView(
computeScore(Color.YELLOW),
computeScore(Color.RED)
);
turnView = new TurnView(turnMessage());
topPanel.add(scoreView);
topPanel.add(turnView);
add(topPanel, BorderLayout.NORTH);
// Plateau
boardView = new BoardView(board, this::onBoardUpdated);
add(boardView, BorderLayout.CENTER);
pack();
setResizable(false);
setLocationRelativeTo(null);
setVisible(true);
// Si un jour le bot doit commencer, on peut déclencher ici.
maybePlayBotTurn();
}
//Méthodes
/**
* Appelée après chaque coup (humain ou bot).
* Met à jour score, tour, et affiche la fin de partie.
*/
public void onBoardUpdated() {
scoreView.updateScores(
computeScore(Color.YELLOW),
computeScore(Color.RED)
);
turnView.setTurn(turnMessage());
if (board.isGameOver()) {
Result res = board.getResult();
String msg;
switch (res) {
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(
this,
msg,
"Partie terminée",
JOptionPane.INFORMATION_MESSAGE
);
return;
}
// Si on est contre un bot et que cest son tour, on déclenche son animation.
maybePlayBotTurn();
}
/**
* 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 dun 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
*/
private int computeScore(Color c) {
int score = 0;
for (int r = 0; r < AvalamBoard.SIZE; r++) {
for (int col = 0; col < AvalamBoard.SIZE; col++) {
Tower t = board.getTowerAt(r, col);
if (t != null && t.getColor() == c) {
score++;
}
}
}
return score;
}
/**
* Retourne le message affiché pour le joueur courant.
*
* @return message du tour
*/
private String turnMessage() {
return "Tour du joueur : " +
(board.getCurrentPlayer() == Player.PLAYER1 ? "Jaune" : "Rouge");
}
//Affichage
}