比較提交
	
		
			11 次程式碼提交
		
	
	
		
			485b63357e
			...
			64108a95e9
		
	
	| 作者 | SHA1 | 日期 | |
|---|---|---|---|
| 64108a95e9 | |||
| c0d2e0e5e2 | |||
| 78333b0c32 | |||
| 5b7f341011 | |||
| 2c611bc6fd | |||
| 8b079bc103 | |||
| 790c3faff2 | |||
| 3f8a86866a | |||
| ee85d6f8f4 | |||
| d2dd0bb982 | |||
| ca5c12a7ba | 
| @@ -7,7 +7,18 @@ import java.util.Set; | ||||
|  | ||||
| /** | ||||
|  * Logique principale du jeu du pendu (back). | ||||
|  * Gère le mot, les lettres trouvées, et les conditions de victoire/défaite. | ||||
|  * 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   :  nombre d'erreure restante sur 6 fois 10  | ||||
|  *  - Bonus temps      : Chaque seconde restante avant 60s vaut 2 points si tu met plus de 60 secondes tu n'a pas de bonus  | ||||
|  *  - 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) | ||||
|  */ | ||||
| public class Game { | ||||
|     private final String word; | ||||
| @@ -16,21 +27,32 @@ public class Game { | ||||
|     private final int maxErrors; | ||||
|     private int errors; | ||||
|  | ||||
|     // --- 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 | ||||
|     } | ||||
|  | ||||
| /** Tente une lettre et renvoie le résultat */ | ||||
|     /** 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; | ||||
|  | ||||
|         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 { | ||||
|             errors++; | ||||
|             addScore(-5); | ||||
|             if (isLose()) end(false); | ||||
|             return Result.MISS; | ||||
|         } | ||||
|     } | ||||
| @@ -62,7 +84,7 @@ public class Game { | ||||
|         return errors >= maxErrors; | ||||
|     } | ||||
|  | ||||
|     /** Renvoie le nombre d'erreurs actuelles */ | ||||
|     /** Nombre d'erreurs actuelles */ | ||||
|     public int getErrors() { return errors; } | ||||
|  | ||||
|     /** Liste les lettres déjà essayées */ | ||||
| @@ -73,4 +95,38 @@ public class Game { | ||||
|         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); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // --- utilitaires privés --- | ||||
|     private void addScore(int delta) { | ||||
|         if (delta < 0) { | ||||
|             // lettre ratée => +1 erreur | ||||
|             errors++; | ||||
|         } | ||||
|         score += delta; | ||||
|         if (score < 0) score = 0; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -82,4 +82,15 @@ public class Words { | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     /* Retourne la liste complète des mots disponibles */ | ||||
|     public static List<String> all() { | ||||
|         ensureLoaded(); | ||||
|         return new ArrayList<>(CACHE); | ||||
|     } | ||||
|  | ||||
|     /* Petit utilitaire pour afficher un mot masqué dans les messages */ | ||||
|     public static String hiddenWord(Game g) { | ||||
|         return g.maskedWord().replace(' ', '_'); | ||||
|     } | ||||
| } | ||||
| @@ -1,125 +1,190 @@ | ||||
| package front; | ||||
|  | ||||
| import back.*; | ||||
|  | ||||
| import javax.swing.*; | ||||
| import java.awt.*; | ||||
| import java.awt.event.ActionEvent; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * Interface graphique (Swing) du jeu du pendu. | ||||
|  * - Affiche une image différente à chaque erreur. | ||||
|  * - Champ de saisie pour entrer une lettre. | ||||
|  * - Texte pour le mot masqué et les lettres essayées. | ||||
|  * Interface graphique du jeu du pendu avec gestion des difficultés. | ||||
|  * - Niveau Facile : mots de moins de 8 lettres | ||||
|  * - Niveau Moyen : mots de 8 lettres ou plus | ||||
|  * - Niveau Difficile : deux mots à deviner à la suite (un court + un long) | ||||
|  * Toutes les méthodes ≤ 50 lignes. | ||||
|  */ | ||||
| public class GameUI { | ||||
|     private JFrame frame; | ||||
|     private JLabel imgLabel; | ||||
|     private JLabel wordLabel; | ||||
|     private JLabel triedLabel; | ||||
|     private JLabel imgLabel, wordLabel, triedLabel, scoreLabel, timeLabel; | ||||
|     private JTextField input; | ||||
|     private JButton tryBtn; | ||||
|     private JButton newGameBtn; | ||||
|     private JButton tryBtn, quitBtn; | ||||
|  | ||||
|     private Game game; | ||||
|     private String currentWord; | ||||
|     private List<String> words; | ||||
|     private int index = 0; | ||||
|     private int level; | ||||
|     private String currentWord = ""; | ||||
|     private Timer timer; | ||||
|  | ||||
|     /** Affiche la fenêtre principale */ | ||||
|     /** Constructeur : reçoit la difficulté (1, 2 ou 3) */ | ||||
|     public GameUI(int level) { | ||||
|         this.level = level; | ||||
|     } | ||||
|  | ||||
|     /** Affiche la fenêtre et lance la partie (ou séquence) */ | ||||
|     public void show() { | ||||
|         setupUI(); | ||||
|         startNewGame(); | ||||
|         setupWindow(); | ||||
|         setupLayout(); | ||||
|         setupActions(); | ||||
|         prepareWords(); | ||||
|         startRound(); | ||||
|         frame.setVisible(true); | ||||
|     } | ||||
|  | ||||
|     /** Initialise les composants Swing */ | ||||
|     private void setupUI() { | ||||
|     /** Prépare la liste des mots selon la difficulté choisie */ | ||||
|     private void prepareWords() { | ||||
|         words = new ArrayList<String>(); | ||||
|         List<String> all = Words.all(); | ||||
|  | ||||
|         if (level == 1) { // mots courts | ||||
|             for (String w : all) if (w.length() < 8) words.add(w); | ||||
|         } else if (level == 2) { // mots longs | ||||
|             for (String w : all) if (w.length() >= 8) words.add(w); | ||||
|         } else if (level == 3) { // un court + un long | ||||
|             String shortW = null, longW = null; | ||||
|             for (String w : all) { | ||||
|                 if (shortW == null && w.length() < 8) shortW = w; | ||||
|                 if (longW == null && w.length() >= 8) longW = w; | ||||
|                 if (shortW != null && longW != null) break; | ||||
|             } | ||||
|             if (shortW != null) words.add(shortW); | ||||
|             if (longW != null) words.add(longW); | ||||
|         } | ||||
|  | ||||
|         if (words.isEmpty()) words.add(Words.random()); // fallback si rien | ||||
|     } | ||||
|  | ||||
|     /** Crée la fenêtre principale */ | ||||
|     private void setupWindow() { | ||||
|         frame = new JFrame("Jeu du Pendu"); | ||||
|         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | ||||
|         frame.setSize(520, 520); | ||||
|         frame.setSize(560, 560); | ||||
|         frame.setLocationRelativeTo(null); | ||||
|         frame.setLayout(new BorderLayout(12, 12)); | ||||
|     } | ||||
|  | ||||
|         // Image du pendu | ||||
|     /** Construit la mise en page et les composants */ | ||||
|     private void setupLayout() { | ||||
|         imgLabel = new JLabel("", SwingConstants.CENTER); | ||||
|         frame.add(imgLabel, BorderLayout.CENTER); | ||||
|  | ||||
|         // Panneau bas: saisie + actions | ||||
|         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"); | ||||
|         quitBtn = new JButton("Quitter"); | ||||
|         inputPanel.add(new JLabel("Lettre :")); | ||||
|         inputPanel.add(input); | ||||
|         inputPanel.add(tryBtn); | ||||
|  | ||||
|         newGameBtn = new JButton("Nouvelle partie"); | ||||
|         bottom.add(inputPanel, BorderLayout.WEST); | ||||
|         bottom.add(newGameBtn, BorderLayout.EAST); | ||||
|         bottom.add(quitBtn, BorderLayout.EAST); | ||||
|         frame.add(bottom, BorderLayout.SOUTH); | ||||
|  | ||||
|         // Panneau haut: mot + lettres essayées | ||||
|         JPanel top = new JPanel(); | ||||
|         top.setLayout(new BoxLayout(top, BoxLayout.Y_AXIS)); | ||||
|         wordLabel = new JLabel("Mot : "); | ||||
|         triedLabel = new JLabel("Lettres essayées : "); | ||||
|         wordLabel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); | ||||
|         triedLabel.setBorder(BorderFactory.createEmptyBorder(0, 8, 8, 8)); | ||||
|         top.add(wordLabel); | ||||
|         top.add(triedLabel); | ||||
|         frame.add(top, BorderLayout.NORTH); | ||||
|  | ||||
|         // Actions | ||||
|         tryBtn.addActionListener(this::onTry); | ||||
|         input.addActionListener(this::onTry); | ||||
|         newGameBtn.addActionListener(e -> startNewGame()); | ||||
|     } | ||||
|  | ||||
|     /** Démarre une nouvelle partie */ | ||||
|     private void startNewGame() { | ||||
|         currentWord = Words.random(); | ||||
|     /** Construit une ligne (label gauche + espace + label droit) */ | ||||
|     private JPanel buildTopLine(JLabel left, JLabel right) { | ||||
|         JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT)); | ||||
|         p.add(left); | ||||
|         p.add(Box.createHorizontalStrut(24)); | ||||
|         p.add(right); | ||||
|         return p; | ||||
|     } | ||||
|  | ||||
|     /** Branche les actions + timer */ | ||||
|     private void setupActions() { | ||||
|         tryBtn.addActionListener(this::onTry); | ||||
|         input.addActionListener(this::onTry); | ||||
|         quitBtn.addActionListener(e -> frame.dispose()); | ||||
|         timer = new Timer(1000, e -> refreshStatsOnly()); | ||||
|     } | ||||
|  | ||||
|     /** Démarre un nouveau mot (ou termine au niveau 3) */ | ||||
|     private void startRound() { | ||||
|         if (index >= words.size()) { | ||||
|             showMsg("Niveau terminé !"); | ||||
|             frame.dispose(); | ||||
|             return; | ||||
|         } | ||||
|         currentWord = words.get(index++); | ||||
|         game = new Game(currentWord, 7); | ||||
|         input.setText(""); | ||||
|         input.requestFocusInWindow(); | ||||
|         if (!timer.isRunning()) timer.start(); | ||||
|         refreshUI(); | ||||
|     } | ||||
|  | ||||
|     /** Gère le clic sur "Essayer" ou Entrée dans le champ */ | ||||
|     /** Tente une lettre (clic bouton ou Entrée) */ | ||||
|     private void onTry(ActionEvent e) { | ||||
|         String text = input.getText(); | ||||
|         if (!Check.isLetter(text)) { | ||||
|             JOptionPane.showMessageDialog(frame, "Tape une seule lettre (A-Z)."); | ||||
|             showMsg("Tape une seule lettre (A-Z)."); | ||||
|             input.requestFocusInWindow(); | ||||
|             input.selectAll(); | ||||
|             return; | ||||
|         } | ||||
|         char c = Character.toLowerCase(text.charAt(0)); | ||||
|         Result res = game.play(c); | ||||
|  | ||||
|         switch (res) { | ||||
|             case ALREADY: JOptionPane.showMessageDialog(frame, "Lettre déjà utilisée."); | ||||
|             break; | ||||
|             case HIT: | ||||
|             break; | ||||
|             case MISS: | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         Result res = game.play(Character.toLowerCase(text.charAt(0))); | ||||
|         if (res == Result.ALREADY) showMsg("Lettre déjà utilisée."); | ||||
|         input.setText(""); | ||||
|         refreshUI(); | ||||
|         checkEnd(); | ||||
|     } | ||||
|  | ||||
|         if (game.isWin()) { | ||||
|             refreshUI(); | ||||
|             JOptionPane.showMessageDialog(frame, "Bravo ! Le mot était : " + currentWord); | ||||
|         } else if (game.isLose()) { | ||||
|             refreshUI(); | ||||
|             JOptionPane.showMessageDialog(frame, "Perdu ! Le mot était : " + currentWord); | ||||
|     /** Vérifie la fin du mot et enchaîne si besoin (niveau 3) */ | ||||
|     private void checkEnd() { | ||||
|         if (!(game.isWin() || game.isLose())) return; | ||||
|  | ||||
|         timer.stop(); | ||||
|         game.end(game.isWin()); | ||||
|         String verdict = game.isWin() ? "Bravo !" : "Perdu !"; | ||||
|         String msg = verdict + " Le mot était : " + currentWord | ||||
|                 + "\nScore : " + game.getScore() | ||||
|                 + "\nTemps : " + game.getElapsedSeconds() + "s"; | ||||
|         showMsg(msg); | ||||
|  | ||||
|         if (level == 3 && index < words.size()) { | ||||
|             startRound(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** Met à jour l'image et les textes selon l'état courant */ | ||||
|     /** Rafraîchit image + textes + stats */ | ||||
|     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(); | ||||
|     } | ||||
|  | ||||
|     /** Rafraîchit uniquement score + chrono */ | ||||
|     private void refreshStatsOnly() { | ||||
|         scoreLabel.setText("Score : " + game.getScore()); | ||||
|         timeLabel.setText("Temps : " + game.getElapsedSeconds() + "s"); | ||||
|     } | ||||
|  | ||||
|     /** Affiche un message */ | ||||
|     private void showMsg(String msg) { | ||||
|         JOptionPane.showMessageDialog(frame, msg); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										50
									
								
								Jeu_pendu/Front/MenuUI.java
									
									
									
									
									
										一般檔案
									
								
							
							
						
						
									
										50
									
								
								Jeu_pendu/Front/MenuUI.java
									
									
									
									
									
										一般檔案
									
								
							| @@ -0,0 +1,50 @@ | ||||
| package front; | ||||
|  | ||||
| import javax.swing.*; | ||||
| import java.awt.*; | ||||
|  | ||||
| /* | ||||
| * Menu de démarrage du jeu du pendu. | ||||
| * Permet de choisir la difficulté (facile, moyen ou difficile). | ||||
| */ | ||||
| public class MenuUI { | ||||
|     private JFrame frame; | ||||
|  | ||||
|     /** | ||||
|      * Interface graphique de la page d'accueil du jeu du pendu. | ||||
|      */ | ||||
|     public void show() { | ||||
|         frame = new JFrame("Jeu du Pendu - Sélection de la difficulté"); | ||||
|         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | ||||
|         frame.setSize(400, 300); | ||||
|         frame.setLocationRelativeTo(null); | ||||
|         frame.setLayout(new BorderLayout(12, 12)); | ||||
|  | ||||
|         JLabel title = new JLabel("Choisis une difficulté", SwingConstants.CENTER); | ||||
|         title.setFont(new Font("Arial", Font.BOLD, 20)); | ||||
|         frame.add(title, BorderLayout.NORTH); | ||||
|  | ||||
|         JPanel buttons = new JPanel(new GridLayout(3, 1, 10, 10)); | ||||
|         JButton easyBtn = new JButton("Niveau Facile"); | ||||
|         JButton mediumBtn = new JButton("Niveau Moyen"); | ||||
|         JButton hardBtn = new JButton("Niveau Difficile"); | ||||
|  | ||||
|         buttons.add(easyBtn); | ||||
|         buttons.add(mediumBtn); | ||||
|         buttons.add(hardBtn); | ||||
|         frame.add(buttons, BorderLayout.CENTER); | ||||
|  | ||||
|         easyBtn.addActionListener(e -> startGame(1)); | ||||
|         mediumBtn.addActionListener(e -> startGame(2)); | ||||
|         hardBtn.addActionListener(e -> startGame(3)); | ||||
|  | ||||
|         frame.setVisible(true); | ||||
|     } | ||||
|  | ||||
|     /* Lance le jeu avec le niveau choisi */ | ||||
|     private void startGame(int level) { | ||||
|         frame.dispose(); // ferme le menu | ||||
|         GameUI ui = new GameUI(level); | ||||
|         ui.show(); | ||||
|     } | ||||
| } | ||||
| @@ -1,17 +1,16 @@ | ||||
| package main; | ||||
|  | ||||
| import front.GameUI; | ||||
| import front.MenuUI; | ||||
|  | ||||
| /** | ||||
|  * Point d'entrée du programme. | ||||
|  * Lance l'interface graphique du jeu du pendu. | ||||
|  */ | ||||
| * Point d'entrée du programme. | ||||
| * Affiche le menu de sélection avant de lancer le jeu. | ||||
| */ | ||||
| public class Main { | ||||
|     public static void main(String[] args) { | ||||
|         // Démarre l'UI Swing sur le thread de l'EDT | ||||
|         javax.swing.SwingUtilities.invokeLater(() -> { | ||||
|             GameUI ui = new GameUI(); | ||||
|             ui.show(); | ||||
|             MenuUI menu = new MenuUI(); | ||||
|             menu.show(); | ||||
|         }); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										
											二進制
										
									
								
								TD3 - DEV5.1.pdf
									
									
									
									
									
								
							
							
						
						
									
										
											二進制
										
									
								
								TD3 - DEV5.1.pdf
									
									
									
									
									
								
							
										
											未顯示二進位檔案。
										
									
								
							
		新增問題並參考
	
	封鎖使用者