Compare commits

7 Commits

30 changed files with 67547 additions and 1847 deletions

View File

@@ -1,8 +1,9 @@
# === Configuration ===
SRC_DIR = src
OUT_DIR = out
Dictionary = fr/iut/Projet/Dictionary
PACKAGE = fr/iut/Projet
MAIN_CLASS = fr.iut.Projet.Random_word
MAIN_CLASS = fr.iut.Projet.Display
# === Règle principale ===
all: compile run
@@ -11,8 +12,11 @@ all: compile run
compile:
@echo "Compilation du projet..."
@mkdir -p $(OUT_DIR)
@javac -d $(OUT_DIR) $(SRC_DIR)/$(PACKAGE)/Random_word.java
@cp $(SRC_DIR)/$(PACKAGE)/Word.txt $(OUT_DIR)/$(PACKAGE)/
# Compilation de tous les fichiers Java du 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."
# === 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.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -4,28 +4,270 @@ import javax.swing.*;
import java.awt.*;
/**
* Classe Action représentant la fenêtre principale du jeu "Hanging Man".
* Affiche un message de bienvenue.
* Classe principale qui gère l'interface graphique du jeu du pendu.
*
* Affiche le mot caché, les lettres incorrectes, le dessin du pendu, le timer et le score.
* Gère également les interactions avec le joueur, la fin de partie et le redémarrage.
*/
public class Action {
private Score score;
private JFrame gameFrame;
private JLabel wordLabel;
private JLabel incorrectLettersLabel;
private JTextField letterInputField;
private Random_word game;
private Affiche affiche;
private GameTimer gameTimer;
private String difficulty;
/**
* Constructeur. Crée et affiche la fenêtre du jeu avec un message.
* Constructeur : initialise le jeu selon la difficulté choisie,
* crée tous les composants graphiques et démarre le timer.
* @param difficulty Niveau de difficulté ("facile", "moyen", "difficile", "hell")
*/
public Action() {
// Création de la fenêtre du jeu
JFrame gameFrame = new JFrame("Hanging Man");
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gameFrame.setSize(1040, 1000);
gameFrame.setLayout(new BorderLayout());
public Action(String difficulty) {
this.difficulty = difficulty;
game = new Random_word(difficulty);
// Label de bienvenue
JLabel label = new JLabel("Bienvenue dans le jeu !");
label.setFont(new Font("Arial", Font.BOLD, 28));
label.setHorizontalAlignment(SwingConstants.CENTER);
// Initialisation
initializeComponents();
layoutComponents();
setupListeners();
// Ajouter le label et afficher la fenêtre
gameFrame.add(label, BorderLayout.CENTER);
// Démarre le timer et affiche la fenêtre
gameTimer.start();
gameFrame.setVisible(true);
}
// ==================== Initialisation ====================
/** Initialise les composants principaux : fenêtre, jeu, timer et score */
private void initializeComponents() {
initializeFrameAndPanels();
initializeGameComponents();
initializeTimerAndScore();
}
/** Initialise la fenêtre principale */
private void initializeFrameAndPanels() {
gameFrame = new JFrame("Hanging Man - " + difficulty);
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gameFrame.setSize(700, 500);
}
/** Initialise les composants du jeu : pendu, mot caché, lettres incorrectes, champ de saisie */
private void initializeGameComponents() {
affiche = new Affiche();
affiche.setPreferredSize(new Dimension(350, 400));
affiche.setBackground(Color.WHITE);
affiche.setOpaque(true);
wordLabel = new JLabel(game.getHiddenWord());
wordLabel.setFont(new Font("Arial", Font.BOLD, 32));
wordLabel.setHorizontalAlignment(SwingConstants.CENTER);
incorrectLettersLabel = new JLabel("Incorrect letters: " + game.getIncorrectLetters());
incorrectLettersLabel.setFont(new Font("Arial", Font.PLAIN, 20));
incorrectLettersLabel.setHorizontalAlignment(SwingConstants.CENTER);
letterInputField = new JTextField(3);
letterInputField.setFont(new Font("Arial", Font.PLAIN, 24));
}
/** Initialise le timer et le score, avec un listener pour diminuer le score chaque seconde */
private void initializeTimerAndScore() {
gameTimer = new GameTimer();
score = new Score();
// Listener pour diminuer le score chaque seconde et finir après 60s
gameTimer.setTimerListener(() -> {
score.decreaseBySecond(); // comportement normal selon le temps
// Si 60 secondes écoulées et que la partie n'est pas finie
if (gameTimer.getSecondsElapsed() >= 60 && !game.isGameOver()) {
score.setScoreToZero(); // on met le score à 0
endGame("Temps écoulé ! Vous avez perdu !");
}
});
}
/** Ajoute les listeners sur les composants */
private void setupListeners() {
letterInputField.addActionListener(e -> handleGuess());
}
// ==================== Mise en page ====================
/** Organise la mise en page globale (BorderLayout : gauche pendu, droite info et saisie) */
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 mot, lettres incorrectes, saisie, boutons et timer/score */
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);
addWordAndIncorrectLetters(rightPanel, gbc);
addInputRow(rightPanel, gbc);
addButtons(rightPanel, gbc);
addTimerAndScore(rightPanel, gbc);
return rightPanel;
}
/** Ajoute le mot caché et les lettres incorrectes dans le panneau */
private void addWordAndIncorrectLetters(JPanel panel, GridBagConstraints gbc) {
gbc.gridy = 0;
gbc.weighty = 1.0;
panel.add(wordLabel, gbc);
gbc.gridy = 1;
panel.add(incorrectLettersLabel, gbc);
}
/** Ajoute le champ de saisie pour les lettres */
private void addInputRow(JPanel panel, GridBagConstraints gbc) {
gbc.gridy = 2;
JPanel inputRow = new JPanel();
inputRow.add(new JLabel("Enter a letter:"));
inputRow.add(letterInputField);
panel.add(inputRow, gbc);
}
/** Ajoute les boutons restart et changement de difficulté */
private void addButtons(JPanel panel, GridBagConstraints gbc) {
gbc.gridy = 3;
JButton restartButton = new JButton("Restart");
restartButton.addActionListener(e -> restartGame());
panel.add(restartButton, gbc);
gbc.gridy = 4;
JButton changeDifficultyButton = new JButton("Changer la difficulté");
changeDifficultyButton.addActionListener(e -> showDifficultyDialog());
panel.add(changeDifficultyButton, gbc);
}
/** Ajoute le timer et le score en haut à droite */
private void addTimerAndScore(JPanel panel, GridBagConstraints gbc) {
gbc.gridy = 5;
JPanel topRightPanel = new JPanel(new BorderLayout());
topRightPanel.add(gameTimer.getTimerLabel(), BorderLayout.WEST);
topRightPanel.add(score.getScoreLabel(), BorderLayout.EAST);
panel.add(topRightPanel, gbc);
}
// ==================== Gestion des actions ====================
/** Traite la saisie d'une lettre par le joueur */
private void handleGuess() {
String inputText = letterInputField.getText();
letterInputField.setText("");
if (!isValidInput(inputText)) return;
char guessedLetter = inputText.charAt(0);
String message = game.guessLetter(guessedLetter);
updateScore(message);
updateUI();
if (game.isGameOver()) {
if (game.isWon()) {
score.increaseByWordFound();
}
endGame(message);
}
}
/** Met à jour le score selon le résultat de la lettre */
private void updateScore(String message) {
if (message.contains("Bien joué")) {
score.increaseByCorrectLetter();
} else if (message.contains("Mauvaise lettre")) {
score.decreaseByWrongLetter();
}
}
/** Vérifie que la saisie 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 l'affichage du mot, des lettres incorrectes et des vies 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 et affiche le message */
private void endGame(String message) {
gameTimer.stop();
if (game.isWon()) {
affiche.setYouWin(true);
} else {
affiche.setLives(0);
score.setScoreToZero(); // <- on met le score à 0 en cas de défaite
}
JOptionPane.showMessageDialog(gameFrame, message);
letterInputField.setEditable(false);
}
/** Redémarre le jeu avec la même difficulté */
private void restartGame() {
gameFrame.dispose();
JFrame tempFrame = new JFrame();
new PlayButtonListener(tempFrame, difficulty).actionPerformed(null);
}
/** Affiche le dialogue pour changer la difficulté et relance le jeu */
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

@@ -1,20 +1,58 @@
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 {
private int step = 0;
/** Nombre de vies restantes (entre 0 et 8). */
private int lives = 8;
/** Indique si le joueur a gagné. */
private boolean youWin = false;
public void setStep(int step) {
this.step = step;
/**
* 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);
@@ -28,43 +66,67 @@ class Affiche extends JComponent {
g2.setStroke(new BasicStroke(3));
g2.setColor(Color.BLACK);
drawGallows(g2);
drawHangman(g2);
if (step >= 7) drawSkull(g2);
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) {
// Base and vertical post
g2.drawLine(50, 350, 200, 350);
g2.drawLine(100, 350, 100, 50);
// Horizontal beam and rope
g2.drawLine(100, 50, 250, 50);
g2.drawLine(250, 50, 250, 100);
// Diagonal support
g2.drawLine(100, 100, 180, 50);
}
private void drawHangman(Graphics2D g2) {
int headX = 225, headY = 100, headDiam = 50;
int bodyX = headX + headDiam / 2, bodyYStart = headY + headDiam, bodyYEnd = bodyYStart + 100;
int armLength = 60;
int legLength = 70;
// 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;
if (step >= 1) g2.drawOval(headX, headY, headDiam, headDiam); // head
if (step >= 2) g2.drawLine(bodyX, bodyYStart, bodyX, bodyYEnd); // body
if (step >= 3) g2.drawLine(bodyX, bodyYStart + 20, bodyX - armLength, bodyYStart + 20); // left arm
if (step >= 4) g2.drawLine(bodyX, bodyYStart + 20, bodyX + armLength, bodyYStart + 20); // right arm
if (step >= 5) g2.drawLine(bodyX, bodyYEnd, bodyX - 5, bodyYEnd + legLength); // left leg
if (step >= 6) g2.drawLine(bodyX, bodyYEnd, bodyX + 5, bodyYEnd + legLength); // right leg
/** Dessine la tête du pendu. */
private void drawHead(Graphics2D g2) { g2.drawOval(headX, headY, headDiam, headDiam); }
if (step == 6) drawAura(g2, headX, headY, headDiam, bodyX, bodyYStart, bodyYEnd, armLength, legLength);
/** 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);
}
private void drawAura(Graphics2D g2, int headX, int headY, int headDiam, int bodyX, int bodyYStart, int bodyYEnd, int armLength, int legLength) {
/** 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);
@@ -75,27 +137,22 @@ class Affiche extends JComponent {
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;
// Skull
g2.setColor(Color.BLACK);
g2.fillOval(skullX, skullY, skullDiam, skullDiam);
// Eyes
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);
// Nose
g2.fillOval(skullX + skullDiam / 2 - skullDiam / 12, skullY + skullDiam / 2 - skullDiam / 12, skullDiam / 6, skullDiam / 6);
// Mouth
g2.setStroke(new BasicStroke(2));
g2.drawLine(skullX + skullDiam / 5, skullY + 2 * skullDiam / 3,
skullX + 4 * skullDiam / 5, skullY + 2 * skullDiam / 3);
// GAME OVER message
g2.setColor(Color.RED);
g2.setFont(new Font("Arial", Font.BOLD, 36));
String message = "GAME OVER";
@@ -106,6 +163,7 @@ class Affiche extends JComponent {
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));
@@ -116,4 +174,4 @@ class Affiche extends JComponent {
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

@@ -5,7 +5,7 @@ import java.awt.*;
/**
* Classe Display représentant le menu principal du jeu "Hanging Man".
* Elle affiche le titre et le bouton Play.
* Elle affiche le titre et trois boutons de difficulté : Facile, Moyen et Difficile.
*/
public class Display {
@@ -25,24 +25,41 @@ public class Display {
text.setAlignmentX(Component.CENTER_ALIGNMENT);
text.setFont(new Font("Arial", Font.BOLD, 70));
// Bouton Play
JButton play = new JButton("Play");
play.setAlignmentX(Component.CENTER_ALIGNMENT);
play.setPreferredSize(new Dimension(300, 100));
play.setMaximumSize(new Dimension(300, 150));
play.setFont(new Font("Arial", Font.PLAIN, 36));
// 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");
// Listener séparé pour gérer le clic sur Play
play.addActionListener(new PlayButtonListener(frame));
// 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));
}
// Ajouter les composants avec de l'espace
// 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(30));
frame.add(play);
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,79 @@
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 déclencher un listener
* à chaque seconde (par exemple pour réduire le score ou vérifier la limite de temps).
*/
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;
/** Listener appelé à chaque tick (chaque seconde) */
private Runnable timerListener;
/** 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");
// Appel du listener pour gérer le score ou la fin de partie
if (timerListener != null) {
timerListener.run();
}
}
});
}
/** Définit le listener appelé à chaque seconde */
public void setTimerListener(Runnable listener) {
this.timerListener = listener;
}
/** 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

@@ -1,25 +0,0 @@
import java.awt.event.*;
import javax.swing.SwingUtilities;
class Mouse extends MouseAdapter {
private Affiche aff;
private int step = 0; // correspond à Affiche.step
public Mouse(Affiche aff) {
this.aff = aff;
}
@Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
// clic droit -> gagne
aff.setYouWin(true);
} else {
// clic gauche -> incrémente étape
if (step < 7) {
step++;
aff.setStep(step); // <-- utiliser setStep
}
}
}
}

View File

@@ -5,8 +5,8 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Classe PlayButtonListener qui gère le clic sur le bouton "Play" du menu.
* Lorsqu'on clique sur le bouton, cette classe ouvre la fenêtre du jeu
* 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 {
@@ -14,22 +14,29 @@ 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) {
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 et ferme la fenêtre principale.
* 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) {
new Action(); // Ouvre la fenêtre du jeu
parentFrame.dispose(); // Ferme la fenêtre principale
// 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.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 static void main(String[] args) {
// Récupère un mot aléatoire depuis le fichier Word.txt
String randomword = getRandomWord();
/** Mot secret que le joueur doit deviner */
private String secretWord;
if (randomword == null) {
System.err.println("Impossible de choisir un mot aléatoire !");
return;
/** Tableau représentant le mot caché avec les lettres découvertes et espaces */
private char[] hiddenWord;
/** 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
play(randomword);
if (this.secretWord == null) {
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.
* @return un mot aléatoire en minuscules, ou null si le fichier est introuvable ou vide
* Lit un fichier de mots correspondant à la difficulté et retourne un mot aléatoire.
*
* @param difficulty Niveau de difficulté
* @return mot aléatoire en minuscules
*/
public static String getRandomWord() {
// Charge le fichier Word.txt depuis le package
InputStream is = Random_word.class.getResourceAsStream("Word.txt");
private String getRandomWord(String difficulty) {
String fileName;
// 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) {
System.err.println("Le fichier 'Word.txt' est introuvable dans le package !");
System.err.println("Fichier introuvable : " + fileName);
return null;
}
String randomWord = null;
Random random = new Random();
try (BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(is))) {
try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
String line;
int count = 0;
// Parcourt chaque ligne du fichier
while ((line = bufferedreader.readLine()) != null) {
while ((line = br.readLine()) != null) {
line = line.trim();
if (!line.isEmpty()) {
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) {
randomWord = line;
}
}
}
} catch (IOException e) {
System.err.println("Erreur lors de la lecture du fichier : " + e.getMessage());
e.printStackTrace();
}
return randomWord != null ? randomWord.toLowerCase() : null;
}
/**
* Affiche l'état actuel du mot et les lettres incorrectes.
* @param hiddenWord le mot masqué avec les lettres découvertes
* @param incorrectLetters les lettres déjà essayées mais incorrectes
* Tente une lettre proposée par le joueur.
* Met à jour l'état du jeu (mot caché, lettres incorrectes, vies restantes).
*
* @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) {
System.out.print("\nMot actuel : ");
for (char Character : hiddenWord) {
System.out.print(Character + " ");
public String guessLetter(char letter) {
letter = Character.toLowerCase(letter);
// 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);
}
/**
* Logique principale du jeu : gère les essais, met à jour l'état du mot,
* suit le nombre de vies restantes, et détermine la victoire ou la défaite.
* @param secretWord le mot que le joueur doit deviner
*/
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
/** @return le mot caché avec les lettres découvertes séparées par des espaces */
public String getHiddenWord() {
StringBuilder sb = new StringBuilder();
for (char c : hiddenWord) sb.append(c).append(' ');
return sb.toString().trim();
}
char[] hiddenWord = new char[secretWord.length()];
Arrays.fill(hiddenWord, '_');
/** @return la liste des lettres incorrectes devinées */
public String getIncorrectLetters() {
return incorrectLetters.toString();
}
System.out.println("Bienvenue dans le jeu du mot mystère !");
System.out.println("Le mot contient " + secretWord.length() + " lettres.");
/** @return nombre de vies restantes */
public int getLives() {
return lives;
}
while (lives > 0) {
// Affiche le mot actuel et les lettres incorrectes
showwordstatus(hiddenWord, incorrectLetters);
/** @return true si le jeu est terminé (victoire ou défaite) */
public boolean isGameOver() {
return lives <= 0 || isWon();
}
System.out.print("Entrez une lettre : ");
String input = scanner.nextLine().toLowerCase();
// Vérifie que l'entrée est valide
if (input.length() != 1 || !Character.isLetter(input.charAt(0))) {
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 si le mot est entièrement deviné */
public boolean isWon() {
for (char c : hiddenWord) {
if (c == '_') {
return false;
}
}
return true;
}
// Le joueur a perdu
System.out.println("\nVous avez perdu ! Le mot était : " + secretWord);
/** @return le mot secret */
public String getSecretWord() {
return secretWord;
}
}

View File

@@ -0,0 +1,70 @@
package fr.iut.Projet;
import javax.swing.*;
import java.awt.*;
/**
* Classe Score qui gère le score du joueur.
*
* Commence à 100, diminue à chaque seconde et à chaque erreur,
* augmente à chaque bonne lettre et ajoute un bonus si le mot est trouvé.
* Si le joueur perd, le score devient 0.
*/
public class Score {
private int currentScore;
private JLabel scoreLabel;
/** Constructeur : initialise le score à 100 */
public Score() {
this.currentScore = 100;
this.scoreLabel = new JLabel("Score : " + currentScore);
this.scoreLabel.setFont(new Font("Arial", Font.BOLD, 16));
this.scoreLabel.setHorizontalAlignment(SwingConstants.RIGHT);
}
/** Décrémente le score de 1 point chaque seconde */
public void decreaseBySecond() {
currentScore = Math.max(0, currentScore - 1);
updateLabel();
}
/** Décrémente le score de 5 points pour une mauvaise lettre */
public void decreaseByWrongLetter() {
currentScore = Math.max(0, currentScore - 5);
updateLabel();
}
/** Incrémente le score de 10 points pour une bonne lettre */
public void increaseByCorrectLetter() {
currentScore += 10;
updateLabel();
}
/** Incrémente le score de 50 points si le mot est trouvé */
public void increaseByWordFound() {
currentScore += 50;
updateLabel();
}
/** Met le score à zéro (utilisé si le joueur perd) */
public void setScoreToZero() {
currentScore = 0;
updateLabel();
}
/** Met à jour le texte du JLabel */
private void updateLabel() {
scoreLabel.setText("Score : " + currentScore);
}
/** @return le JLabel contenant le score */
public JLabel getScoreLabel() {
return scoreLabel;
}
/** @return le score actuel */
public int getCurrentScore() {
return currentScore;
}
}

File diff suppressed because it is too large Load Diff