Fix des scores

This commit is contained in:
Vincent 2024-10-27 23:07:11 +01:00
parent 68e99b9cfc
commit b68751ce2c
13 changed files with 177 additions and 345 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -4,8 +4,10 @@ import view.HexagonTile;
import java.awt.Point; import java.awt.Point;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.ArrayList;
import javax.swing.JPanel; import javax.swing.JPanel;
/** /**
@ -46,7 +48,6 @@ public class GameContext {
return availablePositions; return availablePositions;
} }
/** /**
* Récupère l'offset actuel de la vue. * Récupère l'offset actuel de la vue.
* *
@ -66,7 +67,6 @@ public class GameContext {
offset.translate(deltaX, deltaY); offset.translate(deltaX, deltaY);
} }
/** /**
* Recalcule et applique la position de chaque tuile hexagonale en fonction de l'offset de vue. * Recalcule et applique la position de chaque tuile hexagonale en fonction de l'offset de vue.
* Actualise l'interface graphique en ajustant les positions des tuiles et en repeignant le panneau. * Actualise l'interface graphique en ajustant les positions des tuiles et en repeignant le panneau.
@ -78,23 +78,45 @@ public class GameContext {
Point position = entry.getKey(); Point position = entry.getKey();
HexagonTile tile = entry.getValue(); HexagonTile tile = entry.getValue();
// Calcule la position avec l'offset int xOffset = position.x * (int) (50 * 3 / 2);
int xOffset = position.x * (int) (50 * 3 / 2); // Ajuste la distance horizontale int yOffset = position.y * (int) (Math.sqrt(3) * 50);
int yOffset = position.y * (int) (Math.sqrt(3) * 50); // Ajuste la distance verticale
// Si la colonne est impaire, décale la tuile d'une demi-hauteur d'hexagone
if (position.x % 2 != 0) { if (position.x % 2 != 0) {
yOffset += (int) (Math.sqrt(3) * 50 / 2); yOffset += (int) (Math.sqrt(3) * 50 / 2);
} }
// Applique l'offset de vue
xOffset += offset.x; xOffset += offset.x;
yOffset += offset.y; yOffset += offset.y;
// Met à jour la position de l'hexagone
tile.setBounds(xOffset, yOffset, 50, 50); tile.setBounds(xOffset, yOffset, 50, 50);
} }
gridPanel.revalidate(); gridPanel.revalidate();
gridPanel.repaint(); gridPanel.repaint();
} }
/**
* Retourne les positions adjacentes à une position donnée dans la grille hexagonale.
*
* @param position La position centrale pour laquelle obtenir les positions adjacentes.
* @return Une liste de positions adjacentes à la position spécifiée.
*/
public List<Point> getAdjacentPositions(Point position) {
List<Point> adjacentPositions = new ArrayList<>();
if (position.x % 2 == 0) {
adjacentPositions.add(new Point(position.x + 1, position.y));
adjacentPositions.add(new Point(position.x - 1, position.y));
adjacentPositions.add(new Point(position.x, position.y + 1));
adjacentPositions.add(new Point(position.x, position.y - 1));
adjacentPositions.add(new Point(position.x + 1, position.y - 1));
adjacentPositions.add(new Point(position.x - 1, position.y - 1));
} else {
adjacentPositions.add(new Point(position.x + 1, position.y));
adjacentPositions.add(new Point(position.x - 1, position.y));
adjacentPositions.add(new Point(position.x, position.y + 1));
adjacentPositions.add(new Point(position.x, position.y - 1));
adjacentPositions.add(new Point(position.x + 1, position.y + 1));
adjacentPositions.add(new Point(position.x - 1, position.y + 1));
}
return adjacentPositions;
}
} }

@ -11,11 +11,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
/**
* La classe GameController gère le flux de jeu et la logique principale, y compris le placement de tuiles,
* la mise à jour de la grille et le calcul du score. Elle prend en charge l'initialisation du jeu,
* la génération de tuiles et la gestion de la fin de la partie.
*/
public class GameController implements TilePlacer { public class GameController implements TilePlacer {
private Map<Point, HexagonTile> hexagonMap; private Map<Point, HexagonTile> hexagonMap;
private Set<Point> availablePositions; private Set<Point> availablePositions;
@ -32,7 +27,6 @@ public class GameController implements TilePlacer {
private int seriesId; private int seriesId;
private GameEndListener gameEndListener; private GameEndListener gameEndListener;
/** /**
* Constructeur de la classe GameController. * Constructeur de la classe GameController.
* Initialise les composants de la partie, y compris le contexte de jeu, la série de tuiles, * Initialise les composants de la partie, y compris le contexte de jeu, la série de tuiles,
@ -61,24 +55,12 @@ public class GameController implements TilePlacer {
updatePreview(); updatePreview();
} }
/**
* Charge une série de tuiles spécifiée par l'identifiant de série.
*
* @param idSeries l'identifiant de la série à charger
*/
public void loadSeries(int idSeries) { public void loadSeries(int idSeries) {
currentTiles = dbManager.getTilesBySeries(idSeries); currentTiles = dbManager.getTilesBySeries(idSeries);
tileIndex = 0; tileIndex = 0;
System.out.println("Série " + idSeries + " chargée avec " + currentTiles.size() + " tuiles."); System.out.println("Série " + idSeries + " chargée avec " + currentTiles.size() + " tuiles.");
} }
/**
* Place une tuile à la position spécifiée dans la grille, si la position est disponible.
*
* @param position la position de la grille pour placer la tuile
*/
@Override @Override
public void placeTile(Point position) { public void placeTile(Point position) {
if (availablePositions.contains(position)) { if (availablePositions.contains(position)) {
@ -88,7 +70,6 @@ public class GameController implements TilePlacer {
return; return;
} }
// Placer la tuile actuelle
hexTile.setTile(nextTile); hexTile.setTile(nextTile);
gridPanel.revalidate(); gridPanel.revalidate();
gridPanel.repaint(); gridPanel.repaint();
@ -103,40 +84,29 @@ public class GameController implements TilePlacer {
} }
gameContext.repaintGrid(gridPanel); gameContext.repaintGrid(gridPanel);
// Calculer les scores et mettre à jour la visualisation des poches
scoreGameContext.calculateScore(); scoreGameContext.calculateScore();
// Incrémenter le nombre de tuiles placées et vérifier si la limite est atteinte
placedTileCount++; placedTileCount++;
if (placedTileCount > 48) { if (placedTileCount > 48) {
endGame(); // Terminer la partie si on a atteint la 50ᵉ tuile pile endGame();
return; // Arrêter ici pour éviter de générer une tuile vide return;
} }
// Générer la prochaine tuile si la partie n'est pas terminée
generateNextTile(); generateNextTile();
} }
} }
/**
* Termine la partie, enregistre le score final et notifie le listener de fin de partie.
*/
private void endGame() { private void endGame() {
int finalScore = scoreGameContext.getScore(); int finalScore = scoreGameContext.getScore();
// Enregistrer le score dans la base de données
new SendScore().insertscore(seriesId, finalScore); new SendScore().insertscore(seriesId, finalScore);
// Notifiez le listener de la fin de la partie
if (gameEndListener != null) { if (gameEndListener != null) {
gameEndListener.onGameEnd(finalScore); gameEndListener.onGameEnd(finalScore);
} }
} }
/**
* Initialise le jeu en plaçant une tuile initiale au centre de la grille et en configurant la vue.
*
* @param cameraController le contrôleur de caméra pour gérer les déplacements de vue
*/
public void initializeGame(CameraController cameraController) { public void initializeGame(CameraController cameraController) {
generateNextTile(); generateNextTile();
Tile initialTile = getNextTile(); Tile initialTile = getNextTile();
@ -153,13 +123,6 @@ public class GameController implements TilePlacer {
generateNextTile(); generateNextTile();
} }
/**
* Place la tuile initiale dans la grille et initialise les positions adjacentes comme disponibles.
*
* @param position la position centrale pour la tuile initiale
* @param cameraController le contrôleur de caméra pour appliquer l'offset de vue
* @param tile la tuile initiale à placer
*/
public void placeInitialTile(Point position, CameraController cameraController, Tile tile) { public void placeInitialTile(Point position, CameraController cameraController, Tile tile) {
if (tile == null) { if (tile == null) {
System.out.println("Erreur : tuile initiale non définie."); System.out.println("Erreur : tuile initiale non définie.");
@ -177,15 +140,6 @@ public class GameController implements TilePlacer {
} }
} }
/**
* Ajoute une nouvelle tuile hexagonale à la grille à la position spécifiée.
*
* @param position la position de la tuile dans la grille
* @param panel le panneau contenant la grille
* @param hexSize la taille de l'hexagone
* @param cameraController le contrôleur de caméra pour ajuster la position
* @param tile la tuile à placer ou null pour un espace réservé
*/
public void addHexagonTile(Point position, JPanel panel, int hexSize, CameraController cameraController, Tile tile) { public void addHexagonTile(Point position, JPanel panel, int hexSize, CameraController cameraController, Tile tile) {
if (position == null || panel == null) { if (position == null || panel == null) {
System.out.println("Erreur : position ou panel est null"); System.out.println("Erreur : position ou panel est null");
@ -220,9 +174,6 @@ public class GameController implements TilePlacer {
panel.repaint(); panel.repaint();
} }
/**
* Génère la prochaine tuile de la série et met à jour l'aperçu.
*/
public void generateNextTile() { public void generateNextTile() {
if (tileIndex < currentTiles.size()) { if (tileIndex < currentTiles.size()) {
nextTile = currentTiles.get(tileIndex++); nextTile = currentTiles.get(tileIndex++);
@ -233,9 +184,6 @@ public class GameController implements TilePlacer {
} }
} }
/**
* Met à jour l'aperçu de la tuile suivante.
*/
private void updatePreview() { private void updatePreview() {
if (nextTilePreview != null) { if (nextTilePreview != null) {
if (nextTile != null) { if (nextTile != null) {
@ -247,21 +195,10 @@ public class GameController implements TilePlacer {
} }
} }
/**
* Retourne la prochaine tuile à placer.
*
* @return la prochaine tuile ou null si aucune tuile n'est disponible
*/
public Tile getNextTile() { public Tile getNextTile() {
return nextTile; return nextTile;
} }
/**
* Retourne les positions adjacentes à une position donnée dans la grille.
*
* @param position la position centrale
* @return un tableau de positions adjacentes
*/
private Point[] getAdjacentPositions(Point position) { private Point[] getAdjacentPositions(Point position) {
if (position.x % 2 == 0) { if (position.x % 2 == 0) {
return new Point[]{ return new Point[]{

@ -7,47 +7,43 @@ import view.HexagonTile;
import javax.swing.*; import javax.swing.*;
import java.awt.Point; import java.awt.Point;
import java.util.HashMap; import java.util.*;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/** /**
* La classe ScoreGameContext gère le calcul et l'affichage du score dans le jeu. * La classe ScoreGameContext gère le calcul et l'affichage du score dans le jeu.
* Elle crée des "Pockets" basées sur les tuiles placées et leurs types de terrain, * Elle crée des "Pockets" basées sur les tuiles placées et leurs types de terrain,
* et calcule le score total en fonction de la taille de chaque Pocket. * et calcule le score total en fonction de la taille de chaque Pocket.
*/ */
public class ScoreGameContext { public class ScoreGameContext {
private GameContext gameContext; private GameContext gameContext;
private int score; private int score;
private JLabel scoreLabel; private JLabel scoreLabel;
private Map<Point, Pocket> pocketMap; // Map des Pockets pour chaque tuile private Map<Point, Pocket> pocketMap; // Map des Pockets pour chaque position de tuile
private Set<Pocket> pockets; // Ensemble de toutes les Pockets private Map<TerrainType, List<Pocket>> pocketsByTerrainType; // Ensemble de toutes les poches par type de terrain
/** /**
* Constructeur pour ScoreGameContext. * Constructeur pour ScoreGameContext.
* *
* @param gameContext le contexte du jeu qui contient l'état de la grille * @param gameContext le contexte du jeu qui contient l'état de la grille
* @param scoreLabel le JLabel pour afficher le score * @param scoreLabel le JLabel pour afficher le score
*/ */
public ScoreGameContext(GameContext gameContext, JLabel scoreLabel) { public ScoreGameContext(GameContext gameContext, JLabel scoreLabel) {
this.gameContext = gameContext; this.gameContext = gameContext;
this.scoreLabel = scoreLabel; this.scoreLabel = scoreLabel;
this.pocketMap = new HashMap<>(); this.pocketMap = new HashMap<>();
this.pockets = new HashSet<>(); this.pocketsByTerrainType = new HashMap<>();
this.score = 0; this.score = 0;
} }
/** /**
* Méthode principale pour recalculer le score en reconstruisant toutes les Pockets. * Méthode principale pour recalculer le score en reconstruisant toutes les poches.
* Elle parcourt les tuiles dans la grille et crée des Pockets par type de terrain. * Elle parcourt les tuiles dans la grille et crée des poches par type de terrain.
*/ */
public void calculateScore() { public void calculateScore() {
score = 0; score = 0;
pockets.clear(); pocketsByTerrainType.clear();
pocketMap.clear();
// Parcourt chaque tuile dans la grille pour créer des Pockets par type de terrain // Parcourt chaque tuile dans la grille pour créer des poches par type de terrain
for (Map.Entry<Point, HexagonTile> entry : gameContext.getHexagonMap().entrySet()) { for (Map.Entry<Point, HexagonTile> entry : gameContext.getHexagonMap().entrySet()) {
Point position = entry.getKey(); Point position = entry.getKey();
HexagonTile hexTile = entry.getValue(); HexagonTile hexTile = entry.getValue();
@ -55,122 +51,69 @@ public class ScoreGameContext {
if (hexTile.isFilled()) { if (hexTile.isFilled()) {
Tile tile = hexTile.getTile(); Tile tile = hexTile.getTile();
// Crée ou fusionne une Pocket pour chaque type de terrain de la tuile // Crée des poches pour chaque type de terrain de la tuile
for (int segment = 0; segment < 6; segment++) { addTileToPockets(tile.getTerrain(0), position); // Premier terrain
TerrainType terrainType = tile.getTerrainForSegment(segment); if (tile.hasTwoTerrains()) { // Deuxième terrain si disponible
if (terrainType != null) { addTileToPockets(tile.getTerrain(1), position);
Pocket pocket = findOrCreatePocket(position, segment, terrainType);
pocketMap.put(position, pocket);
}
} }
} }
} }
// Calcule le score total en additionnant le score de chaque Pocket // Calcule le score total en additionnant le score de chaque poche
System.out.println("Pockets and their sizes:"); System.out.println("Poches et leurs tailles:");
for (Pocket pocket : pockets) { for (List<Pocket> pockets : pocketsByTerrainType.values()) {
System.out.println("Pocket with terrain " + pocket.getTerrainType() + " has size " + pocket.getSize()); for (Pocket pocket : pockets) {
score += pocket.calculateScore(); int pocketSize = pocket.getSize();
score += pocket.calculateScore();
System.out.println("Poche de taille " + pocketSize + " ajoutant " + pocket.calculateScore() + " points au score.");
}
} }
updateScoreDisplay(); updateScoreDisplay();
} }
/** /**
* Recherche ou crée une Pocket pour un terrain spécifique dans une tuile. * Ajoute une tuile à une poche de terrains en regroupant les tuiles adjacentes.
* Si des poches existent autour, fusionne ces poches.
* *
* @param position la position de la tuile * @param terrainType Le type de terrain de la tuile.
* @param segment le segment de la tuile * @param position La position de la tuile.
* @param terrainType le type de terrain de la tuile
* @return la Pocket correspondante, soit une Pocket existante fusionnée, soit une nouvelle Pocket
*/ */
private Pocket findOrCreatePocket(Point position, int segment, TerrainType terrainType) { private void addTileToPockets(TerrainType terrainType, Point position) {
Pocket newPocket = new Pocket(terrainType); List<Pocket> pockets = pocketsByTerrainType.computeIfAbsent(terrainType, k -> new ArrayList<>());
newPocket.addTile(position); Pocket foundPocket = null;
List<Pocket> pocketsToMerge = new ArrayList<>();
// Vérifie les voisins pour fusionner les Pockets si les segments se touchent for (Pocket pocket : pockets) {
for (int adjSegment = 0; adjSegment < 6; adjSegment++) { for (Point adj : gameContext.getAdjacentPositions(position)) {
Point neighborPos = getAdjacentPositionForSegment(position, adjSegment); if (pocket.containsTile(adj)) {
Pocket neighborPocket = pocketMap.get(neighborPos); if (foundPocket == null) {
foundPocket = pocket;
if (neighborPocket != null && neighborPocket.getTerrainType() == terrainType) { foundPocket.addTile(position);
// Vérifie si les segments de terrain se touchent avant de fusionner les Pockets } else {
if (areSegmentsConnected(position, neighborPos, segment, adjSegment, terrainType)) { foundPocket.merge(pocket);
System.out.println("Merging pocket at " + position + " with pocket at " + neighborPos + " for terrain " + terrainType); pocketsToMerge.add(pocket);
neighborPocket.merge(newPocket); }
pockets.remove(newPocket); // Supprime la Pocket fusionnée break;
return neighborPocket; // Retourne la Pocket fusionnée
} }
} }
} }
System.out.println("New pocket created at " + position + " for terrain " + terrainType); if (foundPocket == null) {
pockets.add(newPocket); // Ajoute la nouvelle Pocket si aucune fusion n'a eu lieu Pocket newPocket = new Pocket(gameContext, terrainType);
return newPocket; newPocket.addTile(position);
} pockets.add(newPocket);
pocketMap.put(position, newPocket);
/**
* Vérifie si les segments de deux tuiles se touchent et partagent le même type de terrain.
*
* @param position1 la première position de tuile
* @param position2 la seconde position de tuile
* @param segment1 le segment de la première tuile
* @param segment2 le segment de la seconde tuile
* @param terrainType le type de terrain à vérifier
* @return true si les segments sont connectés, false sinon
*/
private boolean areSegmentsConnected(Point position1, Point position2, int segment1, int segment2, TerrainType terrainType) {
Tile tile1 = gameContext.getHexagonMap().get(position1).getTile();
Tile tile2 = gameContext.getHexagonMap().get(position2).getTile();
if (tile1 == null || tile2 == null) return false;
TerrainType terrainSegment1 = tile1.getTerrainForSegment(segment1);
TerrainType terrainSegment2 = tile2.getTerrainForSegment(segment2);
boolean connected = terrainSegment1 == terrainType && terrainSegment2 == terrainType;
if (connected) {
System.out.println("Segments connected between " + position1 + " and " + position2 + " for terrain " + terrainType);
} }
return connected;
}
/** pockets.removeAll(pocketsToMerge);
* Obtient la position adjacente pour un segment spécifique (0 à 5).
*
* @param position la position de la tuile
* @param segment le segment pour lequel on cherche la position adjacente
* @return la position adjacente
*/
private Point getAdjacentPositionForSegment(Point position, int segment) {
if (position.x % 2 == 0) {
switch (segment) {
case 0: return new Point(position.x + 1, position.y);
case 1: return new Point(position.x + 1, position.y - 1);
case 2: return new Point(position.x, position.y - 1);
case 3: return new Point(position.x - 1, position.y - 1);
case 4: return new Point(position.x - 1, position.y);
case 5: return new Point(position.x, position.y + 1);
default: return position;
}
} else {
switch (segment) {
case 0: return new Point(position.x + 1, position.y);
case 1: return new Point(position.x + 1, position.y + 1);
case 2: return new Point(position.x, position.y + 1);
case 3: return new Point(position.x - 1, position.y + 1);
case 4: return new Point(position.x - 1, position.y);
case 5: return new Point(position.x, position.y - 1);
default: return position;
}
}
} }
/** /**
* Met à jour l'affichage du score dans GameView. * Met à jour l'affichage du score dans GameView.
*/ */
private void updateScoreDisplay() { private void updateScoreDisplay() {
System.out.println("Updated Score: " + score); // Débogage du score System.out.println("Score mis à jour : " + score);
scoreLabel.setText("Score: " + score); scoreLabel.setText("Score: " + score);
} }

@ -1,82 +1,95 @@
// src/main/java/model/Pocket.java
package model; package model;
import controller.GameContext;
import view.HexagonTile;
import java.awt.Color;
import java.awt.Point; import java.awt.Point;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
/**
* La classe <code>Pocket</code> représente un groupe de tuiles adjacentes
* d'un même type de terrain dans le jeu.
*/
public class Pocket { public class Pocket {
private TerrainType terrainType; // Type de terrain de cette Pocket private GameContext gameContext;
private Set<Point> tiles; // Ensemble des positions des tuiles de la Pocket private Set<Point> tilePositions; // Ensemble des positions des tuiles dans cette poche
private TerrainType terrainType; // Type de terrain de cette poche
/** /**
* Constructeur de la classe <code>Pocket</code>. * Constructeur de la classe Pocket.
* *
* @param terrainType Le type de terrain associé à cette Pocket. * @param gameContext le contexte de jeu pour accéder aux tuiles
* @param terrainType le type de terrain de cette poche
*/ */
public Pocket(TerrainType terrainType) { public Pocket(GameContext gameContext, TerrainType terrainType) {
this.gameContext = gameContext;
this.terrainType = terrainType; this.terrainType = terrainType;
this.tiles = new HashSet<>(); this.tilePositions = new HashSet<>();
} }
/** /**
* Récupère le type de terrain de cette Pocket. * Ajoute une tuile à la poche.
* *
* @return Le type de terrain de cette Pocket. * @param position la position de la tuile dans la grille
*/
public void addTile(Point position) {
tilePositions.add(position);
}
/**
* Vérifie si la poche contient une tuile à la position donnée.
*
* @param position la position de la tuile à vérifier
* @return true si la tuile est dans la poche, false sinon
*/
public boolean containsTile(Point position) {
return tilePositions.contains(position);
}
/**
* Récupère le type de terrain de cette poche.
*
* @return le type de terrain de la poche
*/ */
public TerrainType getTerrainType() { public TerrainType getTerrainType() {
return terrainType; return terrainType;
} }
/** /**
* Obtient la taille de cette Pocket, c'est-à-dire le nombre de tuiles. * Calcule la taille de la poche en fonction du nombre de tuiles qu'elle contient.
* *
* @return La taille de la Pocket. * @return la taille de la poche
*/ */
public int getSize() { public int getSize() {
return tiles.size(); return tilePositions.size();
} }
/** /**
* Ajoute une tuile à cette Pocket à une position donnée. * Calcule le score de la poche en fonction de sa taille.
* La règle est que le score est la taille de la poche au carré.
* *
* @param position La position de la tuile à ajouter. * @return le score de la poche
*/
public void addTile(Point position) {
tiles.add(position);
}
/**
* Vérifie si une tuile à une position donnée est présente dans cette Pocket.
*
* @param position La position de la tuile à vérifier.
* @return <code>true</code> si la tuile est présente, sinon <code>false</code>.
*/
public boolean containsTile(Point position) {
return tiles.contains(position);
}
/**
* Fusionne cette Pocket avec une autre Pocket si elles partagent le même type de terrain.
*
* @param other La Pocket à fusionner.
*/
public void merge(Pocket other) {
if (this.terrainType == other.terrainType) {
this.tiles.addAll(other.tiles);
}
}
/**
* Calcule le score de cette Pocket basé sur la taille au carré.
*
* @return Le score de la Pocket.
*/ */
public int calculateScore() { public int calculateScore() {
return getSize() * getSize(); // La taille au carré donne le score return (int) Math.pow(getSize(), 2);
}
/**
* Fusionne cette poche avec une autre poche en ajoutant toutes ses tuiles.
*
* @param otherPocket la poche à fusionner avec celle-ci
*/
public void merge(Pocket otherPocket) {
tilePositions.addAll(otherPocket.tilePositions);
}
/**
* Applique une couleur de contraste pour visualiser cette poche sur l'interface.
*/
public void applyContrastColor() {
Color contrastColor = new Color(255, 255, 255, 128); // Couleur semi-transparente pour visualiser
for (Point position : tilePositions) {
HexagonTile tile = gameContext.getHexagonMap().get(position);
if (tile != null) {
tile.setContrastColor(contrastColor);
}
}
} }
} }

@ -1,50 +1,25 @@
// src/main/java/model/Tile.java
package model; package model;
/**
* La classe <code>Tile</code> représente une tuile dans le jeu, qui peut contenir un ou deux types de terrains.
* Chaque tuile a un identifiant unique, un tableau de types de terrains, et gère sa rotation.
*/
public class Tile { public class Tile {
private int id; // ID de la tuile private int id;
private TerrainType[] terrains; // Tableau contenant deux types de terrains (ex. MER, FORET) private TerrainType[] terrains;
private int segmentsForTerrain1; // Nombre de segments pour le premier terrain private int segmentsForTerrain1;
private int rotation; // Rotation de la tuile (en multiple de 60 degrés) private int rotation;
/**
* Constructeur pour créer une nouvelle tuile avec deux types de terrains.
*
* @param id L'identifiant de la tuile.
* @param terrain1 Le premier type de terrain.
* @param terrain2 Le deuxième type de terrain.
* @param segmentsForTerrain1 Le nombre de segments pour le premier terrain.
*/
public Tile(int id, TerrainType terrain1, TerrainType terrain2, int segmentsForTerrain1) { public Tile(int id, TerrainType terrain1, TerrainType terrain2, int segmentsForTerrain1) {
this.id = id; this.id = id;
this.terrains = new TerrainType[]{terrain1, terrain2}; this.terrains = new TerrainType[]{terrain1, terrain2};
this.segmentsForTerrain1 = segmentsForTerrain1; this.segmentsForTerrain1 = segmentsForTerrain1;
this.rotation = 0; // Initialisation de la rotation à 0 this.rotation = 0;
} }
/**
* Renvoie le terrain pour l'index donné (0 ou 1).
*
* @param index L'index du terrain à récupérer.
* @return Le type de terrain à l'index spécifié, ou null si l'index est invalide.
*/
public TerrainType getTerrain(int index) { public TerrainType getTerrain(int index) {
if (index >= 0 && index < terrains.length) { if (index >= 0 && index < terrains.length) {
return terrains[index]; return terrains[index];
} }
return null; // Retourne null si l'index est invalide return null;
} }
/**
* Méthode pour obtenir le terrain associé à un segment spécifique (prend en compte la rotation).
*
* @param segmentIndex L'index du segment.
* @return Le type de terrain associé au segment spécifié.
*/
public TerrainType getTerrainForSegment(int segmentIndex) { public TerrainType getTerrainForSegment(int segmentIndex) {
int adjustedIndex = (segmentIndex - rotation + 6) % 6; int adjustedIndex = (segmentIndex - rotation + 6) % 6;
if (adjustedIndex < segmentsForTerrain1) { if (adjustedIndex < segmentsForTerrain1) {
@ -54,35 +29,28 @@ public class Tile {
} }
} }
/**
* Fait tourner la tuile dans le sens horaire.
*/
public void rotateClockwise() { public void rotateClockwise() {
rotation = (rotation + 1) % 6; rotation = (rotation + 1) % 6;
} }
/**
* Fait tourner la tuile dans le sens antihoraire.
*/
public void rotateCounterClockwise() { public void rotateCounterClockwise() {
rotation = (rotation + 5) % 6; // Tourner dans le sens inverse rotation = (rotation + 5) % 6;
} }
/**
* Renvoie la rotation actuelle de la tuile.
*
* @return La rotation de la tuile en multiples de 60 degrés.
*/
public int getRotation() { public int getRotation() {
return rotation; return rotation;
} }
/**
* Renvoie l'identifiant de la tuile.
*
* @return L'identifiant de la tuile.
*/
public int getId() { public int getId() {
return id; return id;
} }
/**
* Vérifie si la tuile a deux terrains différents.
*
* @return true si la tuile a deux terrains, sinon false.
*/
public boolean hasTwoTerrains() {
return terrains[1] != null;
}
} }

@ -7,78 +7,44 @@ import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.geom.Path2D; import java.awt.geom.Path2D;
/**
* La classe <code>HexagonTile</code> représente une tuile hexagonale dans le jeu.
* Elle gère l'affichage d'une tuile avec ses segments de terrain et
* indique si la tuile est un placeholder.
*/
public class HexagonTile extends JPanel { public class HexagonTile extends JPanel {
/** La tuile associée à cet hexagone. */
private Tile tile; private Tile tile;
/** La position de l'hexagone sur la grille. */
private Point position; private Point position;
/** Indicateur si l'hexagone est un placeholder. */
private boolean isPlaceholder; private boolean isPlaceholder;
private Color contrastColor; // Nouvelle couleur pour le contraste visuel des poches
/**
* Constructeur de la classe <code>HexagonTile</code>.
*
* @param position La position de l'hexagone sur la grille.
* @param isPlaceholder Indique si cet hexagone est un placeholder.
*/
public HexagonTile(Point position, boolean isPlaceholder) { public HexagonTile(Point position, boolean isPlaceholder) {
this.position = position; this.position = position;
this.isPlaceholder = isPlaceholder; this.isPlaceholder = isPlaceholder;
this.tile = null; this.tile = null;
this.contrastColor = null; // Par défaut, pas de contraste
setPreferredSize(new Dimension(100, 100)); setPreferredSize(new Dimension(100, 100));
} }
/**
* Récupère la position de l'hexagone.
*
* @return La position de l'hexagone.
*/
public Point getPosition() { public Point getPosition() {
return position; return position;
} }
/**
* Définit la tuile associée à cet hexagone.
*
* @param tile La tuile à associer.
*/
public void setTile(Tile tile) { public void setTile(Tile tile) {
this.tile = tile; this.tile = tile;
this.isPlaceholder = false; // Une fois la tuile posée, ce n'est plus un placeholder this.isPlaceholder = false;
repaint(); repaint();
} }
/**
* Récupère la tuile associée à cet hexagone.
*
* @return La tuile associée.
*/
public Tile getTile() { public Tile getTile() {
return tile; return tile;
} }
/**
* Vérifie si l'hexagone est rempli avec une tuile.
*
* @return <code>true</code> si l'hexagone contient une tuile, sinon <code>false</code>.
*/
public boolean isFilled() { public boolean isFilled() {
return this.tile != null; return this.tile != null;
} }
/** // Nouvelle méthode pour définir la couleur de contraste
* Méthode de peinture du composant. public void setContrastColor(Color color) {
* Dessine l'hexagone et ses segments de terrain, ou un placeholder si aucun terrain n'est présent. this.contrastColor = color;
* repaint();
* @param g Le contexte graphique dans lequel dessiner. }
*/
@Override @Override
protected void paintComponent(Graphics g) { protected void paintComponent(Graphics g) {
super.paintComponent(g); super.paintComponent(g);
@ -86,7 +52,7 @@ public class HexagonTile extends JPanel {
int centerX = getWidth() / 2; int centerX = getWidth() / 2;
int centerY = getHeight() / 2; int centerY = getHeight() / 2;
int largeRadius = isPlaceholder ? 40 : 50; // Réduction de taille pour les placeholders int largeRadius = isPlaceholder ? 40 : 50;
Shape largeHexagon = createHexagon(centerX, centerY, largeRadius); Shape largeHexagon = createHexagon(centerX, centerY, largeRadius);
g2d.setClip(largeHexagon); g2d.setClip(largeHexagon);
@ -102,33 +68,22 @@ public class HexagonTile extends JPanel {
g2d.setColor(Color.BLACK); g2d.setColor(Color.BLACK);
g2d.setStroke(new BasicStroke(3)); g2d.setStroke(new BasicStroke(3));
g2d.draw(largeHexagon); g2d.draw(largeHexagon);
// Appliquer la couleur contrastée si elle est définie
if (contrastColor != null) {
g2d.setColor(new Color(contrastColor.getRGB() & 0xFFFFFF | 0x66000000, true));
g2d.fill(largeHexagon);
}
} }
/**
* Dessine les segments de terrain associés à la tuile.
*
* @param g2d Le contexte graphique dans lequel dessiner.
* @param centerX La coordonnée X du centre de l'hexagone.
* @param centerY La coordonnée Y du centre de l'hexagone.
* @param radius Le rayon de l'hexagone.
*/
private void drawTerrainSegments(Graphics2D g2d, int centerX, int centerY, int radius) { private void drawTerrainSegments(Graphics2D g2d, int centerX, int centerY, int radius) {
// Parcourt les segments de 0 à 5 pour dessiner chaque segment en fonction du terrain associé
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
TerrainType terrain = tile.getTerrainForSegment(i); // Récupère le terrain du segment, en prenant en compte la rotation TerrainType terrain = tile.getTerrainForSegment(i);
g2d.setColor(getTerrainColor(terrain)); g2d.setColor(getTerrainColor(terrain));
g2d.fillArc(centerX - radius, centerY - radius, 2 * radius, 2 * radius, 60 * i, 60); g2d.fillArc(centerX - radius, centerY - radius, 2 * radius, 2 * radius, 60 * i, 60);
} }
} }
/**
* Crée un hexagone à partir des coordonnées centrales et du rayon.
*
* @param centerX La coordonnée X du centre de l'hexagone.
* @param centerY La coordonnée Y du centre de l'hexagone.
* @param radius Le rayon de l'hexagone.
* @return La forme hexagonale créée.
*/
private Shape createHexagon(int centerX, int centerY, int radius) { private Shape createHexagon(int centerX, int centerY, int radius) {
Path2D hexagon = new Path2D.Double(); Path2D hexagon = new Path2D.Double();
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
@ -145,12 +100,6 @@ public class HexagonTile extends JPanel {
return hexagon; return hexagon;
} }
/**
* Récupère la couleur associée à un type de terrain.
*
* @param terrain Le type de terrain à évaluer.
* @return La couleur correspondant au type de terrain.
*/
private Color getTerrainColor(TerrainType terrain) { private Color getTerrainColor(TerrainType terrain) {
if (terrain == null) { if (terrain == null) {
return Color.WHITE; return Color.WHITE;