比較提交
	
		
			4 次程式碼提交
		
	
	
		
			d074170b0f
			...
			6943bafd1d
		
	
	| 作者 | SHA1 | 日期 | |
|---|---|---|---|
| 6943bafd1d | |||
| 37ebbcbdef | |||
| f3df0b36a9 | |||
| 15d048e21a | 
							
								
								
									
										263
									
								
								HangmanGUI.java
									
									
									
									
									
										一般檔案
									
								
							
							
						
						
									
										263
									
								
								HangmanGUI.java
									
									
									
									
									
										一般檔案
									
								
							| @@ -0,0 +1,263 @@ | ||||
| import javax.swing.*; | ||||
| import java.awt.*; | ||||
| import java.awt.event.*; | ||||
| import java.util.*; | ||||
|  | ||||
| /** | ||||
|  * Hangman game GUI. | ||||
|  * Variables/methods and comments in English. | ||||
|  * User-facing texts remain in French. | ||||
|  */ | ||||
| public class HangmanGUI extends JFrame { | ||||
|     private final String[] words = { | ||||
|         "ordinateur","voiture","maison","soleil","lumiere", | ||||
|         "fromage","chocolat","montagne","riviere","plage", | ||||
|         "oiseau","papillon","musique","chateau","livre", | ||||
|         "telephone","aventure","mystere","foret","fleur", | ||||
|         "chapeau","nuage","horloge","chaise","fenetre", | ||||
|         "paysage","bouteille","parapluie","clavier","souris", | ||||
|         "brouillard","village","histoire","cerise","pomme", | ||||
|         "banane","poisson","arbre","cascade","cheval" | ||||
|     }; | ||||
|  | ||||
|     private String secretWord; | ||||
|     private final Set<Character> found = new HashSet<>(); | ||||
|     private final Set<Character> tried = new HashSet<>(); | ||||
|     private int errors = 0; | ||||
|     private static final int MAX_ERRORS = 8; // 8 steps: base, post, beam, rope, head, body, arms, legs | ||||
|     private boolean gameOver = false;        // indicates if the game is finished | ||||
|  | ||||
|     private final JLabel wordLbl = new JLabel("", SwingConstants.CENTER); | ||||
|     private final JLabel triedLbl = new JLabel("", SwingConstants.CENTER); | ||||
|     private final JLabel infoLbl  = new JLabel("Entrez une lettre (a-z)", SwingConstants.CENTER); | ||||
|     private final JTextField input = new JTextField(); | ||||
|     private final JButton guessBtn = new JButton("Proposer"); | ||||
|     private final HangPanel hangPanel = new HangPanel(); | ||||
|  | ||||
|     /** Drawing panel for the hangman, progressive according to error count. */ | ||||
|     private static class HangPanel extends JPanel { | ||||
|         private int errors = 0; | ||||
|  | ||||
|         public void setErrors(int e) { | ||||
|             this.errors = Math.max(0, Math.min(e, MAX_ERRORS)); | ||||
|             repaint(); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         protected void paintComponent(Graphics g) { | ||||
|             super.paintComponent(g); | ||||
|             Graphics2D gg = (Graphics2D) g; | ||||
|             gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); | ||||
|  | ||||
|             int w = getWidth(), h = getHeight(); | ||||
|             int baseY = h - 40; // ground level | ||||
|  | ||||
|             if (errors >= 1) gg.drawLine(50, baseY, w - 50, baseY); | ||||
|  | ||||
|             if (errors >= 2) gg.drawLine(100, baseY, 100, 60); | ||||
|  | ||||
|             if (errors >= 3) gg.drawLine(100, 60, 220, 60); | ||||
|  | ||||
|             if (errors >= 4) gg.drawLine(220, 60, 220, 90); | ||||
|  | ||||
|             if (errors >= 5) gg.drawOval(200, 90, 40, 40); | ||||
|  | ||||
|             if (errors >= 6) gg.drawLine(220, 130, 220, 200); | ||||
|  | ||||
|             if (errors >= 7) { | ||||
|                 gg.drawLine(220, 145, 190, 165);  | ||||
|                 gg.drawLine(220, 145, 250, 165); | ||||
|             } | ||||
|  | ||||
|             if (errors >= 8) { | ||||
|                 gg.drawLine(220, 200, 200, 240);  | ||||
|                 gg.drawLine(220, 200, 240, 240);  | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** Entry point: create and show the game window. */ | ||||
|     public static void main(String[] args) { | ||||
|         SwingUtilities.invokeLater(() -> { | ||||
|             HangmanGUI app = new HangmanGUI(); | ||||
|             app.setVisible(true); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** Constructor: window setup, UI setup, and start the game. */ | ||||
|     public HangmanGUI() { | ||||
|         super("Jeu du Pendu"); | ||||
|         setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); | ||||
|         setSize(520, 520); | ||||
|         setLocationRelativeTo(null); | ||||
|         setupUI(); | ||||
|         startGame(); | ||||
|     } | ||||
|  | ||||
|     /** Prepare the layout and interactions. */ | ||||
|     private void setupUI() { | ||||
|         wordLbl.setFont(new Font(Font.MONOSPACED, Font.BOLD, 28)); | ||||
|         triedLbl.setFont(new Font("SansSerif", Font.PLAIN, 14)); | ||||
|         infoLbl.setFont(new Font("SansSerif", Font.PLAIN, 14)); | ||||
|  | ||||
|         JPanel top = new JPanel(new GridLayout(3, 1, 8, 8)); | ||||
|         top.add(wordLbl); | ||||
|         top.add(triedLbl); | ||||
|         top.add(infoLbl); | ||||
|  | ||||
|         JPanel controls = new JPanel(new BorderLayout(8, 8)); | ||||
|         controls.add(input, BorderLayout.CENTER); | ||||
|         controls.add(guessBtn, BorderLayout.EAST); | ||||
|  | ||||
|         hangPanel.setPreferredSize(new Dimension(480, 300)); | ||||
|         JPanel center = new JPanel(new BorderLayout()); | ||||
|         center.add(hangPanel, BorderLayout.CENTER); | ||||
|  | ||||
|         JPanel main = new JPanel(new BorderLayout(10, 10)); | ||||
|         main.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); | ||||
|         main.add(top, BorderLayout.NORTH); | ||||
|         main.add(center, BorderLayout.CENTER); | ||||
|         main.add(controls, BorderLayout.SOUTH); | ||||
|  | ||||
|         setContentPane(main); | ||||
|  | ||||
|         guessBtn.addActionListener(e -> onGuess()); | ||||
|         input.addActionListener(e -> onGuess());  | ||||
|         addWindowListener(new WindowAdapter() { | ||||
|             @Override public void windowOpened(WindowEvent e) { input.requestFocusInWindow(); } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** Start a  game. */ | ||||
|     private void startGame() { | ||||
|         secretWord = pickWord(); | ||||
|         found.clear(); | ||||
|         tried.clear(); | ||||
|         errors = 0; | ||||
|         gameOver = false; | ||||
|  | ||||
|         input.setText(""); | ||||
|         input.setEditable(true); | ||||
|         guessBtn.setEnabled(true); | ||||
|         infoLbl.setText("Entrez une lettre (a-z)"); | ||||
|         updateUIState(); | ||||
|     } | ||||
|  | ||||
|     /** Handle a guess: validate input, update state, check for end of game. */ | ||||
|     private void onGuess() { | ||||
|         if (gameOver) return; // block input after game end | ||||
|  | ||||
|         String s = input.getText().trim().toLowerCase(Locale.ROOT); | ||||
|         if (s.length() != 1 || s.charAt(0) < 'a' || s.charAt(0) > 'z') { | ||||
|             infoLbl.setText("Veuillez entrer une seule lettre (a-z)."); | ||||
|             input.selectAll(); | ||||
|             input.requestFocusInWindow(); | ||||
|             return; | ||||
|         } | ||||
|         char c = s.charAt(0); | ||||
|         if (tried.contains(c)) { | ||||
|             infoLbl.setText("Lettre déjà essayée : " + c); | ||||
|             input.selectAll(); | ||||
|             input.requestFocusInWindow(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         tried.add(c); | ||||
|         boolean hit = false; | ||||
|         for (int i = 0; i < secretWord.length(); i++) { | ||||
|             if (Character.toLowerCase(secretWord.charAt(i)) == c) { | ||||
|                 found.add(c); | ||||
|                 hit = true; | ||||
|             } | ||||
|         } | ||||
|         if (!hit) { | ||||
|             errors++; | ||||
|             infoLbl.setText("Mauvaise lettre : " + c); | ||||
|         } else { | ||||
|             infoLbl.setText("Bonne lettre : " + c); | ||||
|         } | ||||
|  | ||||
|         updateUIState(); | ||||
|         input.selectAll(); | ||||
|         input.requestFocusInWindow(); | ||||
|     } | ||||
|  | ||||
|     /** Refresh labels/drawing and handle end-of-game. */ | ||||
|     private void updateUIState() { | ||||
|         wordLbl.setText(maskWord(secretWord, found)); | ||||
|         triedLbl.setText("Lettres essayées : " + joinChars(tried)); | ||||
|         hangPanel.setErrors(errors); | ||||
|  | ||||
|         if (isWin(secretWord, found)) { | ||||
|             infoLbl.setText("Bravo ! Vous avez trouvé le mot : " + secretWord); | ||||
|             wordLbl.setText(spaced(secretWord)); // pretty display of the word | ||||
|             gameOver = true; | ||||
|             disableInput(); | ||||
|         } else if (errors >= MAX_ERRORS) { | ||||
|             infoLbl.setText("Perdu ! Le mot était : " + secretWord); | ||||
|             wordLbl.setText(spaced(secretWord)); | ||||
|             gameOver = true; | ||||
|             disableInput(); | ||||
|         } | ||||
|  | ||||
|         // force UI refresh | ||||
|         revalidate(); | ||||
|         repaint(); | ||||
|     } | ||||
|  | ||||
|     /** Disable controls after the game ends. */ | ||||
|     private void disableInput() { | ||||
|         input.setEditable(false); | ||||
|         guessBtn.setEnabled(false); | ||||
|     } | ||||
|  | ||||
|     /** Pick a random word. */ | ||||
|     private String pickWord() { | ||||
|         Random rnd = new Random(); | ||||
|         return words[rnd.nextInt(words.length)].toLowerCase(Locale.ROOT); | ||||
|     } | ||||
|  | ||||
|     /** Build the masked word based on found letters. */ | ||||
|     private String maskWord(String secret, Set<Character> foundSet) { | ||||
|         StringBuilder sb = new StringBuilder(); | ||||
|         for (int i = 0; i < secret.length(); i++) { | ||||
|             char ch = secret.charAt(i); | ||||
|             char lc = Character.toLowerCase(ch); | ||||
|             if (Character.isLetter(lc) && !foundSet.contains(lc)) sb.append('_'); | ||||
|             else sb.append(ch); | ||||
|             if (i < secret.length() - 1) sb.append(' '); | ||||
|         } | ||||
|         return sb.toString(); | ||||
|     } | ||||
|  | ||||
|     /** True if all letters have been found. */ | ||||
|     private boolean isWin(String secret, Set<Character> foundSet) { | ||||
|         for (int i = 0; i < secret.length(); i++) { | ||||
|             char lc = Character.toLowerCase(secret.charAt(i)); | ||||
|             if (Character.isLetter(lc) && !foundSet.contains(lc)) return false; | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** Sort and join letters for display. */ | ||||
|     private String joinChars(Set<Character> set) { | ||||
|         java.util.List<Character> list = new ArrayList<>(set); | ||||
|         Collections.sort(list); | ||||
|         StringBuilder sb = new StringBuilder(); | ||||
|         for (int i = 0; i < list.size(); i++) { | ||||
|             sb.append(list.get(i)); | ||||
|             if (i < list.size() - 1) sb.append(' '); | ||||
|         } | ||||
|         return sb.toString(); | ||||
|     } | ||||
|  | ||||
|     /** Add spaces between letters for nicer reading. */ | ||||
|     private String spaced(String s) { | ||||
|         StringBuilder sb = new StringBuilder(); | ||||
|         for (int i = 0; i < s.length(); i++) { | ||||
|             sb.append(s.charAt(i)); | ||||
|             if (i < s.length() - 1) sb.append(' '); | ||||
|         } | ||||
|         return sb.toString(); | ||||
|     } | ||||
| } | ||||
		新增問題並參考
	
	封鎖使用者