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, affiche : * - le mot caché avec les lettres devinées, * - les lettres incorrectes, * - le dessin du pendu (via {@link Affiche}), * 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}. */ public class Action { /** Fenêtre principale du jeu */ private JFrame gameFrame; /** Label affichant le mot caché */ private JLabel wordLabel; /** Label affichant les lettres incorrectes */ private JLabel incorrectLettersLabel; /** Champ de texte pour saisir une lettre */ private JTextField letterInputField; /** Instance du jeu avec la logique (mot secret, lettres, vies, etc.) */ private Random_word game; /** Composant graphique qui dessine le pendu */ private Affiche affiche; /** Niveau de difficulté courant ("facile", "moyen", "difficile") */ 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. */ 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()); // Affiche la fenêtre 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 */ private void initializeComponents() { gameFrame = new JFrame("Hanging Man - " + difficulty); gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); gameFrame.setSize(700, 500); // Composant graphique pour 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)); } // ==================== 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 */ private void layoutComponents() { JPanel mainPanel = new JPanel(new BorderLayout()); // Panneau gauche : dessin du pendu JPanel leftPanel = new JPanel(new BorderLayout()); leftPanel.add(affiche, BorderLayout.CENTER); mainPanel.add(leftPanel, BorderLayout.WEST); // Panneau droit : interface du jeu (mot, lettres, saisie, boutons) 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é gbc.gridy = 0; gbc.weighty = 1.0; rightPanel.add(wordLabel, gbc); // Label des 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 de redémarrage gbc.gridy = 3; JButton restartButton = new JButton("Restart"); restartButton.addActionListener(e -> restartGame()); rightPanel.add(restartButton, gbc); // Bouton pour changer la difficulté gbc.gridy = 4; JButton changeDifficultyButton = new JButton("Changer la difficulté"); changeDifficultyButton.addActionListener(e -> showDifficultyDialog()); rightPanel.add(changeDifficultyButton, gbc); mainPanel.add(rightPanel, BorderLayout.CENTER); // Ajout du panneau principal à la fenêtre gameFrame.add(mainPanel); } // ==================== Gestion du jeu ==================== /** * Traite la saisie d'une lettre par l'utilisateur. * Met à jour l'état du jeu et l'affichage. */ private void handleGuess() { String inputText = letterInputField.getText(); letterInputField.setText(""); // efface le champ après saisie 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 */ 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 caché, des lettres incorrectes et du dessin du pendu. */ private void updateUI() { wordLabel.setText(game.getHiddenWord()); incorrectLettersLabel.setText("Incorrect letters: " + game.getIncorrectLetters()); affiche.setLives(game.getLives()); } /** * Termine la partie et affiche le message de résultat. * Désactive le champ de saisie. * * @param message message à afficher (victoire/défaite) */ private void endGame(String message) { if (game.isWon()) { affiche.setYouWin(true); } else { affiche.setLives(0); } JOptionPane.showMessageDialog(gameFrame, message); letterInputField.setEditable(false); } // ==================== Redémarrage ==================== /** * 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 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. */ private void showDifficultyDialog() { String[] options = {"Facile", "Moyen", "Difficile", "Hell"}; // Boîte de dialogue avec trois options int choice = JOptionPane.showOptionDialog( gameFrame, "Choisissez la difficulté :", "Changer la difficulté", JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0] ); // Si l'utilisateur a choisi une option 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; } // 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); } } }