From ee85d6f8f499e86f7375459a6c931f35730c1649 Mon Sep 17 00:00:00 2001 From: Jannaire Date: Wed, 8 Oct 2025 15:16:50 +0200 Subject: [PATCH] ajout score --- Jeu_pendu/Back/Game.java | 255 +++++++++++++++++++++------------------ 1 file changed, 139 insertions(+), 116 deletions(-) diff --git a/Jeu_pendu/Back/Game.java b/Jeu_pendu/Back/Game.java index cfc87c1..1e4354b 100644 --- a/Jeu_pendu/Back/Game.java +++ b/Jeu_pendu/Back/Game.java @@ -1,132 +1,155 @@ -package back; +package front; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import back.*; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; /** - * Logique principale du jeu du pendu (back). - * Ajoute un score et un chronomètre. - * - * Règles de score (simples) : - * - Lettre correcte : +10 points - * - Lettre incorrecte: -5 points (le score ne descend pas sous 0) - * - Bonus victoire : + (restant * 10) + bonus temps - * * bonus temps = max(0, 60 - secondes) * 2 (jusqu'à 120 pts si < 60s) - * - Défaite : pas de bonus - * - * Chronomètre : - * - Démarre à la création de la partie - * - S'arrête définitivement à la fin (victoire/défaite) + * Interface graphique du jeu du pendu. + * (Toutes les méthodes ≤ 50 lignes) */ -public class Game { - private final String word; - private final Set correct = new HashSet<>(); - private final Set all = new HashSet<>(); - private final int maxErrors; - private int errors; +public class GameUI { + private JFrame frame; + private JLabel imgLabel, wordLabel, triedLabel, scoreLabel, timeLabel; + private JTextField input; + private JButton tryBtn, newGameBtn; + private Game game; + private String currentWord; + private Timer timer; - // Score & chrono - private int score = 0; - private long startNano; // début de partie (System.nanoTime) - private long endNano = -1L; // fin (sinon -1 = en cours) - - public Game(String word, int maxErrors) { - this.word = word.toLowerCase(); - this.maxErrors = maxErrors; - this.startNano = System.nanoTime(); // démarre le chrono à la création + /** Lance la fenêtre et démarre une partie */ + public void show() { + setupWindow(); + setupLayout(); + setupActions(); + startNewGame(); + frame.setVisible(true); } - /** Tente une lettre et renvoie le résultat + ajuste le score */ - public Result play(char letter) { - char c = Character.toLowerCase(letter); - if (all.contains(c)) return Result.ALREADY; + /** Crée la fenêtre principale */ + private void setupWindow() { + frame = new JFrame("Jeu du Pendu"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setSize(560, 560); + frame.setLocationRelativeTo(null); + frame.setLayout(new BorderLayout(12, 12)); + } - all.add(c); - if (word.indexOf(c) >= 0) { - correct.add(c); - addScore(10); - // Si la lettre trouvée fait gagner immédiatement, on finalise ici - if (isWin()) end(true); - return Result.HIT; - } else { - addScore(-5); - if (isLose()) end(false); - return Result.MISS; + /** Construit les composants et le layout */ + private void setupLayout() { + imgLabel = new JLabel("", SwingConstants.CENTER); + frame.add(imgLabel, BorderLayout.CENTER); + + wordLabel = new JLabel("Mot : "); + triedLabel = new JLabel("Lettres essayées : "); + scoreLabel = new JLabel("Score : 0"); + timeLabel = new JLabel("Temps : 0s"); + + JPanel top = new JPanel(new GridLayout(2, 1)); + top.add(buildTopLine(wordLabel, scoreLabel)); + top.add(buildTopLine(triedLabel, timeLabel)); + frame.add(top, BorderLayout.NORTH); + + JPanel bottom = new JPanel(new BorderLayout(8, 8)); + JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + input = new JTextField(5); + tryBtn = new JButton("Essayer"); + newGameBtn = new JButton("Nouvelle partie"); + inputPanel.add(new JLabel("Lettre :")); + inputPanel.add(input); + inputPanel.add(tryBtn); + bottom.add(inputPanel, BorderLayout.WEST); + bottom.add(newGameBtn, BorderLayout.EAST); + frame.add(bottom, BorderLayout.SOUTH); + } + + /** Crée une ligne du haut avec 2 labels */ + private JPanel buildTopLine(JLabel left, JLabel right) { + JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + panel.add(left); + panel.add(Box.createHorizontalStrut(24)); + panel.add(right); + return panel; + } + + /** Ajoute les actions et le timer */ + private void setupActions() { + tryBtn.addActionListener(this::onTry); + input.addActionListener(this::onTry); + newGameBtn.addActionListener(e -> startNewGame()); + timer = new Timer(1000, e -> refreshStatsOnly()); + } + + /** Démarre une nouvelle partie */ + private void startNewGame() { + currentWord = Words.random(); + game = new Game(currentWord, 7); + input.setText(""); + input.requestFocusInWindow(); + if (!timer.isRunning()) timer.start(); + refreshUI(); + } + + /** Gère le clic ou l'appui sur Entrée */ + private void onTry(ActionEvent e) { + String text = input.getText(); + if (!Check.isLetter(text)) { + showMsg("Tape une seule lettre (A-Z)."); + input.requestFocusInWindow(); + input.selectAll(); + return; + } + Result res = game.play(Character.toLowerCase(text.charAt(0))); + handleResult(res); + input.setText(""); + refreshUI(); + checkEnd(); + } + + /** Réagit selon le résultat d'une tentative */ + private void handleResult(Result res) { + switch (res) { + case ALREADY: + showMsg("Lettre déjà utilisée."); + break; + case HIT: + case MISS: + break; // rien, juste refresh } } - /** Retourne le mot masqué avec les lettres trouvées */ - public String maskedWord() { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < word.length(); i++) { - char c = word.charAt(i); - if (!Character.isLetter(c)) sb.append(c); - else if (correct.contains(c)) sb.append(c); - else sb.append('_'); - if (i < word.length() - 1) sb.append(' '); - } - return sb.toString(); - } - - /** Vérifie si le joueur a gagné */ - public boolean isWin() { - for (int i = 0; i < word.length(); i++) { - char c = word.charAt(i); - if (Character.isLetter(c) && !correct.contains(c)) return false; - } - return true; - } - - /** Vérifie si le joueur a perdu */ - public boolean isLose() { - return errors >= maxErrors; - } - - /** Nombre d'erreurs actuelles */ - public int getErrors() { return errors; } - - /** Liste les lettres déjà essayées */ - public List triedLetters() { - List sorted = new ArrayList<>(all); - sorted.sort(Character::compareTo); - List out = new ArrayList<>(); - for (Character ch : sorted) out.add(String.valueOf(ch)); - return out; - } - - // -Score & Chrono - - /** Retourne le score courant */ - public int getScore() { return score; } - - /** Secondes écoulées depuis le début (si finie, temps figé) */ - public long getElapsedSeconds() { - long end = (endNano > 0L) ? endNano : System.nanoTime(); - long deltaNs = end - startNano; - if (deltaNs < 0) deltaNs = 0; - return deltaNs / 1_000_000_000L; - } - - /** Termine la partie (victoire/défaite) et applique le bonus si gagné */ - public void end(boolean win) { - if (endNano > 0L) return; // déjà terminé - endNano = System.nanoTime(); - if (win) { - int remaining = Math.max(0, maxErrors - errors); - int timeBonus = (int) Math.max(0, 60 - getElapsedSeconds()) * 2; - addScore(remaining * 10 + timeBonus); + /** Vérifie si la partie est finie */ + private void checkEnd() { + if (game.isWin() || game.isLose()) { + timer.stop(); + game.end(game.isWin()); + String msg = (game.isWin() ? "Bravo !" : "Perdu !") + + " Le mot était : " + currentWord + + "\nScore final : " + game.getScore() + + "\nTemps : " + game.getElapsedSeconds() + "s"; + showMsg(msg); } } - // --- utilitaires privés --- - private void addScore(int delta) { - if (delta < 0) { - // lettre ratée => +1 erreur - errors++; - } - score += delta; - if (score < 0) score = 0; + /** Met à jour tout l'affichage */ + private void refreshUI() { + imgLabel.setIcon(Gallows.icon(game.getErrors())); + wordLabel.setText("Mot : " + game.maskedWord()); + triedLabel.setText("Lettres essayées : " + String.join(", ", game.triedLetters())); + refreshStatsOnly(); + frame.repaint(); + } + + /** Met à jour uniquement score + chrono */ + private void refreshStatsOnly() { + scoreLabel.setText("Score : " + game.getScore()); + timeLabel.setText("Temps : " + game.getElapsedSeconds() + "s"); + } + + /** Affiche une boîte de message */ + private void showMsg(String msg) { + JOptionPane.showMessageDialog(frame, msg); } }