2 Commits

Author SHA1 Message Date
4b7d0c7753 nul 2025-10-08 17:14:42 +02:00
cc14043782 readme 2025-10-08 16:25:54 +02:00
4 changed files with 60 additions and 39 deletions

View File

@@ -17,7 +17,6 @@ import java.util.stream.Stream;
* - Si le fichier est introuvable ou vide, bascule sur une liste par défaut. * - Si le fichier est introuvable ou vide, bascule sur une liste par défaut.
*/ */
public class Words { public class Words {
/** Chemin du fichier de mots (relatif à la racine du projet). */ /** Chemin du fichier de mots (relatif à la racine du projet). */
private static final Path WORDS_PATH = Paths.get("Bibliotheque", "mots.txt"); private static final Path WORDS_PATH = Paths.get("Bibliotheque", "mots.txt");
@@ -83,13 +82,13 @@ public class Words {
return result; return result;
} }
/* Retourne la liste complète des mots disponibles */ /** Retourne la liste complète des mots disponibles */
public static List<String> all() { public static List<String> all() {
ensureLoaded(); ensureLoaded();
return new ArrayList<>(CACHE); return new ArrayList<>(CACHE);
} }
/* Petit utilitaire pour afficher un mot masqué dans les messages */ /** Petit utilitaire pour afficher un mot masqué dans les messages */
public static String hiddenWord(Game g) { public static String hiddenWord(Game g) {
return g.maskedWord().replace(' ', '_'); return g.maskedWord().replace(' ', '_');
} }

View File

@@ -10,16 +10,16 @@ import java.util.List;
/** /**
* Interface graphique du jeu du pendu avec gestion des difficultés. * Interface graphique du jeu du pendu avec gestion des difficultés.
* - Niveau 1 : mots de moins de 8 lettres * - Niveau Facile : mots < 8 lettres
* - Niveau 2 : mots de 8 lettres ou plus * - Niveau Moyen : mots 8 lettres
* - Niveau 3 : deux mots à deviner à la suite (un court + un long) * - Niveau Difficile : deux mots à la suite (score & chrono cumulés)
* Toutes les méthodes ≤ 50 lignes. * Toutes les méthodes ≤ 50 lignes.
*/ */
public class GameUI { public class GameUI {
private JFrame frame; private JFrame frame;
private JLabel imgLabel, wordLabel, triedLabel, scoreLabel, timeLabel; private JLabel imgLabel, wordLabel, triedLabel, scoreLabel, timeLabel;
private JTextField input; private JTextField input;
private JButton tryBtn, quitBtn, menuBtn; private JButton tryBtn, quitBtn, menuBtn, newGameBtn;
private Game game; private Game game;
private List<String> words; private List<String> words;
@@ -28,10 +28,11 @@ public class GameUI {
private String currentWord = ""; private String currentWord = "";
private Timer timer; private Timer timer;
/** Constructeur : reçoit la difficulté (1, 2 ou 3) */ // Cumul pour le niveau 3
public GameUI(int level) { private long sessionStartNano = -1L; // début du niveau
this.level = level; private int sessionScore = 0; // score cumulé des mots terminés
}
public GameUI(int level) { this.level = level; }
/** Affiche la fenêtre et lance la partie (ou séquence) */ /** Affiche la fenêtre et lance la partie (ou séquence) */
public void show() { public void show() {
@@ -39,6 +40,7 @@ public class GameUI {
setupLayout(); setupLayout();
setupActions(); setupActions();
prepareWords(); prepareWords();
sessionStartNano = System.nanoTime(); // CHRONO DE SESSION (lvl 3)
startRound(); startRound();
frame.setVisible(true); frame.setVisible(true);
} }
@@ -48,11 +50,11 @@ public class GameUI {
words = new ArrayList<String>(); words = new ArrayList<String>();
List<String> all = Words.all(); List<String> all = Words.all();
if (level == 1) { // mots courts if (level == 1) {
for (String w : all) if (w.length() < 8) words.add(w); for (String w : all) if (w.length() < 8) words.add(w);
} else if (level == 2) { // mots longs } else if (level == 2) {
for (String w : all) if (w.length() >= 8) words.add(w); for (String w : all) if (w.length() >= 8) words.add(w);
} else if (level == 3) { // un court + un long } else if (level == 3) {
String shortW = null, longW = null; String shortW = null, longW = null;
for (String w : all) { for (String w : all) {
if (shortW == null && w.length() < 8) shortW = w; if (shortW == null && w.length() < 8) shortW = w;
@@ -62,7 +64,6 @@ public class GameUI {
if (shortW != null) words.add(shortW); if (shortW != null) words.add(shortW);
if (longW != null) words.add(longW); if (longW != null) words.add(longW);
} }
if (words.isEmpty()) words.add(Words.random()); if (words.isEmpty()) words.add(Words.random());
} }
@@ -90,11 +91,11 @@ public class GameUI {
top.add(buildTopLine(triedLabel, timeLabel)); top.add(buildTopLine(triedLabel, timeLabel));
frame.add(top, BorderLayout.NORTH); frame.add(top, BorderLayout.NORTH);
// --- Bas : boutons + saisie
JPanel bottom = new JPanel(new BorderLayout(8, 8)); JPanel bottom = new JPanel(new BorderLayout(8, 8));
JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
input = new JTextField(5); input = new JTextField(5);
tryBtn = new JButton("Essayer"); tryBtn = new JButton("Essayer");
newGameBtn = new JButton("Nouvelle partie");
inputPanel.add(new JLabel("Lettre :")); inputPanel.add(new JLabel("Lettre :"));
inputPanel.add(input); inputPanel.add(input);
inputPanel.add(tryBtn); inputPanel.add(tryBtn);
@@ -107,6 +108,7 @@ public class GameUI {
bottom.add(inputPanel, BorderLayout.WEST); bottom.add(inputPanel, BorderLayout.WEST);
bottom.add(actionPanel, BorderLayout.EAST); bottom.add(actionPanel, BorderLayout.EAST);
top.add(newGameBtn, BorderLayout.EAST);
frame.add(bottom, BorderLayout.SOUTH); frame.add(bottom, BorderLayout.SOUTH);
} }
@@ -136,10 +138,13 @@ public class GameUI {
menu.show(); menu.show();
} }
/** Démarre un nouveau mot (ou termine au niveau 3) */ /** Démarre un nouveau mot (ou termine la séquence au niveau 3) */
private void startRound() { private void startRound() {
if (index >= words.size()) { if (index >= words.size()) {
showMsg("🎉 Niveau terminé !"); // Fin du niveau (affiche score cumulé si lvl 3)
int finalScore = (level == 3) ? sessionScore : game.getScore();
long secs = (level == 3) ? getSessionSeconds() : game.getElapsedSeconds();
showMsg("Niveau terminé !\nScore total : " + finalScore + "\nTemps : " + secs + "s");
frame.dispose(); frame.dispose();
return; return;
} }
@@ -167,20 +172,25 @@ public class GameUI {
checkEnd(); checkEnd();
} }
/** Vérifie la fin du mot et enchaîne si besoin (niveau 3) */ /** Vérifie fin de mot et enchaîne si besoin (niveau 3 → cumule score & chrono) */
private void checkEnd() { private void checkEnd() {
if (!(game.isWin() || game.isLose())) return; if (!(game.isWin() || game.isLose())) return;
timer.stop(); game.end(game.isWin()); // applique bonus de fin pour ce mot
game.end(game.isWin()); int displayScore = (level == 3) ? sessionScore + game.getScore() : game.getScore();
long displaySecs = (level == 3) ? getSessionSeconds() : game.getElapsedSeconds();
String verdict = game.isWin() ? "Bravo !" : "Perdu !"; String verdict = game.isWin() ? "Bravo !" : "Perdu !";
String msg = verdict + " Le mot était : " + currentWord showMsg(verdict + " Le mot était : " + currentWord
+ "\nScore : " + game.getScore() + "\nScore : " + displayScore
+ "\nTemps : " + game.getElapsedSeconds() + "s"; + "\nTemps : " + displaySecs + "s");
showMsg(msg);
if (level == 3 && index < words.size()) { if (level == 3 && index < words.size()) {
// CUMULE le score du mot terminé, poursuit SANS réinitialiser le chrono
sessionScore += game.getScore();
startRound(); startRound();
} else {
timer.stop(); // fins niveaux 1/2, ou mot 2 du niveau 3
} }
} }
@@ -193,14 +203,22 @@ public class GameUI {
frame.repaint(); frame.repaint();
} }
/** Rafraîchit uniquement score + chrono */ /** Rafraîchit uniquement score + chrono (cumul si niveau 3) */
private void refreshStatsOnly() { private void refreshStatsOnly() {
scoreLabel.setText("Score : " + game.getScore()); int s = (level == 3) ? sessionScore + game.getScore() : game.getScore();
timeLabel.setText("Temps : " + game.getElapsedSeconds() + "s"); long t = (level == 3) ? getSessionSeconds() : game.getElapsedSeconds();
scoreLabel.setText("Score : " + s);
timeLabel.setText("Temps : " + t + "s");
}
/** Durée écoulée depuis le début du niveau (niveau 3) */
private long getSessionSeconds() {
long now = System.nanoTime();
long delta = now - sessionStartNano;
if (delta < 0) delta = 0;
return delta / 1_000_000_000L;
} }
/** Affiche un message */ /** Affiche un message */
private void showMsg(String msg) { private void showMsg(String msg) { JOptionPane.showMessageDialog(frame, msg); }
JOptionPane.showMessageDialog(frame, msg);
}
} }

View File

@@ -3,7 +3,7 @@ package front;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
/* /**
* Menu de démarrage du jeu du pendu. * Menu de démarrage du jeu du pendu.
* Permet de choisir la difficulté (facile, moyen ou difficile). * Permet de choisir la difficulté (facile, moyen ou difficile).
*/ */
@@ -41,7 +41,7 @@ public class MenuUI {
frame.setVisible(true); frame.setVisible(true);
} }
/* Lance le jeu avec le niveau choisi */ /** Lance le jeu avec le niveau choisi */
private void startGame(int level) { private void startGame(int level) {
frame.dispose(); // ferme le menu frame.dispose(); // ferme le menu
GameUI ui = new GameUI(level); GameUI ui = new GameUI(level);

View File

@@ -5,11 +5,15 @@
## Fonctionnalités ## Fonctionnalités
Affichage dune **image différente du pendu** à chaque erreur - Affichage dune **image différente du pendu** à chaque erreur
Lecture de mots depuis un **fichier externe** (`bibliothèque/mots.txt`) - Lecture de mots depuis un **fichier externe** (`bibliothèque/mots.txt`)
Validation des entrées (une seule LETTRE à la fois) - Validation des entrées (une seule LETTRE à la fois)
Bouton **“Nouvelle partie”** pour rejouer sans relancer le programme - Bouton **“Nouvelle partie”** pour rejouer sans relancer le programme
Messages de victoire / défaite - Bouton **“Quitter”** pour quitter le programme
- Bouton **“Menu”** pour retourner à la page menu et pouvoir rechoisir le niveau de difficulté
- Messages de victoire / défaite
- Score + Chronomètre en direct
- Sélection du niveau dans le menu avant de jouer (Facile, Moyen, Difficile)
--- ---