diff --git a/out/fr/iut/Projet/Action.class b/out/fr/iut/Projet/Action.class index 2aee067..995cf66 100644 Binary files a/out/fr/iut/Projet/Action.class and b/out/fr/iut/Projet/Action.class differ diff --git a/out/fr/iut/Projet/GameTimer$1.class b/out/fr/iut/Projet/GameTimer$1.class index a09165d..db0f216 100644 Binary files a/out/fr/iut/Projet/GameTimer$1.class and b/out/fr/iut/Projet/GameTimer$1.class differ diff --git a/out/fr/iut/Projet/GameTimer.class b/out/fr/iut/Projet/GameTimer.class index 6f35b7d..6fd3bce 100644 Binary files a/out/fr/iut/Projet/GameTimer.class and b/out/fr/iut/Projet/GameTimer.class differ diff --git a/out/fr/iut/Projet/Score.class b/out/fr/iut/Projet/Score.class new file mode 100644 index 0000000..65eb45c Binary files /dev/null and b/out/fr/iut/Projet/Score.class differ diff --git a/src/fr/iut/Projet/Action.java b/src/fr/iut/Projet/Action.java index b0e79ba..a99d081 100644 --- a/src/fr/iut/Projet/Action.java +++ b/src/fr/iut/Projet/Action.java @@ -6,116 +6,100 @@ 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}. + * 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 { - /** Fenêtre principale du jeu */ + private Score score; 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 + * 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(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 + // Initialisation initializeComponents(); layoutComponents(); + setupListeners(); - // Gestion de la saisie utilisateur - letterInputField.addActionListener(e -> handleGuess()); - - // Démarre le timer dès l'ouverture de la partie + // Démarre le timer et affiche la fenêtre gameTimer.start(); - - // Affiche la fenêtre du jeu gameFrame.setVisible(true); } - // ==================== Initialisation des composants ==================== + // ==================== Initialisation ==================== - /** - * 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 - */ + /** 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); + } - // Composant graphique pour dessiner le pendu + /** 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); - // 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 + /** 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 ==================== - /** - * 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 - */ + /** 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); @@ -130,15 +114,7 @@ public class Action { 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 - */ + /** 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(); @@ -146,51 +122,58 @@ public class Action { 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); + 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 : - * - vérifie la validité - * - met à jour le mot caché et lettres incorrectes - * - met à jour le pendu - * - termine la partie si nécessaire - */ + /** Traite la saisie d'une lettre par le joueur */ private void handleGuess() { String inputText = letterInputField.getText(); letterInputField.setText(""); @@ -200,12 +183,27 @@ public class Action { char guessedLetter = inputText.charAt(0); String message = game.guessLetter(guessedLetter); + updateScore(message); updateUI(); - if (game.isGameOver()) endGame(message); + if (game.isGameOver()) { + if (game.isWon()) { + score.increaseByWordFound(); + } + endGame(message); + } } - /** Vérifie que le texte saisi est une seule lettre */ + /** 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!"); @@ -214,20 +212,14 @@ public class Action { return true; } - /** Met à jour les labels et le dessin du pendu */ + /** 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 - * - met à jour le dessin du pendu en cas de victoire/défaite - * - affiche le message de fin - * - désactive le champ de saisie - */ + /** Termine la partie, arrête le timer et affiche le message */ private void endGame(String message) { gameTimer.stop(); @@ -235,26 +227,24 @@ public class Action { 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é en utilisant PlayButtonListener */ + + /** 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 une boîte de dialogue pour changer la difficulté, - * puis relance le jeu avec la nouvelle difficulté. - */ + /** 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é :", @@ -269,23 +259,12 @@ public class Action { 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; + 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); diff --git a/src/fr/iut/Projet/GameTimer.java b/src/fr/iut/Projet/GameTimer.java index d412290..6bfd00a 100644 --- a/src/fr/iut/Projet/GameTimer.java +++ b/src/fr/iut/Projet/GameTimer.java @@ -7,8 +7,8 @@ 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. + * 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 { @@ -21,9 +21,10 @@ public class GameTimer { /** Compteur de secondes écoulées */ private int secondsElapsed; - /** - * Constructeur : crée le label et initialise le timer. - */ + /** 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"); @@ -35,10 +36,20 @@ public class GameTimer { 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; @@ -65,4 +76,4 @@ public class GameTimer { public int getSecondsElapsed() { return secondsElapsed; } -} \ No newline at end of file +} diff --git a/src/fr/iut/Projet/Score.java b/src/fr/iut/Projet/Score.java new file mode 100644 index 0000000..7da2bbf --- /dev/null +++ b/src/fr/iut/Projet/Score.java @@ -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; + } +}