diff --git a/out/fr/iut/Projet/Action.class b/out/fr/iut/Projet/Action.class index 2f0fd28..2aee067 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 new file mode 100644 index 0000000..a09165d Binary files /dev/null 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 new file mode 100644 index 0000000..6f35b7d Binary files /dev/null and b/out/fr/iut/Projet/GameTimer.class differ diff --git a/out/fr/iut/Projet/Random_word.class b/out/fr/iut/Projet/Random_word.class index 5996aa7..4c8f64c 100644 Binary files a/out/fr/iut/Projet/Random_word.class and b/out/fr/iut/Projet/Random_word.class differ diff --git a/src/fr/iut/Projet/Action.java b/src/fr/iut/Projet/Action.java index bdcfb91..b0e79ba 100644 --- a/src/fr/iut/Projet/Action.java +++ b/src/fr/iut/Projet/Action.java @@ -6,42 +6,49 @@ import java.awt.*; /** * Classe principale qui gère l'interface graphique du jeu du pendu. * - * Cette classe crée la fenêtre du jeu, affiche : + * 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, la fin de partie, - * le redémarrage et le changement de difficulté en utilisant {@link PlayButtonListener}. + * 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é */ + /** Label affichant le mot caché avec les lettres découvertes */ private JLabel wordLabel; - /** Label affichant les lettres incorrectes */ + /** Label affichant les lettres incorrectes devinées par le joueur */ private JLabel incorrectLettersLabel; /** Champ de texte pour saisir une lettre */ private JTextField letterInputField; - /** Instance du jeu avec la logique (mot secret, lettres, vies, etc.) */ + /** Instance de la logique du jeu (mot secret, lettres, vies, etc.) */ private Random_word game; - /** Composant graphique qui dessine le pendu */ + /** Composant graphique représentant le pendu */ private Affiche affiche; - /** Niveau de difficulté courant ("facile", "moyen", "difficile") */ + /** 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 de la classe Action. - * Initialise le jeu avec la difficulté choisie, crée et dispose les composants. - * - * @param difficulty Niveau de difficulté pour le mot à deviner. + * 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; @@ -56,7 +63,10 @@ public class Action { // Gestion de la saisie utilisateur letterInputField.addActionListener(e -> handleGuess()); - // Affiche la fenêtre + // Démarre le timer dès l'ouverture de la partie + gameTimer.start(); + + // Affiche la fenêtre du jeu gameFrame.setVisible(true); } @@ -64,17 +74,18 @@ public class Action { /** * Initialise tous les composants graphiques du jeu : - * - fenêtre principale - * - dessin du pendu - * - labels pour le mot et les lettres incorrectes - * - champ de saisie + * - 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 le pendu + // Composant graphique pour dessiner le pendu affiche = new Affiche(); affiche.setPreferredSize(new Dimension(350, 400)); affiche.setBackground(Color.WHITE); @@ -93,37 +104,54 @@ public class Action { // 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 ==================== /** - * Dispose tous les composants graphiques dans la fenêtre. - * Utilise un BorderLayout principal avec : - * - panneau gauche pour le dessin du pendu - * - panneau droit pour les interactions utilisateur + * 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); + } - // Panneau gauche : dessin du pendu + /** Crée le panneau gauche avec le dessin du pendu */ + private JPanel createLeftPanel() { JPanel leftPanel = new JPanel(new BorderLayout()); leftPanel.add(affiche, BorderLayout.CENTER); - mainPanel.add(leftPanel, BorderLayout.WEST); + return leftPanel; + } - // Panneau droit : interface du jeu (mot, lettres, saisie, boutons) + /** + * 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); - // Label du mot caché + // Mot caché gbc.gridy = 0; gbc.weighty = 1.0; rightPanel.add(wordLabel, gbc); - // Label des lettres incorrectes + // Lettres incorrectes gbc.gridy = 1; rightPanel.add(incorrectLettersLabel, gbc); @@ -134,52 +162,50 @@ public class Action { inputRow.add(letterInputField); rightPanel.add(inputRow, gbc); - // Bouton de redémarrage + // Bouton restart gbc.gridy = 3; JButton restartButton = new JButton("Restart"); restartButton.addActionListener(e -> restartGame()); rightPanel.add(restartButton, gbc); - // Bouton pour changer la difficulté + // Bouton changement de difficulté gbc.gridy = 4; JButton changeDifficultyButton = new JButton("Changer la difficulté"); changeDifficultyButton.addActionListener(e -> showDifficultyDialog()); rightPanel.add(changeDifficultyButton, gbc); - mainPanel.add(rightPanel, BorderLayout.CENTER); + // Timer en haut à droite + gbc.gridy = 5; + gbc.anchor = GridBagConstraints.NORTHEAST; + rightPanel.add(gameTimer.getTimerLabel(), gbc); - // Ajout du panneau principal à la fenêtre - gameFrame.add(mainPanel); + return rightPanel; } - // ==================== Gestion du jeu ==================== + // ==================== Gestion des actions ==================== /** - * Traite la saisie d'une lettre par l'utilisateur. - * Met à jour l'état du jeu et l'affichage. + * 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(""); // efface le champ après saisie + letterInputField.setText(""); if (!isValidInput(inputText)) return; char guessedLetter = inputText.charAt(0); String message = game.guessLetter(guessedLetter); - // Mise à jour de l'interface updateUI(); - // Si la partie est terminée, affiche le résultat if (game.isGameOver()) endGame(message); } - /** - * Vérifie que l'utilisateur a saisi une seule lettre valide. - * - * @param inputText texte saisi - * @return true si la saisie est valide - */ + /** 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!"); @@ -188,9 +214,7 @@ public class Action { return true; } - /** - * Met à jour l'affichage du mot caché, des lettres incorrectes et du dessin du pendu. - */ + /** Met à jour les labels et le dessin du pendu */ private void updateUI() { wordLabel.setText(game.getHiddenWord()); incorrectLettersLabel.setText("Incorrect letters: " + game.getIncorrectLetters()); @@ -198,12 +222,15 @@ public class Action { } /** - * Termine la partie et affiche le message de résultat. - * Désactive le champ de saisie. - * - * @param message message à afficher (victoire/défaite) + * 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 { @@ -214,30 +241,20 @@ public class Action { letterInputField.setEditable(false); } - // ==================== Redémarrage ==================== - - /** - * Redémarre le jeu avec la même difficulté en utilisant PlayButtonListener. - */ + /** Redémarre le jeu avec la même difficulté en utilisant PlayButtonListener */ private void restartGame() { - gameFrame.dispose(); // ferme la fenêtre actuelle - - // Crée un JFrame temporaire pour utiliser PlayButtonListener + gameFrame.dispose(); JFrame tempFrame = new JFrame(); new PlayButtonListener(tempFrame, difficulty).actionPerformed(null); - // tempFrame ne sera jamais affiché, il sert juste à passer la référence } - // ==================== Changement de difficulté ==================== - /** - * Affiche une boîte de dialogue pour choisir une nouvelle difficulté - * et relance une partie avec cette difficulté en utilisant PlayButtonListener. + * 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"}; - // Boîte de dialogue avec trois options int choice = JOptionPane.showOptionDialog( gameFrame, "Choisissez la difficulté :", @@ -249,7 +266,6 @@ public class Action { options[0] ); - // Si l'utilisateur a choisi une option if (choice >= 0) { String newDifficulty; switch (choice) { @@ -270,10 +286,7 @@ public class Action { break; } - // Ferme la fenêtre actuelle gameFrame.dispose(); - - // Crée un JFrame temporaire pour utiliser PlayButtonListener 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 new file mode 100644 index 0000000..d412290 --- /dev/null +++ b/src/fr/iut/Projet/GameTimer.java @@ -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; + } +} \ No newline at end of file