diff --git a/out/Affiche.class b/out/Affiche.class new file mode 100644 index 0000000..c56eac4 Binary files /dev/null and b/out/Affiche.class differ diff --git a/out/Mouse.class b/out/Mouse.class new file mode 100644 index 0000000..c279c32 Binary files /dev/null and b/out/Mouse.class differ diff --git a/out/fr/iut/Projet/Action.class b/out/fr/iut/Projet/Action.class index 654fe3b..e07c5a2 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/Affiche.class b/out/fr/iut/Projet/Affiche.class new file mode 100644 index 0000000..2f899f1 Binary files /dev/null and b/out/fr/iut/Projet/Affiche.class differ diff --git a/out/fr/iut/Projet/Random_word.class b/out/fr/iut/Projet/Random_word.class index 36fc137..c549677 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 5bcaf5e..c215214 100644 --- a/src/fr/iut/Projet/Action.java +++ b/src/fr/iut/Projet/Action.java @@ -4,29 +4,42 @@ import javax.swing.*; import java.awt.*; /** - * Classe qui représente l'interface graphique du jeu du pendu. - * Elle gère l'affichage du mot caché, des lettres incorrectes, des vies - * et permet de saisir des lettres. Un bouton permet de relancer le jeu. + * 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é, 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 et la fin de partie. + *

+ * + * @author + * @version 1.0 */ public class Action { - // Fenêtre principale du jeu + /** Fenêtre principale du jeu. */ private JFrame gameFrame; - // Labels pour afficher le mot, les lettres incorrectes et les vies + /** Label affichant le mot caché avec les lettres découvertes. */ private JLabel wordLabel; - private JLabel incorrectLettersLabel; - private JLabel livesLabel; - // Champ de saisie pour entrer une lettre + /** Label affichant la liste des lettres incorrectes. */ + private JLabel incorrectLettersLabel; + + /** Champ de texte permettant à l'utilisateur d'entrer une lettre. */ private JTextField letterInputField; - // Instance du jeu + /** Instance du jeu, contenant la logique (mot, vies, lettres, etc.). */ private Random_word game; + /** Composant graphique qui affiche le dessin du pendu. */ + private Affiche affiche; + /** - * Constructeur de la classe Action. - * Initialise le jeu, les composants graphiques et affiche la fenêtre. + * Constructeur de la classe {@code Action}. + *

+ * Initialise le jeu, crée les composants graphiques, met en place la mise en page + * et affiche la fenêtre du jeu. + *

*/ public Action() { game = new Random_word(); @@ -36,27 +49,25 @@ public class Action { gameFrame.setVisible(true); } - // ==================== Initialisation des composants ==================== + // ==================== Initialisation ==================== /** - * Initialise tous les composants graphiques : - * - Fenêtre principale - * - Labels pour le mot, les vies et les lettres incorrectes - * - Champ de saisie pour entrer les lettres + * Initialise tous les composants graphiques (labels, champs, boutons...). */ private void initializeComponents() { gameFrame = new JFrame("Hanging Man"); gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - gameFrame.setSize(600, 400); + gameFrame.setSize(700, 500); + + 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); - livesLabel = new JLabel("Lives: " + game.getLives()); - livesLabel.setFont(new Font("Arial", Font.BOLD, 20)); - livesLabel.setHorizontalAlignment(SwingConstants.CENTER); - incorrectLettersLabel = new JLabel("Incorrect letters: " + game.getIncorrectLetters()); incorrectLettersLabel.setFont(new Font("Arial", Font.PLAIN, 20)); incorrectLettersLabel.setHorizontalAlignment(SwingConstants.CENTER); @@ -65,119 +76,60 @@ public class Action { letterInputField.setFont(new Font("Arial", Font.PLAIN, 24)); } - // ==================== Layout des composants ==================== + // ==================== Mise en page ==================== /** - * Dispose les composants dans la fenêtre principale en utilisant GridBagLayout. - * Sépare la fenêtre en deux parties : le haut (mot et vies) et le bas (lettres incorrectes, saisie, bouton restart) + * Dispose les composants graphiques dans la fenêtre selon un {@link BorderLayout}. */ private void layoutComponents() { - JPanel mainPanel = new JPanel(new GridBagLayout()); - GridBagConstraints mainConstraints = new GridBagConstraints(); - mainConstraints.gridx = 0; - mainConstraints.fill = GridBagConstraints.BOTH; - mainConstraints.insets = new Insets(5, 5, 5, 5); + JPanel mainPanel = new JPanel(new BorderLayout()); - JPanel topPanel = createTopPanel(); - mainConstraints.gridy = 0; - mainConstraints.weighty = 3.0; - mainConstraints.weightx = 1.0; - mainPanel.add(topPanel, mainConstraints); + // --- panneau gauche : dessin du pendu --- + JPanel leftPanel = new JPanel(new BorderLayout()); + leftPanel.add(affiche, BorderLayout.CENTER); + mainPanel.add(leftPanel, BorderLayout.WEST); - JPanel bottomPanel = createBottomPanel(); - mainConstraints.gridy = 1; - mainConstraints.weighty = 1.0; - mainPanel.add(bottomPanel, mainConstraints); + // --- panneau droit : interface du jeu --- + 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); - gameFrame.add(mainPanel, BorderLayout.CENTER); - } + // Mot caché + gbc.gridy = 0; + gbc.weighty = 1.0; + rightPanel.add(wordLabel, gbc); - /** - * Crée le panneau supérieur avec : - * - Le label des vies (à gauche) - * - Le label du mot caché (à droite) - * @return JPanel configuré pour la partie supérieure - */ - private JPanel createTopPanel() { - JPanel topPanel = new JPanel(new GridBagLayout()); - - // Panel pour les vies - JPanel livesPanel = new JPanel(new GridBagLayout()); - GridBagConstraints livesConstraints = new GridBagConstraints(); - livesConstraints.anchor = GridBagConstraints.CENTER; - livesConstraints.fill = GridBagConstraints.NONE; - livesPanel.add(livesLabel, livesConstraints); - - // Panel pour le mot - JPanel wordPanel = new JPanel(new GridBagLayout()); - GridBagConstraints wordConstraints = new GridBagConstraints(); - wordConstraints.anchor = GridBagConstraints.CENTER; - wordConstraints.fill = GridBagConstraints.NONE; - wordPanel.add(wordLabel, wordConstraints); - - // Ajout des panels dans topPanel - GridBagConstraints leftConstraints = new GridBagConstraints(); - leftConstraints.gridx = 0; - leftConstraints.weightx = 0.5; - leftConstraints.weighty = 1.0; - leftConstraints.fill = GridBagConstraints.BOTH; - topPanel.add(livesPanel, leftConstraints); - - GridBagConstraints rightConstraints = new GridBagConstraints(); - rightConstraints.gridx = 1; - rightConstraints.weightx = 0.5; - rightConstraints.weighty = 1.0; - rightConstraints.fill = GridBagConstraints.BOTH; - topPanel.add(wordPanel, rightConstraints); - - return topPanel; - } - - /** - * Crée le panneau inférieur avec : - * - Le label des lettres incorrectes - * - Le champ de saisie pour entrer une lettre - * - Le bouton "Restart" en bas à droite - * @return JPanel configuré pour la partie inférieure - */ - private JPanel createBottomPanel() { - JPanel bottomPanel = new JPanel(); - bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS)); - - // Label des lettres incorrectes - incorrectLettersLabel.setAlignmentX(Component.CENTER_ALIGNMENT); - bottomPanel.add(incorrectLettersLabel); + // Lettres incorrectes + gbc.gridy = 1; + rightPanel.add(incorrectLettersLabel, gbc); // Champ de saisie - JLabel promptLabel = new JLabel("Enter a letter:"); - promptLabel.setFont(new Font("Arial", Font.PLAIN, 16)); - promptLabel.setAlignmentX(Component.CENTER_ALIGNMENT); - - JPanel inputRow = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5)); - inputRow.add(promptLabel); + gbc.gridy = 2; + JPanel inputRow = new JPanel(); + inputRow.add(new JLabel("Enter a letter:")); inputRow.add(letterInputField); - inputRow.setAlignmentX(Component.CENTER_ALIGNMENT); + rightPanel.add(inputRow, gbc); - bottomPanel.add(Box.createVerticalStrut(10)); - bottomPanel.add(inputRow); - - // Bouton "Restart" en bas à droite + // Bouton de redémarrage + gbc.gridy = 3; JButton restartButton = new JButton("Restart"); restartButton.addActionListener(new PlayButtonListener(gameFrame)); - JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); - buttonPanel.add(restartButton); + rightPanel.add(restartButton, gbc); - bottomPanel.add(Box.createVerticalStrut(10)); - bottomPanel.add(buttonPanel); - - return bottomPanel; + mainPanel.add(rightPanel, BorderLayout.CENTER); + gameFrame.add(mainPanel); } // ==================== Gestion du jeu ==================== /** * Gère la saisie d'une lettre par le joueur. - * Vérifie la validité de la lettre, met à jour l'affichage et termine le jeu si nécessaire. + *

+ * Vérifie la validité de la lettre, met à jour le jeu, l'affichage + * et teste si la partie est terminée. + *

*/ private void handleGuess() { String inputText = letterInputField.getText(); @@ -187,17 +139,17 @@ public class Action { char guessedLetter = inputText.charAt(0); String message = game.guessLetter(guessedLetter); + updateUI(); if (game.isGameOver()) endGame(message); } /** - * Vérifie si la saisie de l'utilisateur est valide : - * - Une seule lettre - * - Caractère alphabétique - * @param inputText texte saisi par l'utilisateur - * @return true si la saisie est valide, false sinon + * Vérifie que la saisie de l'utilisateur est une seule lettre valide. + * + * @param inputText texte saisi dans le champ de saisie + * @return {@code true} si la saisie est valide, {@code false} sinon */ private boolean isValidInput(String inputText) { if (inputText.length() != 1 || !Character.isLetter(inputText.charAt(0))) { @@ -208,24 +160,33 @@ public class Action { } /** - * Met à jour l'affichage des labels : - * - Mot caché - * - Lettres incorrectes - * - Nombre de vies restantes + * Met à jour les éléments de l'interface graphique : + * */ private void updateUI() { wordLabel.setText(game.getHiddenWord()); incorrectLettersLabel.setText("Incorrect letters: " + game.getIncorrectLetters()); - livesLabel.setText("Lives: " + game.getLives()); + affiche.setLives(game.getLives()); } /** - * Termine le jeu et affiche un message. - * Désactive le champ de saisie. - * @param message Message à afficher (victoire ou défaite) + * Termine la partie en affichant un message selon le résultat (victoire ou défaite) + * et empêche de nouvelles saisies. + * + * @param message message à afficher dans une boîte de dialogue */ private void endGame(String message) { + if (game.isWon()) { + affiche.setYouWin(true); + } else { + affiche.setLives(0); + } + JOptionPane.showMessageDialog(gameFrame, message); letterInputField.setEditable(false); } -} +} \ No newline at end of file diff --git a/src/fr/iut/Projet/Affiche.java b/src/fr/iut/Projet/Affiche.java index 63c9627..c8d06e5 100644 --- a/src/fr/iut/Projet/Affiche.java +++ b/src/fr/iut/Projet/Affiche.java @@ -1,20 +1,58 @@ +package fr.iut.Projet; + import javax.swing.*; import java.awt.*; +/** + * Classe graphique responsable du dessin du pendu dans le jeu. + *

+ * 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. + *

+ * + * @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. + * + * + * @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); } -} +} \ No newline at end of file diff --git a/src/fr/iut/Projet/Mouse.java b/src/fr/iut/Projet/Mouse.java deleted file mode 100644 index bb270fa..0000000 --- a/src/fr/iut/Projet/Mouse.java +++ /dev/null @@ -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 - } - } - } -} \ No newline at end of file diff --git a/src/fr/iut/Projet/Random_word.java b/src/fr/iut/Projet/Random_word.java index bc57dcd..adf9114 100644 --- a/src/fr/iut/Projet/Random_word.java +++ b/src/fr/iut/Projet/Random_word.java @@ -102,7 +102,12 @@ public class Random_word { } public boolean isWon() { - return secretWord.equals(String.valueOf(hiddenWord)); + for (char c : hiddenWord) { + if (c == '_') { + return false; + } + } + return true; } public String getSecretWord() {