package fr.iut_fbleau.Avalam.ui; import fr.iut_fbleau.Avalam.AvalamBoard; import fr.iut_fbleau.Avalam.AvalamPly; import fr.iut_fbleau.Avalam.Tower; import fr.iut_fbleau.GameAPI.AbstractPly; import fr.iut_fbleau.GameAPI.Player; import java.awt.Point; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Le contrôleur gère toute l'interaction entre l'utilisateur et le moteur Avalam. * * Son rôle : * - gérer la sélection d’une tour * - générer les coups légaux via l’API (iterator) * - valider un déplacement (isLegal) * - appliquer un coup (doPly) * - mettre à jour le plateau (via refresh demandé au BoardView) * * IMPORTANT : ce contrôleur n’affiche rien. Il envoie les infos à BoardView. */ public class InteractionController { private AvalamBoard board; /** Position sélectionnée (-1 si aucune) */ private int selectedRow = -1; private int selectedCol = -1; /** Liste des coups légaux (en Point) autour de la sélection */ private List legalMoves = new ArrayList<>(); /** Référence à la vue pour la rafraîchir après déplacements */ private BoardView view; public InteractionController(AvalamBoard board, BoardView view) { this.board = board; this.view = view; } /** Retourne les cases jouables (pour HighlightLayer). */ public List getLegalMoves() { return legalMoves; } /** * Appelé lorsqu’un pion est cliqué dans BoardView. * Gère : * - sélection d’une tour * - désélection * - tentative de déplacement (si clique sur un highlight) */ public void onPieceClicked(int r, int c) { // Si on clique la même case ⇒ désélection if (r == selectedRow && c == selectedCol) { clearSelection(); view.refresh(); return; } // Si aucune sélection : on sélectionne un pion appartenant au joueur courant Tower t = board.getTowerAt(r, c); if (t != null && t.getColor().toPlayer() == board.getCurrentPlayer()) { selectTower(r, c); view.refresh(); return; } // Sinon : tentons de jouer un coup (déplacement) if (selectedRow != -1 && selectedCol != -1) { tryMove(r, c); } } /* ------------------------------------------------------------------------- * SÉLECTION D’UNE TOUR * ---------------------------------------------------------------------- */ private void selectTower(int r, int c) { selectedRow = r; selectedCol = c; computeLegalMoves(); } private void clearSelection() { selectedRow = -1; selectedCol = -1; legalMoves.clear(); } /** * Identifie les destinations possibles depuis la tour sélectionnée. * Utilise l’API officielle : board.iterator() */ private void computeLegalMoves() { legalMoves.clear(); Iterator it = board.iterator(); while (it.hasNext()) { AbstractPly p = it.next(); if (!(p instanceof AvalamPly)) continue; AvalamPly ap = (AvalamPly) p; // On ne garde que les coups dont la source correspond à la sélection if (ap.getXFrom() == selectedRow && ap.getYFrom() == selectedCol) { legalMoves.add(new Point(ap.getXTo(), ap.getYTo())); } } } /* ------------------------------------------------------------------------- * TENTATIVE DE DÉPLACEMENT * ---------------------------------------------------------------------- */ /** * Tente d’exécuter un déplacement vers (r,c) si c’est un coup légal. */ private void tryMove(int r, int c) { // Vérifier si (r,c) est une destination légale boolean isLegalDest = false; for (Point p : legalMoves) { if (p.x == r && p.y == c) { isLegalDest = true; break; } } if (!isLegalDest) { clearSelection(); // clic ailleurs = désélection view.refresh(); return; } // Construire le coup Player cur = board.getCurrentPlayer(); AvalamPly ply = new AvalamPly(cur, selectedRow, selectedCol, r, c); // Vérifier via l’API if (board.isLegal(ply)) { // Appliquer via l’API board.doPly(ply); // Réinitialiser la sélection clearSelection(); // Recalcul du score + joueur courant + fin de partie (handled in window) view.onBoardUpdated(); } else { // Coup impossible (rare, mais pour sécurité) clearSelection(); } view.refresh(); } }