11 Commits

Author SHA1 Message Date
023aa9d419 Mise à jour des diagrammes + SVG 2026-02-05 19:45:44 +01:00
2cf929e024 Merge pull request 'modification du makefile pour séparer la compilation du jeu et des test et automatiser l'installation des dépendance' (#27) from makefile_compilation_erreur into master
Reviewed-on: #27
2026-02-05 16:39:42 +01:00
felix-vi
ee374a9221 modification du makefile pour séparer la compilation du jeu et des test et automatiser l'installation des dépendance 2026-02-05 16:37:57 +01:00
1eddda2605 Merge pull request 'quitter_rejouer_score' (#25) from quitter_rejouer_score into master
Reviewed-on: #25
2026-02-05 16:26:20 +01:00
8bbe17ebd8 Merge pull request 'Test complet de la fonction isLegal() de AvalamBoard' (#24) from tests into master
Reviewed-on: #24
2026-02-05 16:16:53 +01:00
f43361a48f Ajout vérification correspondance du Joueur (Test Ok) 2026-02-05 16:06:03 +01:00
ad2f0c63cf Merge pull request 'mise en place du bot divin dans l'arène et modification de la javadoc' (#23) from Verification_BotDivin_Arene into master
Reviewed-on: #23
2026-02-05 16:05:22 +01:00
dea162182b Merge branch 'master' of https://grond.iut-fbleau.fr/dick/BUT3ProjetJeuGroupe into tests 2026-02-05 14:01:16 +01:00
c0cd120b1e Ajout de la commande de test au ReadMe + légères corrections de langue 2026-02-05 11:52:12 +01:00
fa578b86d2 Adaptation du test (Board copie la grille) (à tester) 2026-02-05 11:50:15 +01:00
14e5df4332 Test de isLegal (à debug) [wip] 2026-02-03 10:38:14 +01:00
10 changed files with 264 additions and 23 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 128 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -3,6 +3,28 @@ title: Avalam - Diagramme de classes (complet)
--- ---
classDiagram classDiagram
class ArenaGame{
+ArenaGame(IBoard board, AbstractGamePlayer bot1, AbstractGamePlayer bot2)
-createPlayerMap(AbstractGamePlayer bot1, AbstractGamePlayer bot2): EnumMap<Player, AbstractGamePlayer>
}
class ArenaWindow{
-resultsTable: JTable
-tableModel: DefaultTableModel
-results: List<string>
+ArenaWindows()
-createConfigPanel(): JPanel
-createResultsTable()
-showConfigDialog()
-runArena(String bot1Type, String bot2Type, int depth, int nbParties)
-createBot(String botType, Player player, int depth): AbstractGamePlayer
-getWinnerName(Result result, String bot1Type, String bot2Type): String
}
ArenaWindow *-- AvalamBoard
ArenaWindow *-- ArenaGame
class AvalamBoard{ class AvalamBoard{
+SIZE: int +SIZE: int
-MAX_HEIGHT: int -MAX_HEIGHT: int
@@ -42,8 +64,6 @@ classDiagram
+toString(): String +toString(): String
} }
class AvalamWindow{ class AvalamWindow{
-board : AvalamBoard -board : AvalamBoard
@@ -70,13 +90,18 @@ classDiagram
AvalamWindow *-- BoardView AvalamWindow *-- BoardView
AvalamWindow *-- ScoreView AvalamWindow *-- ScoreView
AvalamWindow *-- TurnView AvalamWindow *-- TurnView
AvalamWindow *-- EndGameDialog
AvalamWindow --> GameMode AvalamWindow --> GameMode
class BackgroundLayer{
-img: Image
+BackgroundLayer(String resourcePath)
#paintComponent(Graphics g): void
}
class BoardLoader{ class BoardLoader{
+loadFromFile(String resourcePath): Tower[][] +loadFromFile(String resourcePath): Tower[][]
} }
class BoardView{ class BoardView{
-board: AvalamBoard -board: AvalamBoard
@@ -105,14 +130,6 @@ classDiagram
BoardView *-- InteractionController BoardView *-- InteractionController
BoardView --> AvalamBoard BoardView --> AvalamBoard
class BackgroundLayer{
-img: Image
+BackgroundLayer(String resourcePath)
#paintComponent(Graphics g): void
}
class Color{ class Color{
-YELLOW(int r, int g, int b) -YELLOW(int r, int g, int b)
-RED(int r, int g, int b) -RED(int r, int g, int b)
@@ -122,11 +139,17 @@ classDiagram
+toPlayer(): fr.iut_fbleau.GameAPI.Player +toPlayer(): fr.iut_fbleau.GameAPI.Player
} }
class EndGameDialog{
+EndGameDialog(JFrame parent, Result result, int scoreJaune, int scoreRouge, GameMode mode, int depth, Runnable onReplay, Runnable onMenu, Runnable onQuit)
-modeToString(GameMode mode, int depth): String
}
class GameMode{ class GameMode{
PVP PVP
PVBOT PVBOT
PVALPHA PVALPHA
PVGOD PVGOD
ARENA
} }
class HighlightLayer{ class HighlightLayer{
@@ -165,6 +188,7 @@ classDiagram
Main ..> AvalamWindow Main ..> AvalamWindow
Main ..> GameMode Main ..> GameMode
Main ..> ArenaWindow
class PieceButton{ class PieceButton{
-color: java.awt.Color -color: java.awt.Color

View File

@@ -17,7 +17,16 @@ classDiagram
} }
class DivineBot{ class DivineBot{
-me: Player
-maxDepth: int
-rng: Random
+DivineBot(Player p, int maxDepth)
+giveYourMove(IBoard board): AbstractPly
-alphaBeta(IBoard board, int depth, int alpha, int beta): int
-terminalValue(IBoard board): int
-evaluate(IBoard board): int
-listMoves(IBoard board): List<AbstractPly>
} }
class IdiotBot{ class IdiotBot{

View File

@@ -1,3 +1,8 @@
# === Environnements ===
JUNIT_JAR = /usr/share/java/junit.jar
HAMCREST_JAR = /usr/share/java/hamcrest-core.jar
TEST_ENV = "bin:$(JUNIT_JAR):$(HAMCREST_JAR)"
# === Répertoires === # === Répertoires ===
SRC_DIR = fr SRC_DIR = fr
BIN_DIR = bin BIN_DIR = bin
@@ -6,18 +11,28 @@ BIN_DIR = bin
RES_SRC = fr/iut_fbleau/Res RES_SRC = fr/iut_fbleau/Res
RES_BIN = bin/fr/iut_fbleau/Res RES_BIN = bin/fr/iut_fbleau/Res
# === Recherche automatique des fichiers .java dans tous les sous-dossiers === # === Recherche automatique des fichiers .java ===
SOURCES := $(shell find $(SRC_DIR) -name "*.java") # SOURCES : uniquement le code de l'application (sans les fichiers de tests)
SOURCES := $(shell find $(SRC_DIR) -name "*.java" -not -path "$(SRC_DIR)/iut_fbleau/Tests/*")
# TEST_SOURCES : uniquement les fichiers de tests
TEST_SOURCES := $(shell find $(SRC_DIR)/iut_fbleau/Tests -name "*.java" 2>/dev/null)
# === Classe principale === # === Classe principale ===
MAIN_CLASS = fr.iut_fbleau.Avalam.Main MAIN_CLASS = fr.iut_fbleau.Avalam.Main
# === Classe de test ===
TEST_CLASS = fr.iut_fbleau.Tests.AvalamBoardTest
# === Commandes Java === # === Commandes Java ===
JC = javac JC = javac
# Compilation normale (application uniquement)
JCFLAGS = -d $(BIN_DIR) JCFLAGS = -d $(BIN_DIR)
# Compilation des tests (application + JUnit)
JCFLAGS_TESTS = -d $(BIN_DIR) -cp $(TEST_ENV)
JAVA = java JAVA = java
JAVAFLAGS = -cp $(BIN_DIR) JAVAFLAGS = -cp $(BIN_DIR)
JAVAFLAGS_TESTS = -cp $(TEST_ENV)
# === Règle par défaut === # === Règle par défaut ===
all: build all: build
@@ -31,6 +46,35 @@ compile:
@mkdir -p $(BIN_DIR) @mkdir -p $(BIN_DIR)
@$(JC) $(JCFLAGS) $(SOURCES) @$(JC) $(JCFLAGS) $(SOURCES)
compile_tests: compile
@echo "===> Compilation des tests..."
@mkdir -p $(BIN_DIR)
ifneq ($(TEST_SOURCES),)
@$(JC) $(JCFLAGS_TESTS) $(TEST_SOURCES)
else
@echo "Aucun fichier de test trouvé dans $(SRC_DIR)/iut_fbleau/Tests"
endif
# === Vérification / installation des dépendances de tests ===
check_test_deps:
@echo "===> Vérification des dépendances de tests (JUnit / Hamcrest)..."
@if [ ! -f "$(JUNIT_JAR)" ] || [ ! -f "$(HAMCREST_JAR)" ]; then \
echo " JUnit ou Hamcrest manquant, tentative d'installation (sudo requis)..."; \
if command -v sudo >/dev/null 2>&1; then \
sudo apt-get update && sudo apt-get install -y junit4 libhamcrest-java; \
else \
apt-get update && apt-get install -y junit4 libhamcrest-java; \
fi; \
if [ ! -f "$(JUNIT_JAR)" ] || [ ! -f "$(HAMCREST_JAR)" ]; then \
echo "✖ Impossible de trouver/installer $(JUNIT_JAR) ou $(HAMCREST_JAR). Vérifiez manuellement vos paquets JUnit/Hamcrest."; \
exit 1; \
else \
echo "✔ Dépendances de tests installées."; \
fi; \
else \
echo "✔ JUnit et Hamcrest trouvés."; \
fi
# === Copie des ressources (.txt) dans bin === # === Copie des ressources (.txt) dans bin ===
resources: resources:
@echo "===> Copie des ressources..." @echo "===> Copie des ressources..."
@@ -43,6 +87,12 @@ run:
@echo "===> Lancement du jeu Avalam..." @echo "===> Lancement du jeu Avalam..."
@$(JAVA) $(JAVAFLAGS) $(MAIN_CLASS) @$(JAVA) $(JAVAFLAGS) $(MAIN_CLASS)
# === Tests ===
test: check_test_deps compile_tests
@echo "===> Lancement des tests..."
@$(JAVA) $(JAVAFLAGS_TESTS) org.junit.runner.JUnitCore $(TEST_CLASS)
@echo "... Fin des tests."
# === Nettoyage === # === Nettoyage ===
clean: clean:
@echo "===> Suppression des fichiers compilés..." @echo "===> Suppression des fichiers compilés..."

View File

@@ -4,38 +4,63 @@
Date de création : 16/10/25 Date de création : 16/10/25
Le but est de mettre en oeuvre des jeux plus intéressants que le jeu de Nim, toujours en suivant l'API. Date de rendu : 06/02/26
Dans un second temps, on fera des bots le plus efficace possible (probablement un alpha beta avec cut-off plus fonction d'évaluation qui peut être faite à la main ou par MonteCarlo). Le but est de mettre en oeuvre un jeu plus intéressants que le jeu de Nim, en suivant l'API de Florent Madelaine.
Dans un second temps, nous développerons des bots les plus efficaces possible, probablement en utilisant un algorithme alpha-bêta avec cut-off et une fonction d'évaluation réalisé à la main ou par MonteCarlo.
Le jeu de notre groupe est **Avalam**. Le jeu de notre groupe est **Avalam**.
## Compilation et exécution ## Compilation, exécution et tests
### Compilation ### Compilation (sans tests)
```bash ```bash
make build make build
``` ```
ou simplement :
```bash
make
```
Cette commande :
- compile uniquement le code de l'application (sans les fichiers du dossier `fr/iut_fbleau/Tests`) ;
- copie les ressources dans `bin/`.
### Exécution ### Exécution du jeu
```bash ```bash
make run make run
``` ```
Lance la fenêtre de jeu Avalam après compilation.
### Lancer les tests
```bash
make test
```
Cette commande :
- vérifie d'abord la présence de **JUnit** et **Hamcrest** dans `/usr/share/java` ;
- si nécessaire, tente de les installer automatiquement via `apt-get` (sudo requis sur Debian/Ubuntu) ;
- compile ensuite les fichiers de tests (`fr/iut_fbleau/Tests`) ;
- lance enfin la suite de tests JUnit (`AvalamBoardTest`).
Si l'installation automatique échoue (autre OS, pas de droits sudo, pas d'accès réseau, etc.), un message l'indiquera et il faudra installer JUnit/Hamcrest manuellement.
### Nettoyage ### Nettoyage
```bash ```bash
make clean make clean
``` ```
Supprime le répertoire `bin/` (classes compilées et ressources copiées).
### Recompiler et exécuter ### Recompiler puis exécuter
```bash ```bash
make re make re
``` ```
Équivaut à `make clean` puis `make build` puis `make run`.
### Générer la Javadoc ### Générer la Javadoc
```bash ```bash
make javadoc make javadoc
``` ```
Génère la documentation dans le dossier `doc/`.
## Architecture du projet ## Architecture du projet
@@ -78,13 +103,13 @@ Le plateau est représenté par une grille 9x9 où chaque case contient :
Sur un plateau de jeu, les joueurs disposent de 24 pions chacun. Le but est de créer de petites tours avec son pion de couleur au-dessus. Pour ce faire, chaque joueur déplace son pion sur une tour ou déplace une tour sur un autre pion. La personne ayant le plus de pions sur le dessus des tours gagne. Sur un plateau de jeu, les joueurs disposent de 24 pions chacun. Le but est de créer de petites tours avec son pion de couleur au-dessus. Pour ce faire, chaque joueur déplace son pion sur une tour ou déplace une tour sur un autre pion. La personne ayant le plus de pions sur le dessus des tours gagne.
### Régles officiel : ### Règles officielles :
**Régle de base** \ **Régle de base** \
Chaque joueur choisit sa couleur. Chaque joueur choisit sa couleur.
Le but du jeu est de constituer un maximum de tours de 1 à 5 pions, jamais plus, surmontées par un pion de sa couleur. Le but du jeu est de constituer un maximum de tours de 1 à 5 pions, jamais plus, surmontées par un pion de sa couleur.
Un joueur est le propriétaire d'une tour lorsqu'un pion de sa couleur en occupe le sommet. Un pion isolé constitue également une tour. Un joueur est le propriétaire d'une tour lorsqu'un pion de sa couleur en occupe le sommet. Un pion isolé constitue également une tour.
**Deplacements** \ **Déplacements** \
Chaque joueur en effectue un seul mouvement, dans n'importe quel sens (horizontal, vertical, diagonal) avec n'importe quel pion (ou pile de pions), quelle qu'en soit la couleur. Ce mouvement consiste à empiler le ou les pions déplacés sur un trou directement voisin déjà occupé par un ou plusieurs pions. Chaque joueur en effectue un seul mouvement, dans n'importe quel sens (horizontal, vertical, diagonal) avec n'importe quel pion (ou pile de pions), quelle qu'en soit la couleur. Ce mouvement consiste à empiler le ou les pions déplacés sur un trou directement voisin déjà occupé par un ou plusieurs pions.
**Mouvement interdit (1)** \ **Mouvement interdit (1)** \

View File

@@ -205,6 +205,7 @@ public class AvalamBoard extends AbstractBoard {
Tower dst = grid[xT][yT]; Tower dst = grid[xT][yT];
if (src == null || dst == null) return false; if (src == null || dst == null) return false;
if (p.getPlayer() != getCurrentPlayer()) return false;
if (src.getColor() != colorForPlayer(getCurrentPlayer())) return false; if (src.getColor() != colorForPlayer(getCurrentPlayer())) return false;
if (!areAdjacent(xF, yF, xT, yT)) return false; if (!areAdjacent(xF, yF, xT, yT)) return false;
if (src.getColor() == dst.getColor()) return false; if (src.getColor() == dst.getColor()) return false;

View File

@@ -0,0 +1,123 @@
package fr.iut_fbleau.Tests;
import fr.iut_fbleau.GameAPI.AbstractPly;
import fr.iut_fbleau.GameAPI.Player;
import fr.iut_fbleau.Avalam.AvalamBoard;
import fr.iut_fbleau.Avalam.AvalamPly;
import fr.iut_fbleau.Avalam.Tower;
import fr.iut_fbleau.Avalam.Color;
import org.junit.Before;
import org.junit.Test;
//import org.mockito.Mockito; //Mockito absent
import static org.junit.Assert.*;
/**
* La classe <code>AvalamBoardTest</code> test si la méthode isLegal() fonctionne comme prévu.
*/
public class AvalamBoardTest {
private Tower[][] grid;
private AvalamBoard board;
@Before
public void setUp() {
grid = new Tower[AvalamBoard.SIZE][AvalamBoard.SIZE];
//Création des tours de tests
/* Motif
1,0,2 | 2,0,3
2,1,0 | 2,3,0
0,2,1 | 0,1,1
*/
grid[4][2] = new Tower(2, Color.YELLOW);
grid[6][2] = new Tower(3, Color.RED);
grid[4][3] = new Tower(2, Color.RED);
grid[5][3] = new Tower(3, Color.YELLOW);
grid[5][4] = new Tower(1, Color.RED);
grid[6][4] = new Tower(1, Color.YELLOW);
//Joueur courant initialisé à 1, soit jaune
board = new AvalamBoard(grid); //AvalamBoard copie la grille
}
/*
@Test //Mockito absent
public void nonAvalamPly_returnsFalse() {
//Vérifie si l'instance est bien AvalamPly
AbstractPly fake = Mockito.mock(AbstractPly.class); //Crée une instance non-AvalamPly
assertFalse(board.isLegal(fake));
}*/
@Test
public void outOfBounds_returnsFalse() {
//Source "out of box"
AvalamPly p = new AvalamPly(Player.PLAYER1, -1, 2, 4, 2);
assertFalse(board.isLegal(p));
//Destination "out of box"
AvalamPly p2 = new AvalamPly(Player.PLAYER1, 6, 4, 9, 4);
assertFalse(board.isLegal(p2));
}
@Test
public void sameCell_returnsFalse() {
AvalamPly p = new AvalamPly(Player.PLAYER1, 5, 4, 5, 4);
assertFalse(board.isLegal(p));
}
@Test
public void emptySourceOrDest_returnsFalse() {
//Source null
AvalamPly p1 = new AvalamPly(Player.PLAYER1, 5, 5, 5, 4);
assertFalse(board.isLegal(p1));
//Destination null
AvalamPly p2 = new AvalamPly(Player.PLAYER1, 6, 4, 6, 3);
assertFalse(board.isLegal(p2));
}
@Test
public void sourceNotOwned_returnsFalse() {
//Le joueur courant n'est pas rouge
AvalamPly p = new AvalamPly(Player.PLAYER1, 5, 4, 6, 4);
assertFalse(board.isLegal(p));
}
@Test
public void notAdjacent_returnsFalse() {
AvalamPly p = new AvalamPly(Player.PLAYER1, 4, 2, 6, 2);
assertFalse(board.isLegal(p));
}
@Test
public void sameColor_returnsFalse() {
//La couleur des tours est identique
AvalamPly p = new AvalamPly(Player.PLAYER1, 4, 2, 5, 3);
assertFalse(board.isLegal(p));
}
@Test
public void tooTallAfterMerge_returnsFalse() {
//Hauteur maximale dépassé : 3+3 = 6 > MAX_HEIGHT (5)
AvalamPly p = new AvalamPly(Player.PLAYER1, 5, 3, 6, 2);
assertFalse(board.isLegal(p));
}
@Test
public void validMove_returnsTrue() {
AvalamPly p = new AvalamPly(Player.PLAYER1, 5, 3, 4, 3); //Hauteur limite à 5
assertTrue(board.isLegal(p));
}
@Test //À vérifier
public void currentPlayerMismatchInPlyDoesNotAffectOwnershipCheck() {
//Si le coup est construit avec le mauvais joueur
AvalamPly p = new AvalamPly(Player.PLAYER2, 4, 2, 4, 3);
assertFalse(board.isLegal(p));
}
}