Compare commits

11 Commits

27 changed files with 67655 additions and 1757 deletions

View File

@@ -1,8 +1,9 @@
# === Configuration === # === Configuration ===
SRC_DIR = src SRC_DIR = src
OUT_DIR = out OUT_DIR = out
Dictionary = fr/iut/Projet/Dictionary
PACKAGE = fr/iut/Projet PACKAGE = fr/iut/Projet
MAIN_CLASS = fr.iut.Projet.Random_word MAIN_CLASS = fr.iut.Projet.Display
# === Règle principale === # === Règle principale ===
all: compile run all: compile run
@@ -11,8 +12,11 @@ all: compile run
compile: compile:
@echo "Compilation du projet..." @echo "Compilation du projet..."
@mkdir -p $(OUT_DIR) @mkdir -p $(OUT_DIR)
@javac -d $(OUT_DIR) $(SRC_DIR)/$(PACKAGE)/Random_word.java # Compilation de tous les fichiers Java du package
@cp $(SRC_DIR)/$(PACKAGE)/Word.txt $(OUT_DIR)/$(PACKAGE)/ @javac -d $(OUT_DIR) $(SRC_DIR)/$(PACKAGE)/*.java
# Copier Word.txt dans le dossier de sortie
@mkdir -p $(OUT_DIR)/$(Dictionary)
@cp $(SRC_DIR)/$(Dictionary)/*.txt $(OUT_DIR)/$(Dictionary)/
@echo "Compilation terminée." @echo "Compilation terminée."
# === Exécution === # === Exécution ===

BIN
out/Affiche.class Normal file

Binary file not shown.

BIN
out/Mouse.class Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,294 @@
package fr.iut.Projet;
import javax.swing.*;
import java.awt.*;
/**
* Classe principale qui gère l'interface graphique du jeu du pendu.
*
* Cette classe crée la fenêtre du jeu et affiche :
* - le mot caché avec les lettres devinées,
* - les lettres incorrectes,
* - le dessin du pendu (via {@link Affiche}),
* - le timer affiché en haut à droite (via {@link GameTimer}),
* et permet à l'utilisateur de saisir des lettres.
* Elle gère également :
* - la logique de mise à jour de l'interface,
* - la fin de partie,
* - le redémarrage,
* - et le changement de difficulté en utilisant {@link PlayButtonListener}.
*/
public class Action {
/** Fenêtre principale du jeu */
private JFrame gameFrame;
/** Label affichant le mot caché avec les lettres découvertes */
private JLabel wordLabel;
/** Label affichant les lettres incorrectes devinées par le joueur */
private JLabel incorrectLettersLabel;
/** Champ de texte pour saisir une lettre */
private JTextField letterInputField;
/** Instance de la logique du jeu (mot secret, lettres, vies, etc.) */
private Random_word game;
/** Composant graphique représentant le pendu */
private Affiche affiche;
/** Timer qui compte le temps écoulé depuis le début du mot */
private GameTimer gameTimer;
/** Niveau de difficulté courant ("facile", "moyen", "difficile", "hell") */
private String difficulty;
/**
* Constructeur : initialise le jeu avec la difficulté choisie,
* crée les composants graphiques et démarre le timer.
*
* @param difficulty Niveau de difficulté pour le mot à deviner
*/
public Action(String difficulty) {
this.difficulty = difficulty;
// Création du jeu avec le mot choisi selon la difficulté
game = new Random_word(difficulty);
// Initialisation des composants graphiques
initializeComponents();
layoutComponents();
// Gestion de la saisie utilisateur
letterInputField.addActionListener(e -> handleGuess());
// Démarre le timer dès l'ouverture de la partie
gameTimer.start();
// Affiche la fenêtre du jeu
gameFrame.setVisible(true);
}
// ==================== Initialisation des composants ====================
/**
* Initialise tous les composants graphiques du jeu :
* - fenêtre principale
* - dessin du pendu
* - labels pour le mot et les lettres incorrectes
* - champ de saisie
* - timer
*/
private void initializeComponents() {
gameFrame = new JFrame("Hanging Man - " + difficulty);
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gameFrame.setSize(700, 500);
// Composant graphique pour dessiner le pendu
affiche = new Affiche();
affiche.setPreferredSize(new Dimension(350, 400));
affiche.setBackground(Color.WHITE);
affiche.setOpaque(true);
// Label affichant le mot caché
wordLabel = new JLabel(game.getHiddenWord());
wordLabel.setFont(new Font("Arial", Font.BOLD, 32));
wordLabel.setHorizontalAlignment(SwingConstants.CENTER);
// Label affichant les lettres incorrectes
incorrectLettersLabel = new JLabel("Incorrect letters: " + game.getIncorrectLetters());
incorrectLettersLabel.setFont(new Font("Arial", Font.PLAIN, 20));
incorrectLettersLabel.setHorizontalAlignment(SwingConstants.CENTER);
// Champ pour saisir une lettre
letterInputField = new JTextField(3);
letterInputField.setFont(new Font("Arial", Font.PLAIN, 24));
// Création du timer
gameTimer = new GameTimer();
}
// ==================== Mise en page ====================
/**
* Crée la mise en page principale avec un BorderLayout :
* - panneau gauche : dessin du pendu
* - panneau droit : mot, lettres incorrectes, champ de saisie, boutons et timer
*/
private void layoutComponents() {
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(createLeftPanel(), BorderLayout.WEST);
mainPanel.add(createRightPanel(), BorderLayout.CENTER);
gameFrame.add(mainPanel);
}
/** Crée le panneau gauche avec le dessin du pendu */
private JPanel createLeftPanel() {
JPanel leftPanel = new JPanel(new BorderLayout());
leftPanel.add(affiche, BorderLayout.CENTER);
return leftPanel;
}
/**
* Crée le panneau droit avec tous les éléments :
* - mot caché
* - lettres incorrectes
* - champ de saisie
* - bouton restart
* - bouton changement de difficulté
* - timer en haut à droite
*/
private JPanel createRightPanel() {
JPanel rightPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(5, 5, 5, 5);
// Mot caché
gbc.gridy = 0;
gbc.weighty = 1.0;
rightPanel.add(wordLabel, gbc);
// Lettres incorrectes
gbc.gridy = 1;
rightPanel.add(incorrectLettersLabel, gbc);
// Champ de saisie
gbc.gridy = 2;
JPanel inputRow = new JPanel();
inputRow.add(new JLabel("Enter a letter:"));
inputRow.add(letterInputField);
rightPanel.add(inputRow, gbc);
// Bouton restart
gbc.gridy = 3;
JButton restartButton = new JButton("Restart");
restartButton.addActionListener(e -> restartGame());
rightPanel.add(restartButton, gbc);
// Bouton changement de difficulté
gbc.gridy = 4;
JButton changeDifficultyButton = new JButton("Changer la difficulté");
changeDifficultyButton.addActionListener(e -> showDifficultyDialog());
rightPanel.add(changeDifficultyButton, gbc);
// Timer en haut à droite
gbc.gridy = 5;
gbc.anchor = GridBagConstraints.NORTHEAST;
rightPanel.add(gameTimer.getTimerLabel(), gbc);
return rightPanel;
}
// ==================== Gestion des actions ====================
/**
* Traite la saisie d'une lettre par le joueur :
* - vérifie la validité
* - met à jour le mot caché et lettres incorrectes
* - met à jour le pendu
* - termine la partie si nécessaire
*/
private void handleGuess() {
String inputText = letterInputField.getText();
letterInputField.setText("");
if (!isValidInput(inputText)) return;
char guessedLetter = inputText.charAt(0);
String message = game.guessLetter(guessedLetter);
updateUI();
if (game.isGameOver()) endGame(message);
}
/** Vérifie que le texte saisi est une seule lettre */
private boolean isValidInput(String inputText) {
if (inputText.length() != 1 || !Character.isLetter(inputText.charAt(0))) {
JOptionPane.showMessageDialog(gameFrame, "Please enter a single letter!");
return false;
}
return true;
}
/** Met à jour les labels et le dessin du pendu */
private void updateUI() {
wordLabel.setText(game.getHiddenWord());
incorrectLettersLabel.setText("Incorrect letters: " + game.getIncorrectLetters());
affiche.setLives(game.getLives());
}
/**
* Termine la partie :
* - arrête le timer
* - met à jour le dessin du pendu en cas de victoire/défaite
* - affiche le message de fin
* - désactive le champ de saisie
*/
private void endGame(String message) {
gameTimer.stop();
if (game.isWon()) {
affiche.setYouWin(true);
} else {
affiche.setLives(0);
}
JOptionPane.showMessageDialog(gameFrame, message);
letterInputField.setEditable(false);
}
/** Redémarre le jeu avec la même difficulté en utilisant PlayButtonListener */
private void restartGame() {
gameFrame.dispose();
JFrame tempFrame = new JFrame();
new PlayButtonListener(tempFrame, difficulty).actionPerformed(null);
}
/**
* Affiche une boîte de dialogue pour changer la difficulté,
* puis relance le jeu avec la nouvelle difficulté.
*/
private void showDifficultyDialog() {
String[] options = {"Facile", "Moyen", "Difficile", "Hell"};
int choice = JOptionPane.showOptionDialog(
gameFrame,
"Choisissez la difficulté :",
"Changer la difficulté",
JOptionPane.DEFAULT_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]
);
if (choice >= 0) {
String newDifficulty;
switch (choice) {
case 0:
newDifficulty = "facile";
break;
case 1:
newDifficulty = "moyen";
break;
case 2:
newDifficulty = "difficile";
break;
case 3:
newDifficulty = "hell";
break;
default:
newDifficulty = "moyen";
break;
}
gameFrame.dispose();
JFrame tempFrame = new JFrame();
new PlayButtonListener(tempFrame, newDifficulty).actionPerformed(null);
}
}
}

View File

@@ -0,0 +1,177 @@
package fr.iut.Projet;
import javax.swing.*;
import java.awt.*;
/**
* Classe graphique responsable du dessin du pendu dans le jeu.
* <p>
* Cette classe hérite de {@link JComponent} et redéfinit la méthode
* {@link #paintComponent(Graphics)} pour afficher le pendu selon le nombre
* de vies restantes. Elle affiche également un message de victoire ou de défaite.
* </p>
*
* @author
* @version 1.0
*/
class Affiche extends JComponent {
/** Nombre de vies restantes (entre 0 et 8). */
private int lives = 8;
/** Indique si le joueur a gagné. */
private boolean youWin = false;
/**
* Définit le nombre de vies restantes et redessine le composant.
*
* @param lives nombre de vies restantes
*/
public void setLives(int lives) {
this.lives = lives;
repaint();
}
/**
* Définit si le joueur a gagné et redessine le composant.
*
* @param value {@code true} si le joueur a gagné, sinon {@code false}
*/
public void setYouWin(boolean value) {
this.youWin = value;
repaint();
}
/**
* Redessine le pendu en fonction du nombre de vies restantes.
* <ul>
* <li>Affiche la potence dès la première erreur</li>
* <li>Ajoute progressivement les membres du pendu</li>
* <li>Affiche une tête de mort si toutes les vies sont perdues</li>
* <li>Affiche un message "YOU WIN" si la partie est gagnée</li>
* </ul>
*
* @param g contexte graphique utilisé pour dessiner
*/
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (isOpaque()) {
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
}
Graphics2D g2 = (Graphics2D) g.create();
g2.setStroke(new BasicStroke(3));
g2.setColor(Color.BLACK);
if (lives <= 7) drawGallows(g2);
if (lives <= 6) drawHead(g2);
if (lives <= 5) drawBody(g2);
if (lives <= 4) drawLeftArm(g2);
if (lives <= 3) drawRightArm(g2);
if (lives <= 2) drawLeftLeg(g2);
if (lives <= 1) drawRightLeg(g2);
if (lives == 1) drawAura(g2);
if (lives == 0) drawSkull(g2);
if (youWin) drawYouWinMessage(g2);
g2.dispose();
}
// ==================== Méthodes de dessin ====================
/** Dessine la potence. */
private void drawGallows(Graphics2D g2) {
g2.drawLine(50, 350, 200, 350);
g2.drawLine(100, 350, 100, 50);
g2.drawLine(100, 50, 250, 50);
g2.drawLine(250, 50, 250, 100);
g2.drawLine(100, 100, 180, 50);
}
// Coordonnées et tailles du pendu
private final int headX = 225, headY = 100, headDiam = 50;
private final int bodyX = headX + headDiam / 2;
private final int bodyYStart = headY + headDiam;
private final int bodyYEnd = bodyYStart + 100;
private final int armLength = 60;
private final int legLength = 70;
/** Dessine la tête du pendu. */
private void drawHead(Graphics2D g2) { g2.drawOval(headX, headY, headDiam, headDiam); }
/** Dessine le corps du pendu. */
private void drawBody(Graphics2D g2) { g2.drawLine(bodyX, bodyYStart, bodyX, bodyYEnd); }
/** Dessine le bras gauche. */
private void drawLeftArm(Graphics2D g2) {
g2.drawLine(bodyX, bodyYStart + 20, bodyX - armLength, bodyYStart + 20);
}
/** Dessine le bras droit. */
private void drawRightArm(Graphics2D g2) {
g2.drawLine(bodyX, bodyYStart + 20, bodyX + armLength, bodyYStart + 20);
}
/** Dessine la jambe gauche. */
private void drawLeftLeg(Graphics2D g2) {
g2.drawLine(bodyX, bodyYEnd, bodyX - 5, bodyYEnd + legLength);
}
/** Dessine la jambe droite. */
private void drawRightLeg(Graphics2D g2) {
g2.drawLine(bodyX, bodyYEnd, bodyX + 5, bodyYEnd + legLength);
}
/** Dessine une aura bleue lorsque le joueur est sur sa dernière vie. */
private void drawAura(Graphics2D g2) {
g2.setColor(new Color(0, 0, 255, 100));
g2.setStroke(new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2.drawOval(headX, headY, headDiam, headDiam);
g2.drawLine(bodyX, bodyYStart, bodyX, bodyYEnd);
g2.drawLine(bodyX, bodyYStart + 20, bodyX - armLength, bodyYStart + 20);
g2.drawLine(bodyX, bodyYStart + 20, bodyX + armLength, bodyYStart + 20);
g2.drawLine(bodyX, bodyYEnd, bodyX - 5, bodyYEnd + legLength);
g2.drawLine(bodyX, bodyYEnd, bodyX + 5, bodyYEnd + legLength);
}
/** Dessine la tête de mort et le message "GAME OVER". */
private void drawSkull(Graphics2D g2) {
int skullX = 225, skullY = 100, skullDiam = 50;
g2.setColor(Color.BLACK);
g2.fillOval(skullX, skullY, skullDiam, skullDiam);
g2.setColor(Color.WHITE);
g2.fillOval(skullX + skullDiam / 5, skullY + skullDiam / 6, skullDiam / 5, skullDiam / 5);
g2.fillOval(skullX + 3 * skullDiam / 5, skullY + skullDiam / 6, skullDiam / 5, skullDiam / 5);
g2.fillOval(skullX + skullDiam / 2 - skullDiam / 12, skullY + skullDiam / 2 - skullDiam / 12, skullDiam / 6, skullDiam / 6);
g2.setStroke(new BasicStroke(2));
g2.drawLine(skullX + skullDiam / 5, skullY + 2 * skullDiam / 3,
skullX + 4 * skullDiam / 5, skullY + 2 * skullDiam / 3);
g2.setColor(Color.RED);
g2.setFont(new Font("Arial", Font.BOLD, 36));
String message = "GAME OVER";
FontMetrics fm = g2.getFontMetrics();
int textWidth = fm.stringWidth(message);
int xText = (getWidth() - textWidth) / 2;
int yText = skullY - 20;
g2.drawString(message, xText, yText);
}
/** Dessine le message "YOU WIN" en vert en cas de victoire. */
private void drawYouWinMessage(Graphics2D g2) {
g2.setColor(Color.GREEN);
g2.setFont(new Font("Arial", Font.BOLD, 36));
String message = "YOU WIN";
FontMetrics fm = g2.getFontMetrics();
int textWidth = fm.stringWidth(message);
int xText = (getWidth() - textWidth) / 2;
int yText = 50;
g2.drawString(message, xText, yText);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,65 @@
package fr.iut.Projet;
import javax.swing.*;
import java.awt.*;
/**
* Classe Display représentant le menu principal du jeu "Hanging Man".
* Elle affiche le titre et trois boutons de difficulté : Facile, Moyen et Difficile.
*/
public class Display {
/**
* Méthode principale. Crée et affiche la fenêtre du menu principal.
* @param args Arguments de la ligne de commande (non utilisés)
*/
public static void main(String[] args) {
// Création de la fenêtre principale
JFrame frame = new JFrame("Hanging Man");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1040, 1000);
frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
// Titre du jeu
JLabel text = new JLabel("Hanging Man");
text.setAlignmentX(Component.CENTER_ALIGNMENT);
text.setFont(new Font("Arial", Font.BOLD, 70));
// Création des boutons de difficulté
JButton easyButton = new JButton("Facile");
JButton mediumButton = new JButton("Moyen");
JButton hardButton = new JButton("Difficile");
JButton hellButton = new JButton("Hell");
// Mise en forme des boutons
JButton[] buttons = { easyButton, mediumButton, hardButton, hellButton};
for (JButton button : buttons) {
button.setAlignmentX(Component.CENTER_ALIGNMENT);
button.setPreferredSize(new Dimension(300, 100));
button.setMaximumSize(new Dimension(300, 150));
button.setFont(new Font("Arial", Font.PLAIN, 36));
}
// Ajout d'écouteurs (listeners)
easyButton.addActionListener(new PlayButtonListener(frame, "facile"));
mediumButton.addActionListener(new PlayButtonListener(frame, "moyen"));
hardButton.addActionListener(new PlayButtonListener(frame, "difficile"));
hellButton.addActionListener(new PlayButtonListener(frame, "hell"));
// Ajout des composants à la fenêtre
frame.add(Box.createVerticalGlue());
frame.add(text);
frame.add(Box.createVerticalStrut(50));
frame.add(easyButton);
frame.add(Box.createVerticalStrut(20));
frame.add(mediumButton);
frame.add(Box.createVerticalStrut(20));
frame.add(hardButton);
frame.add(Box.createVerticalStrut(20));
frame.add(hellButton);
frame.add(Box.createVerticalGlue());
// Affichage de la fenêtre
frame.setVisible(true);
}
}

View File

@@ -0,0 +1,68 @@
package fr.iut.Projet;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Classe GameTimer qui gère le temps écoulé sur un mot.
*
* Affiche le temps en secondes dans un JLabel et peut être intégré
* à la fenêtre du jeu.
*/
public class GameTimer {
/** Label affichant le temps écoulé */
private JLabel timerLabel;
/** Timer Swing qui incrémente le temps chaque seconde */
private Timer timer;
/** Compteur de secondes écoulées */
private int secondsElapsed;
/**
* Constructeur : crée le label et initialise le timer.
*/
public GameTimer() {
this.secondsElapsed = 0;
this.timerLabel = new JLabel("Temps : 0 s");
timerLabel.setHorizontalAlignment(SwingConstants.RIGHT);
// Timer qui déclenche l'action toutes les 1000ms (1 seconde)
this.timer = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
secondsElapsed++;
timerLabel.setText("Temps : " + secondsElapsed + " s");
}
});
}
/** Démarre le timer */
public void start() {
secondsElapsed = 0;
timer.start();
}
/** Arrête le timer */
public void stop() {
timer.stop();
}
/** Remet le compteur à zéro */
public void reset() {
secondsElapsed = 0;
timerLabel.setText("Temps : 0 s");
}
/** @return le JLabel contenant le temps écoulé */
public JLabel getTimerLabel() {
return timerLabel;
}
/** @return le temps écoulé en secondes */
public int getSecondsElapsed() {
return secondsElapsed;
}
}

View File

@@ -0,0 +1,42 @@
package fr.iut.Projet;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Classe PlayButtonListener qui gère le clic sur les boutons de difficulté.
* Lorsqu'on clique sur un bouton, elle ouvre la fenêtre du jeu avec le niveau choisi
* et ferme la fenêtre principale.
*/
public class PlayButtonListener implements ActionListener {
/** Référence à la fenêtre principale du menu */
private JFrame parentFrame;
/** Niveau de difficulté choisi */
private String difficulty;
/**
* Constructeur de PlayButtonListener.
* @param frame La fenêtre principale à fermer après ouverture du jeu
* @param difficulty Le niveau de difficulté choisi ("facile", "moyen" ou "difficile")
*/
public PlayButtonListener(JFrame frame, String difficulty) {
this.parentFrame = frame;
this.difficulty = difficulty;
}
/**
* Méthode appelée lorsque le bouton est cliqué.
* Ouvre la fenêtre du jeu avec la difficulté sélectionnée
* et ferme la fenêtre principale.
* @param e L'événement déclenché par le clic
*/
@Override
public void actionPerformed(ActionEvent e) {
// Passe la difficulté à la classe Action
new Action(difficulty);
parentFrame.dispose(); // Ferme le menu principal
}
}

View File

@@ -3,134 +3,203 @@ package fr.iut.Projet;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
/**
* Classe gérant la logique du jeu du pendu.
*
* Cette classe sélectionne un mot (ou une combinaison de mots) aléatoire
* selon la difficulté, conserve l'état du jeu (mot secret, lettres devinées,
* lettres incorrectes, nombre de vies) et fournit des méthodes pour deviner
* des lettres et vérifier l'état du jeu.
*/
public class Random_word { public class Random_word {
public static void main(String[] args) { /** Mot secret que le joueur doit deviner */
// Récupère un mot aléatoire depuis le fichier Word.txt private String secretWord;
String randomword = getRandomWord();
if (randomword == null) { /** Tableau représentant le mot caché avec les lettres découvertes et espaces */
System.err.println("Impossible de choisir un mot aléatoire !"); private char[] hiddenWord;
return;
/** Lettres correctement devinées par le joueur */
private Set<Character> lettersGuessed;
/** Lettres incorrectes devinées par le joueur */
private Set<Character> incorrectLetters;
/** Nombre de vies restantes */
private int lives;
/**
* Constructeur : sélectionne un mot aléatoire selon la difficulté
* et initialise les structures du jeu.
*
* @param difficulty Niveau de difficulté ("facile", "moyen", "difficile", "hell")
* @throws RuntimeException si aucun mot n'a pu être choisi
*/
public Random_word(String difficulty) {
if (difficulty.equalsIgnoreCase("hell")) {
// En mode Hell, on choisit deux mots faciles et on les concatène avec un espace
String firstWord = getRandomWord("facile");
String secondWord = getRandomWord("facile");
if (firstWord == null || secondWord == null) {
throw new RuntimeException("Impossible de choisir deux mots pour le mode Hell !");
}
this.secretWord = firstWord + " " + secondWord;
} else {
// Pour les autres difficultés, on choisit un seul mot correspondant
this.secretWord = getRandomWord(difficulty);
} }
// Démarre le jeu avec le mot choisi if (this.secretWord == null) {
play(randomword); throw new RuntimeException("Impossible de choisir un mot aléatoire !");
}
this.lives = 8; // nombre de vies par défaut
this.hiddenWord = new char[secretWord.length()];
// Initialise le mot caché : underscore pour les lettres, espace conservé
for (int i = 0; i < secretWord.length(); i++) {
hiddenWord[i] = (secretWord.charAt(i) == ' ') ? ' ' : '_';
}
this.lettersGuessed = new HashSet<>();
this.incorrectLetters = new HashSet<>();
} }
/** /**
* Lit les mots dans "Word.txt" et retourne un mot aléatoire. * Lit un fichier de mots correspondant à la difficulté et retourne un mot aléatoire.
* @return un mot aléatoire en minuscules, ou null si le fichier est introuvable ou vide *
* @param difficulty Niveau de difficulté
* @return mot aléatoire en minuscules
*/ */
public static String getRandomWord() { private String getRandomWord(String difficulty) {
// Charge le fichier Word.txt depuis le package String fileName;
InputStream is = Random_word.class.getResourceAsStream("Word.txt");
// Sélection du fichier selon la difficulté
switch (difficulty.toLowerCase()) {
case "facile":
fileName = "/fr/iut/Projet/Dictionary/EASY-FRENCH.txt";
break;
case "moyen":
fileName = "/fr/iut/Projet/Dictionary/MEDIUM-FRENCH.txt";
break;
case "difficile":
fileName = "/fr/iut/Projet/Dictionary/HARD-FRENCH.txt";
break;
default:
System.out.println("Difficulté inconnue, mode 'moyen' utilisé par défaut.");
fileName = "/fr/iut/Projet/Dictionary/MEDIUM-FRENCH.txt";
}
// Récupère le fichier dans les ressources
InputStream is = Random_word.class.getResourceAsStream(fileName);
if (is == null) { if (is == null) {
System.err.println("Le fichier 'Word.txt' est introuvable dans le package !"); System.err.println("Fichier introuvable : " + fileName);
return null; return null;
} }
String randomWord = null; String randomWord = null;
Random random = new Random(); Random random = new Random();
try (BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(is))) { try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
String line; String line;
int count = 0; int count = 0;
// Parcourt chaque ligne du fichier while ((line = br.readLine()) != null) {
while ((line = bufferedreader.readLine()) != null) {
line = line.trim(); line = line.trim();
if (!line.isEmpty()) { if (!line.isEmpty()) {
count++; count++;
// Sélection aléatoire d'un mot (méthode reservoir sampling) // Choix aléatoire d'une ligne avec Reservoir Sampling
if (random.nextInt(count) == 0) { if (random.nextInt(count) == 0) {
randomWord = line; randomWord = line;
} }
} }
} }
} catch (IOException e) { } catch (IOException e) {
System.err.println("Erreur lors de la lecture du fichier : " + e.getMessage()); e.printStackTrace();
} }
return randomWord != null ? randomWord.toLowerCase() : null; return randomWord != null ? randomWord.toLowerCase() : null;
} }
/** /**
* Affiche l'état actuel du mot et les lettres incorrectes. * Tente une lettre proposée par le joueur.
* @param hiddenWord le mot masqué avec les lettres découvertes * Met à jour l'état du jeu (mot caché, lettres incorrectes, vies restantes).
* @param incorrectLetters les lettres déjà essayées mais incorrectes *
* @param letter lettre proposée
* @return message d'information pour le joueur (succès, erreur ou fin de partie)
*/ */
private static void showwordstatus(char[] hiddenWord, Set<Character> incorrectLetters) { public String guessLetter(char letter) {
System.out.print("\nMot actuel : "); letter = Character.toLowerCase(letter);
for (char Character : hiddenWord) {
System.out.print(Character + " "); // Vérifie si la lettre a déjà été essayée
if (lettersGuessed.contains(letter) || incorrectLetters.contains(letter)) {
return "Vous avez déjà essayé cette lettre !";
}
// Lettre correcte
if (secretWord.indexOf(letter) >= 0) {
lettersGuessed.add(letter);
// Remplace les underscores par la lettre devinée
for (int i = 0; i < secretWord.length(); i++) {
if (secretWord.charAt(i) == letter) {
hiddenWord[i] = letter;
}
}
if (isWon()) {
return "Félicitations ! Vous avez trouvé le mot : " + secretWord;
}
return "Bien joué !";
} else {
// Lettre incorrecte
incorrectLetters.add(letter);
lives--;
if (lives <= 0) {
return "Vous avez perdu ! Le mot était : " + secretWord;
}
return "Mauvaise lettre ! Il vous reste " + lives + " vies.";
} }
System.out.println();
System.out.println("Lettres incorrectes : " + incorrectLetters);
} }
/** /** @return le mot caché avec les lettres découvertes séparées par des espaces */
* Logique principale du jeu : gère les essais, met à jour l'état du mot, public String getHiddenWord() {
* suit le nombre de vies restantes, et détermine la victoire ou la défaite. StringBuilder sb = new StringBuilder();
* @param secretWord le mot que le joueur doit deviner for (char c : hiddenWord) sb.append(c).append(' ');
*/ return sb.toString().trim();
public static void play(String secretWord) { }
Scanner scanner = new Scanner(System.in);
Set<Character> lettersGuessed = new HashSet<>();
Set<Character> incorrectLetters = new HashSet<>();
int lives = 8; // nombre d'essais
char[] hiddenWord = new char[secretWord.length()]; /** @return la liste des lettres incorrectes devinées */
Arrays.fill(hiddenWord, '_'); public String getIncorrectLetters() {
return incorrectLetters.toString();
}
System.out.println("Bienvenue dans le jeu du mot mystère !"); /** @return nombre de vies restantes */
System.out.println("Le mot contient " + secretWord.length() + " lettres."); public int getLives() {
return lives;
}
while (lives > 0) { /** @return true si le jeu est terminé (victoire ou défaite) */
// Affiche le mot actuel et les lettres incorrectes public boolean isGameOver() {
showwordstatus(hiddenWord, incorrectLetters); return lives <= 0 || isWon();
}
System.out.print("Entrez une lettre : "); /** @return true si le mot est entièrement deviné */
String input = scanner.nextLine().toLowerCase(); public boolean isWon() {
for (char c : hiddenWord) {
// Vérifie que l'entrée est valide if (c == '_') {
if (input.length() != 1 || !Character.isLetter(input.charAt(0))) { return false;
System.out.println("Entrez une seule lettre !");
continue;
}
char letter = input.charAt(0);
// Vérifie si la lettre a déjà été essayée
if (lettersGuessed.contains(letter) || incorrectLetters.contains(letter)) {
System.out.println("Vous avez déjà essayé cette lettre !");
continue;
}
// Vérifie si la lettre fait partie du mot secret
if (secretWord.indexOf(letter) >= 0) {
lettersGuessed.add(letter);
for (int i = 0; i < secretWord.length(); i++) {
if (secretWord.charAt(i) == letter) {
hiddenWord[i] = letter;
}
}
System.out.println("Bien joué !");
} else {
// Lettre incorrecte : décrémente le nombre de vies
incorrectLetters.add(letter);
lives--;
System.out.println("Mauvaise lettre ! Il vous reste " + lives + " vies.");
}
// Vérifie si le mot complet a été trouvé
if (String.valueOf(hiddenWord).equals(secretWord)) {
System.out.println("\nFélicitations ! Vous avez trouvé le mot : " + secretWord);
return;
} }
} }
return true;
}
// Le joueur a perdu /** @return le mot secret */
System.out.println("\nVous avez perdu ! Le mot était : " + secretWord); public String getSecretWord() {
return secretWord;
} }
} }

File diff suppressed because it is too large Load Diff