diff --git a/Jeu_pendu/Back/Game.java b/Jeu_pendu/Back/Game.java index 6d9f40e..1e4354b 100644 --- a/Jeu_pendu/Back/Game.java +++ b/Jeu_pendu/Back/Game.java @@ -1,76 +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). - * Gère le mot, les lettres trouvées, et les conditions de 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; - public Game(String word, int maxErrors) { - this.word = word.toLowerCase(); - this.maxErrors = maxErrors; + /** 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 */ - public Result play(char letter) { - char c = Character.toLowerCase(letter); - if (all.contains(c)) return Result.ALREADY; - all.add(c); - if (word.indexOf(c) >= 0) { - correct.add(c); - return Result.HIT; - } else { - errors++; - return Result.MISS; + /** 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)); + } + + /** 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(' '); + /** 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); } - 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; + /** 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(); } - /** Vérifie si le joueur a perdu */ - public boolean isLose() { - return errors >= maxErrors; + /** Met à jour uniquement score + chrono */ + private void refreshStatsOnly() { + scoreLabel.setText("Score : " + game.getScore()); + timeLabel.setText("Temps : " + game.getElapsedSeconds() + "s"); } - /** Renvoie le 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; + /** Affiche une boîte de message */ + private void showMsg(String msg) { + JOptionPane.showMessageDialog(frame, msg); } -} \ No newline at end of file +}