比較提交
	
		
			14 次程式碼提交
		
	
	
		
			e6e0d4cf71
			...
			77b3158262
		
	
	| 作者 | SHA1 | 日期 | |
|---|---|---|---|
| 77b3158262 | |||
| 0f7c1f6b71 | |||
| 9d7c681ca3 | |||
| a3627d9023 | |||
| 7206dca3ef | |||
| 0fa7ec527f | |||
| f7aecb038d | |||
| 62f6f94be7 | |||
| 90874a3296 | |||
| 49e32b316e | |||
| 06daa4e478 | |||
| 35c9fcd873 | |||
| ba7e16dc64 | |||
| 721543075c | 
							
								
								
									
										5
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								Makefile
									
									
									
									
									
								
							| @@ -21,7 +21,7 @@ CLASSFILES = Pendu.class \ | ||||
| $(OUT)Pendu.class : $(IN)Pendu.java $(OUT)Partie.class $(OUT)Fenetre.class | ||||
| 	$(JC) $(JCFLAGS) $< | ||||
|  | ||||
| $(OUT)Partie.class : $(IN)Partie.java | ||||
| $(OUT)Partie.class : $(IN)Partie.java $(OUT)Mots.class | ||||
| 	$(JC) $(JCFLAGS) $< | ||||
|  | ||||
| $(OUT)Fenetre.class : $(IN)Fenetre.java $(OUT)Partie.class $(OUT)Dessin.class | ||||
| @@ -30,6 +30,9 @@ $(OUT)Fenetre.class : $(IN)Fenetre.java $(OUT)Partie.class $(OUT)Dessin.class | ||||
| $(OUT)Dessin.class : $(IN)Dessin.java | ||||
| 	$(JC) $(JCFLAGS) $< | ||||
|  | ||||
| $(OUT)Mots.class : $(IN)Mots.java | ||||
| 	$(JC) $(JCFLAGS) $< | ||||
|  | ||||
| # Commandes | ||||
| Pendu : $(OUT)Pendu.class | ||||
|  | ||||
|   | ||||
| @@ -1,23 +1,88 @@ | ||||
| import javax.swing.*; | ||||
| import java.awt.*; | ||||
|  | ||||
| /** | ||||
| * La classe <code>Dessin</code> | ||||
| * La classe <code>Dessin</code> gère uniquement le dessin du pendu | ||||
| * | ||||
| * @version | ||||
| * @author | ||||
| * Date : | ||||
| * @version 1.0 | ||||
| * @author Adrien | ||||
| * Date : 08-10-2025 | ||||
| * Licence : | ||||
| */ | ||||
| public class Dessin { | ||||
|    //Attributs | ||||
| public class Dessin extends JPanel { | ||||
|  | ||||
|    //Constructeur | ||||
|    public Dessin() { | ||||
|     // --- Constructeur --- | ||||
|     public Dessin() { | ||||
|         // Taille préférée pour s'intégrer dans Fenetre | ||||
|         setPreferredSize(new Dimension(600, 350)); | ||||
|         setBackground(new Color(245, 245, 245)); | ||||
|     } | ||||
|  | ||||
|    } | ||||
|    //Méthodes | ||||
|     // --- Dessin principal --- | ||||
|     @Override | ||||
|     protected void paintComponent(Graphics graphics) { | ||||
|         super.paintComponent(graphics); | ||||
|  | ||||
|    //Affichage | ||||
|    public String toString() { | ||||
|       return "" ; | ||||
|    } | ||||
|         // Anti-aliasing pour des traits plus doux | ||||
|         Graphics2D graphics2D = (Graphics2D) graphics.create(); | ||||
|         graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); | ||||
|         graphics2D.setStroke(new BasicStroke(3f)); | ||||
|         graphics2D.setColor(Color.DARK_GRAY); | ||||
|  | ||||
|         // Repères et proportions | ||||
|         int width = getWidth(); | ||||
|         int height = getHeight(); | ||||
|         int marginPixels = Math.min(width, height) / 12; // marge proportionnelle | ||||
|  | ||||
|         // Potence : socle | ||||
|         int baseYCoordinate = height - marginPixels; | ||||
|         graphics2D.drawLine(marginPixels, baseYCoordinate, width / 2, baseYCoordinate); | ||||
|  | ||||
|         // Montant vertical | ||||
|         int postXCoordinate = marginPixels + (width / 12); | ||||
|         graphics2D.drawLine(postXCoordinate, baseYCoordinate, postXCoordinate, marginPixels); | ||||
|  | ||||
|         // Traverse horizontale | ||||
|         int beamLength = width / 3; | ||||
|         graphics2D.drawLine(postXCoordinate, marginPixels, postXCoordinate + beamLength, marginPixels); | ||||
|  | ||||
|         // Renfort diagonal | ||||
|         graphics2D.drawLine(postXCoordinate, marginPixels + height / 10, postXCoordinate + width / 12, marginPixels); | ||||
|  | ||||
|         // Corde | ||||
|         int ropeXCoordinate = postXCoordinate + beamLength; | ||||
|         int ropeTopYCoordinate = marginPixels; | ||||
|         int ropeBottomYCoordinate = marginPixels + height / 12; | ||||
|         graphics2D.drawLine(ropeXCoordinate, ropeTopYCoordinate, ropeXCoordinate, ropeBottomYCoordinate); | ||||
|  | ||||
|         // Personnage : tête | ||||
|         int headRadiusPixels = Math.min(width, height) / 16; | ||||
|         int headCenterX = ropeXCoordinate; | ||||
|         int headCenterY = ropeBottomYCoordinate + headRadiusPixels; | ||||
|         graphics2D.drawOval(headCenterX - headRadiusPixels, headCenterY - headRadiusPixels, headRadiusPixels * 2, headRadiusPixels * 2); | ||||
|  | ||||
|         // Corps | ||||
|         int bodyTopYCoordinate = headCenterY + headRadiusPixels; | ||||
|         int bodyBottomYCoordinate = bodyTopYCoordinate + height / 6; | ||||
|         graphics2D.drawLine(headCenterX, bodyTopYCoordinate, headCenterX, bodyBottomYCoordinate); | ||||
|  | ||||
|         // Bras | ||||
|         int armSpanPixels = width / 10; | ||||
|         int shouldersYCoordinate = bodyTopYCoordinate + height / 24; | ||||
|         graphics2D.drawLine(headCenterX, shouldersYCoordinate, headCenterX - armSpanPixels, shouldersYCoordinate + height / 20); | ||||
|         graphics2D.drawLine(headCenterX, shouldersYCoordinate, headCenterX + armSpanPixels, shouldersYCoordinate + height / 20); | ||||
|  | ||||
|         // Jambes | ||||
|         int legSpanPixels = width / 12; | ||||
|         graphics2D.drawLine(headCenterX, bodyBottomYCoordinate, headCenterX - legSpanPixels, bodyBottomYCoordinate + height / 8); | ||||
|         graphics2D.drawLine(headCenterX, bodyBottomYCoordinate, headCenterX + legSpanPixels, bodyBottomYCoordinate + height / 8); | ||||
|  | ||||
|         graphics2D.dispose(); | ||||
|     } | ||||
|  | ||||
|     // Affichage | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return ""; | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										62
									
								
								src/Event.java
									
									
									
									
									
										一般檔案
									
								
							
							
						
						
									
										62
									
								
								src/Event.java
									
									
									
									
									
										一般檔案
									
								
							| @@ -0,0 +1,62 @@ | ||||
| import javax.swing.*; | ||||
| import java.awt.event.*; | ||||
| import java.util.function.Consumer; | ||||
|  | ||||
| /** | ||||
|  * La classe <code>Event</code> regroupe et branche tous les listeners liés à Fenetre. | ||||
|  * - Validation de la saisie (1 lettre A-Z, majuscule) | ||||
|  * - Action sur Entrée ou clic bouton | ||||
|  * - Notification du handler externe (fourni au constructeur) | ||||
|  * Aucune logique de jeu ici. | ||||
|  * @version 1.3 | ||||
|  * author Adrien | ||||
|  * Date : 08-10-2025 | ||||
|  */ | ||||
| public class Event implements ActionListener { | ||||
|  | ||||
|     private final Fenetre window; | ||||
|     private final Consumer<Character> onLetterSubmitted; | ||||
|  | ||||
|     /** Constructeur : conserve les références et branche les événements. */ | ||||
|     public Event(Fenetre window, Consumer<Character> onLetterSubmitted) { | ||||
|         this.window = window; | ||||
|         this.onLetterSubmitted = onLetterSubmitted; | ||||
|         wireEvents(); | ||||
|     } | ||||
|  | ||||
|     /** Branche les listeners sur les composants de Fenetre. */ | ||||
|     private void wireEvents() { | ||||
|         JTextField letterInput = window.getLetterInput(); | ||||
|         JButton sendButton = window.getSendButton(); | ||||
|  | ||||
|         // Même listener (this) pour Entrée et clic bouton | ||||
|         sendButton.addActionListener(this); | ||||
|         letterInput.addActionListener(this); | ||||
|  | ||||
|         // UX : limiter à une seule lettre et forcer la majuscule (classe dédiée) | ||||
|         letterInput.addKeyListener(new LetterInputFilter(letterInput)); | ||||
|     } | ||||
|  | ||||
|     /** Réagit à Entrée ou au clic bouton : récupère, valide et transmet la lettre. */ | ||||
|     @Override | ||||
|     public void actionPerformed(ActionEvent actionEvent) { | ||||
|         JTextField letterInput = window.getLetterInput(); | ||||
|  | ||||
|         String inputText = letterInput.getText().trim().toUpperCase(); | ||||
|         letterInput.setText(""); // reset du champ après tentative | ||||
|  | ||||
|         // Validation : exactement une lettre A–Z | ||||
|         if (inputText.length() != 1 || !inputText.matches("[A-Z]")) { | ||||
|             JOptionPane.showMessageDialog(window.getWindow(), "Veuillez entrer une seule lettre (A-Z)."); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // Notification du handler externe, sinon placeholder | ||||
|         if (onLetterSubmitted != null) { | ||||
|             onLetterSubmitted.accept(inputText.charAt(0)); | ||||
|         } else { | ||||
|             JOptionPane.showMessageDialog(window.getWindow(), | ||||
|                     "Lettre soumise (placeholder) : " + inputText); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										103
									
								
								src/Fenetre.java
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								src/Fenetre.java
									
									
									
									
									
								
							| @@ -1,23 +1,98 @@ | ||||
| import javax.swing.*; | ||||
| import java.awt.*; | ||||
| import java.util.function.Consumer; | ||||
|  | ||||
| /** | ||||
| * La classe <code>Fenetre</code> | ||||
| * La classe <code>Fenetre</code> gère uniquement l'interface graphique : | ||||
| * - zone de dessin (assurée par la classe Dessin) | ||||
| * - affichage du mot masqué | ||||
| * - saisie d'une lettre (les événements sont gérés dans Event) | ||||
| * | ||||
| * @version | ||||
| * @author | ||||
| * Date : | ||||
| * Aucune logique de jeu ici. | ||||
| * @version 1.5 | ||||
| * @author Adrien | ||||
| * Date : 08-10-2025 | ||||
| * Licence : | ||||
| */ | ||||
|  | ||||
| public class Fenetre { | ||||
|    //Attributs | ||||
|  | ||||
|    //Constructeur | ||||
|    public Fenetre() { | ||||
|     // --- Composants de l'interface --- | ||||
|     private JFrame window; | ||||
|     private JLabel wordLabel; | ||||
|     private JTextField letterInput; | ||||
|     private JButton sendButton; | ||||
|     private JPanel drawZone; // instance de Dessin | ||||
|  | ||||
|    } | ||||
|    //Méthodes | ||||
|     // --- Constructeur --- | ||||
|     public Fenetre() { | ||||
|         setupWindow(); | ||||
|  | ||||
|    //Affichage | ||||
|    public String toString() { | ||||
|       return "" ; | ||||
|    } | ||||
| } | ||||
|         JPanel root = new JPanel(); | ||||
|         root.setLayout(new BoxLayout(root, BoxLayout.Y_AXIS)); | ||||
|         window.setContentPane(root); | ||||
|  | ||||
|         drawZone = new Dessin(); | ||||
|         root.add(drawZone); | ||||
|  | ||||
|         wordLabel = createWordLabel(); | ||||
|         root.add(wordLabel); | ||||
|  | ||||
|         JPanel inputPanel = createInputPanel(); | ||||
|         root.add(inputPanel); | ||||
|  | ||||
|         window.setVisible(true); | ||||
|         letterInput.requestFocusInWindow(); | ||||
|     } | ||||
|  | ||||
|     // --- Initialisation fenêtre --- | ||||
|     private void setupWindow() { | ||||
|         window = new JFrame("Jeu du Pendu"); | ||||
|         window.setSize(600, 600); | ||||
|         window.setLocationRelativeTo(null); | ||||
|         window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | ||||
|     } | ||||
|  | ||||
|     // --- Sous-composants UI --- | ||||
|     private JLabel createWordLabel() { | ||||
|         JLabel label = new JLabel("_ _ _ _ _", SwingConstants.CENTER); | ||||
|         label.setFont(new Font("Segoe UI", Font.BOLD, 32)); | ||||
|         label.setBorder(BorderFactory.createEmptyBorder(20, 10, 20, 10)); | ||||
|         label.setAlignmentX(Component.CENTER_ALIGNMENT); | ||||
|         return label; | ||||
|     } | ||||
|  | ||||
|     private JPanel createInputPanel() { | ||||
|         JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10)); | ||||
|         JLabel prompt = new JLabel("Entrez une lettre :"); | ||||
|  | ||||
|         letterInput = new JTextField(2); | ||||
|         letterInput.setHorizontalAlignment(JTextField.CENTER); | ||||
|         letterInput.setFont(new Font("Segoe UI", Font.BOLD, 24)); | ||||
|  | ||||
|         sendButton = new JButton("Envoyer"); | ||||
|  | ||||
|         inputPanel.add(prompt); | ||||
|         inputPanel.add(letterInput); | ||||
|         inputPanel.add(sendButton); | ||||
|         return inputPanel; | ||||
|     } | ||||
|  | ||||
|     // --- Getters pour Event --- | ||||
|     public JFrame getWindow() { return window; } | ||||
|     public JTextField getLetterInput() { return letterInput; } | ||||
|     public JButton getSendButton() { return sendButton; } | ||||
|     public JLabel getWordLabel() { return wordLabel; } | ||||
|     public JPanel getDrawZone() { return drawZone; } | ||||
|  | ||||
|     // --- Méthode principale de test --- | ||||
|     public static void main(String[] args) { | ||||
|         SwingUtilities.invokeLater(() -> { | ||||
|             Fenetre f = new Fenetre(); | ||||
|             // On passe le handler directement ici (pas de setOnLetterSubmitted) | ||||
|             new Event(f, ch -> | ||||
|                 JOptionPane.showMessageDialog(f.getWindow(), "Lettre reçue : " + ch + " (sans logique de jeu)") | ||||
|             ); | ||||
|         }); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										47
									
								
								src/LetterInputFilter.java
									
									
									
									
									
										一般檔案
									
								
							
							
						
						
									
										47
									
								
								src/LetterInputFilter.java
									
									
									
									
									
										一般檔案
									
								
							| @@ -0,0 +1,47 @@ | ||||
| import javax.swing.*; | ||||
| import java.awt.event.KeyAdapter; | ||||
| import java.awt.event.KeyEvent; | ||||
|  | ||||
| /** | ||||
|  * La classe <code>LetterInputFilter</code> limite la saisie d'un champ texte | ||||
|  * à une seule lettre de l'alphabet (A–Z), en forçant automatiquement | ||||
|  * la majuscule. Toute autre frappe est ignorée. | ||||
|  * | ||||
|  * @version 1.0 | ||||
|  * @author Adrien | ||||
|  * Date : 08-10-2025 | ||||
|  * Licence : | ||||
|  */ | ||||
| public class LetterInputFilter extends KeyAdapter { | ||||
|  | ||||
|     /** Référence vers le champ de saisie à filtrer. */ | ||||
|     private final JTextField letterInput; | ||||
|  | ||||
|     //Constructeur. | ||||
|     public LetterInputFilter(JTextField letterInput) { | ||||
|         if (letterInput == null) { | ||||
|             throw new NullPointerException("letterInput ne doit pas être null"); | ||||
|         } | ||||
|         this.letterInput = letterInput; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Intercepte les frappes clavier et applique les règles suivantes : | ||||
|      * - n'accepte que les lettres (A–Z)  | ||||
|      * - limite la saisie à un seul caractère  | ||||
|      * - force la majuscule sur le caractère saisi. | ||||
|      */ | ||||
|     @Override | ||||
|     public void keyTyped(KeyEvent keyEvent) { | ||||
|         char typedChar = keyEvent.getKeyChar(); | ||||
|  | ||||
|         // Refuse tout caractère non alphabétique ou une saisie > 1 caractère. | ||||
|         if (!Character.isLetter(typedChar) || letterInput.getText().length() >= 1) { | ||||
|             keyEvent.consume(); // ignore la frappe | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // Force la majuscule. | ||||
|         keyEvent.setKeyChar(Character.toUpperCase(typedChar)); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										58
									
								
								src/Mots.java
									
									
									
									
									
										一般檔案
									
								
							
							
						
						
									
										58
									
								
								src/Mots.java
									
									
									
									
									
										一般檔案
									
								
							| @@ -0,0 +1,58 @@ | ||||
|  | ||||
| /** | ||||
| * La classe <code>Mots</code> | ||||
| * | ||||
| * @version 1.0 | ||||
| * @author Aurélien | ||||
| * Date : 08-10-25 | ||||
| * Licence : | ||||
| */ | ||||
| public final class Mots { | ||||
|    //Attributs | ||||
|    public static final short dictionarysize = 32 ; | ||||
|    public static final String[] dictionary = { | ||||
|       "Magnifique", | ||||
|       "Etoile", | ||||
|       "Voyage", | ||||
|       "Biscuit", | ||||
|       "Refrigerateur", | ||||
|       "Courage", | ||||
|       "Avion", | ||||
|       "Explorateur", | ||||
|       "Montagne", | ||||
|       "Philosophie", | ||||
|       "Lumiere", | ||||
|       "Ethernet", | ||||
|       "Architecture", | ||||
|       "Ocean", | ||||
|       "Liberte", | ||||
|       "Aventure", | ||||
|       "Cerise", | ||||
|       "Harmonieux", | ||||
|       "Informatique", | ||||
|       "Pluie", | ||||
|       "Equilibriste", | ||||
|       "Papillon", | ||||
|       "Saisons", | ||||
|       "Liberte", | ||||
|       "Alphabet", | ||||
|       "Musique", | ||||
|       "Translucent", | ||||
|       "Passion", | ||||
|       "Etreindre", | ||||
|       "Poetique", | ||||
|       "Serenite", | ||||
|       "Révolution" | ||||
|    }; | ||||
|  | ||||
|    //Constructeur | ||||
|    private Mots() {  //N'a pas pour but d'être instanciée | ||||
|       throw new UnsupportedOperationException("The \"Fichier\" class cannot be instanced !"); | ||||
|    } | ||||
|    //Méthodes | ||||
|  | ||||
|    //Affichage | ||||
|    public String toString() { | ||||
|       return "" ; | ||||
|    } | ||||
| } | ||||
| @@ -1,8 +1,9 @@ | ||||
| import java.util.Random; | ||||
|  | ||||
| /** | ||||
| * La classe <code>Partie</code> | ||||
| * | ||||
| * @version 0.1 | ||||
| * @version 0.2 | ||||
| * @author Aurélien | ||||
| * Date : 08-10-25 | ||||
| * Licence : | ||||
| @@ -81,10 +82,15 @@ public class Partie { | ||||
|       } | ||||
|    } | ||||
|  | ||||
|  | ||||
|    /** | ||||
|     * Génère un mot à partir d'un grand dictionnaire (enfin en principe). | ||||
|     *  | ||||
|     * @return le mot généré. | ||||
|     */ | ||||
|    private char[] generateSecretWord() { | ||||
|       char[] word = {'D','A','M','I','E','N'}; | ||||
|       //À implémenter plus tard | ||||
|       Random random = new Random(); | ||||
|       byte grain = (byte) random.nextInt(Mots.dictionarysize); | ||||
|       char[] word = Mots.dictionary[grain].toUpperCase().toCharArray(); | ||||
|       return word ; | ||||
|    } | ||||
|  | ||||
| @@ -105,7 +111,7 @@ public class Partie { | ||||
|  | ||||
|    //Tests | ||||
|    public static void main(String[] args){ | ||||
|       char[] test = {'E','O','M','I','E','D','A','Z','N'}; | ||||
|       char[] test = {'E','O','M','I','E','D','A','Z','N','L','C','R','P','H','T','S'}; | ||||
|       byte size = (byte) test.length ; | ||||
|       boolean status ; | ||||
|  | ||||
| @@ -124,5 +130,6 @@ public class Partie { | ||||
|          System.out.println("");  //Lisibilité | ||||
|          //System.out.println("Lettres : " + game.entriesletters); | ||||
|       } | ||||
|       System.out.println("Essais restants : " + game.getRemainingTry()); | ||||
|    } | ||||
| } | ||||
|   | ||||
		新增問題並參考
	
	封鎖使用者