|
1 | 1 | /** |
2 | | - * 🎮 Hangman GUI Game |
| 2 | + * 🎮 Enhanced Hangman GUI Game |
3 | 3 | * |
4 | | - * A simple word-guessing game using Java Swing. |
5 | | - * Players guess letters to figure out a hidden word. |
6 | | - * GUI displays the current word, remaining attempts, messages, and allows restarting. |
| 4 | + * Features added for Hacktoberfest: |
| 5 | + * ✅ Tracks used letters |
| 6 | + * ✅ Provides hints after 3 wrong guesses |
| 7 | + * ✅ Displays a score system (wins/losses) |
| 8 | + * ✅ Adds color-coded messages for better UX |
7 | 9 | * |
8 | | - * |
9 | | - * Author: Pradyumn Pratap Singh (Strange) |
| 10 | + * Author: Sakshi (Hacktoberfest Contribution) |
| 11 | + * Original Author: Pradyumn Pratap Singh (Strange) |
10 | 12 | */ |
11 | 13 |
|
12 | 14 | import javax.swing.*; |
13 | 15 | import java.awt.*; |
14 | 16 | import java.awt.event.*; |
15 | | -import java.util.Random; |
| 17 | +import java.util.*; |
16 | 18 |
|
17 | 19 | public class HangmanGUI extends JFrame implements ActionListener { |
18 | 20 |
|
19 | | - // Array of possible words for the game |
20 | | - private String[] words = {"JAVA", "HANGMAN", "COMPUTER", "PROGRAMMING", "SWING"}; |
| 21 | + // Word list with hints |
| 22 | + private final Map<String, String> wordHints = Map.of( |
| 23 | + "JAVA", "A popular programming language", |
| 24 | + "HANGMAN", "A classic word-guessing game", |
| 25 | + "COMPUTER", "An electronic device for calculations", |
| 26 | + "PROGRAMMING", "What developers love to do!", |
| 27 | + "SWING", "A Java GUI toolkit" |
| 28 | + ); |
21 | 29 |
|
22 | 30 | // The current word to guess |
23 | 31 | private String word; |
24 | 32 |
|
25 | | - // Array to store the current guessed letters (e.g., "_ A _ A") |
| 33 | + // Array to store guessed letters (e.g., "_ A _ A") |
26 | 34 | private char[] guessedWord; |
27 | 35 |
|
28 | | - // Remaining attempts before the game is over |
| 36 | + // Game state variables |
29 | 37 | private int attempts = 6; |
| 38 | + private int wins = 0; |
| 39 | + private int losses = 0; |
| 40 | + private Set<Character> usedLetters = new HashSet<>(); |
30 | 41 |
|
31 | 42 | // Swing components |
32 | | - private JLabel wordLabel, attemptsLabel, messageLabel; |
| 43 | + private JLabel wordLabel, attemptsLabel, messageLabel, usedLabel, scoreLabel; |
33 | 44 | private JTextField inputField; |
34 | 45 | private JButton guessButton, restartButton; |
35 | 46 |
|
36 | 47 | /** |
37 | | - * Constructor to set up the GUI and initialize the game. |
| 48 | + * Constructor to set up the GUI and start the first game. |
38 | 49 | */ |
39 | 50 | public HangmanGUI() { |
40 | | - // Select a random word from the list |
41 | | - word = words[new Random().nextInt(words.length)]; |
42 | | - |
43 | | - // Initialize guessedWord array with underscores |
44 | | - guessedWord = new char[word.length()]; |
45 | | - for (int i = 0; i < guessedWord.length; i++) guessedWord[i] = '_'; |
| 51 | + setupUI(); |
| 52 | + startNewGame(); |
| 53 | + } |
46 | 54 |
|
47 | | - // JFrame properties |
48 | | - setTitle("🎮 Hangman Game"); |
49 | | - setSize(400, 250); |
| 55 | + /** |
| 56 | + * Initializes GUI components and layout. |
| 57 | + */ |
| 58 | + private void setupUI() { |
| 59 | + setTitle("🎮 Enhanced Hangman Game"); |
| 60 | + setSize(450, 320); |
50 | 61 | setDefaultCloseOperation(EXIT_ON_CLOSE); |
51 | 62 | setLocationRelativeTo(null); |
52 | | - setLayout(new GridLayout(5, 1, 5, 5)); |
| 63 | + setLayout(new GridLayout(7, 1, 5, 5)); |
53 | 64 |
|
54 | | - // Label to display the guessed word |
55 | | - wordLabel = new JLabel(new String(guessedWord), SwingConstants.CENTER); |
56 | | - wordLabel.setFont(new Font("Segoe UI", Font.BOLD, 24)); |
| 65 | + wordLabel = new JLabel("", SwingConstants.CENTER); |
| 66 | + wordLabel.setFont(new Font("Segoe UI", Font.BOLD, 28)); |
57 | 67 |
|
58 | | - // Label to show remaining attempts |
59 | | - attemptsLabel = new JLabel("Attempts left: " + attempts, SwingConstants.CENTER); |
| 68 | + attemptsLabel = new JLabel("", SwingConstants.CENTER); |
| 69 | + messageLabel = new JLabel("", SwingConstants.CENTER); |
| 70 | + usedLabel = new JLabel("", SwingConstants.CENTER); |
| 71 | + scoreLabel = new JLabel("Score: 0 Wins | 0 Losses", SwingConstants.CENTER); |
60 | 72 |
|
61 | | - // Label to display messages or prompts |
62 | | - messageLabel = new JLabel("Enter a letter:", SwingConstants.CENTER); |
63 | | - |
64 | | - // Text field for player to enter a guess |
65 | 73 | inputField = new JTextField(); |
66 | | - |
67 | | - // Buttons for guessing and restarting the game |
68 | 74 | guessButton = new JButton("Guess"); |
69 | 75 | restartButton = new JButton("Restart"); |
70 | 76 |
|
71 | | - // Add action listeners |
72 | 77 | guessButton.addActionListener(this); |
73 | | - restartButton.addActionListener(e -> restartGame()); |
| 78 | + restartButton.addActionListener(e -> startNewGame()); |
| 79 | + |
| 80 | + JPanel bottomPanel = new JPanel(new FlowLayout()); |
| 81 | + bottomPanel.add(guessButton); |
| 82 | + bottomPanel.add(restartButton); |
74 | 83 |
|
75 | | - // Add components to JFrame |
76 | 84 | add(wordLabel); |
77 | 85 | add(attemptsLabel); |
78 | 86 | add(messageLabel); |
79 | 87 | add(inputField); |
80 | | - |
81 | | - // Bottom panel for buttons |
82 | | - JPanel bottomPanel = new JPanel(new FlowLayout()); |
83 | | - bottomPanel.add(guessButton); |
84 | | - bottomPanel.add(restartButton); |
| 88 | + add(usedLabel); |
| 89 | + add(scoreLabel); |
85 | 90 | add(bottomPanel); |
86 | 91 |
|
87 | | - // Make GUI visible |
88 | 92 | setVisible(true); |
89 | 93 | } |
90 | 94 |
|
| 95 | + /** |
| 96 | + * Starts or restarts a new round of the game. |
| 97 | + */ |
| 98 | + private void startNewGame() { |
| 99 | + // Pick a random word |
| 100 | + List<String> keys = new ArrayList<>(wordHints.keySet()); |
| 101 | + word = keys.get(new Random().nextInt(keys.size())); |
| 102 | + |
| 103 | + guessedWord = new char[word.length()]; |
| 104 | + Arrays.fill(guessedWord, '_'); |
| 105 | + attempts = 6; |
| 106 | + usedLetters.clear(); |
| 107 | + |
| 108 | + // Update GUI |
| 109 | + updateLabels(); |
| 110 | + messageLabel.setText("Enter a letter:"); |
| 111 | + messageLabel.setForeground(Color.BLACK); |
| 112 | + guessButton.setEnabled(true); |
| 113 | + inputField.setText(""); |
| 114 | + } |
| 115 | + |
91 | 116 | /** |
92 | 117 | * Handles the Guess button click event. |
93 | 118 | */ |
94 | 119 | @Override |
95 | 120 | public void actionPerformed(ActionEvent e) { |
96 | | - String input = inputField.getText().toUpperCase(); // Convert to uppercase |
97 | | - inputField.setText(""); // Clear input field |
| 121 | + String input = inputField.getText().toUpperCase(); |
| 122 | + inputField.setText(""); |
98 | 123 |
|
99 | | - // Validate input |
100 | | - if (input.length() != 1) { |
101 | | - messageLabel.setText("Enter only one letter!"); |
| 124 | + if (input.length() != 1 || !Character.isLetter(input.charAt(0))) { |
| 125 | + messageLabel.setText("⚠️ Please enter a single letter!"); |
| 126 | + messageLabel.setForeground(Color.ORANGE); |
102 | 127 | return; |
103 | 128 | } |
104 | 129 |
|
105 | 130 | char guess = input.charAt(0); |
| 131 | + if (usedLetters.contains(guess)) { |
| 132 | + messageLabel.setText("You already tried '" + guess + "'!"); |
| 133 | + messageLabel.setForeground(Color.GRAY); |
| 134 | + return; |
| 135 | + } |
| 136 | + |
| 137 | + usedLetters.add(guess); |
106 | 138 | boolean correct = false; |
107 | 139 |
|
108 | | - // Check if the guessed letter is in the word |
109 | 140 | for (int i = 0; i < word.length(); i++) { |
110 | 141 | if (word.charAt(i) == guess) { |
111 | 142 | guessedWord[i] = guess; |
112 | 143 | correct = true; |
113 | 144 | } |
114 | 145 | } |
115 | 146 |
|
116 | | - // Update attempts if guess is incorrect |
117 | | - if (!correct) attempts--; |
| 147 | + if (!correct) { |
| 148 | + attempts--; |
| 149 | + messageLabel.setText("❌ Wrong! Attempts left: " + attempts); |
| 150 | + messageLabel.setForeground(Color.RED); |
| 151 | + } else { |
| 152 | + messageLabel.setText("✅ Good guess!"); |
| 153 | + messageLabel.setForeground(Color.GREEN); |
| 154 | + } |
118 | 155 |
|
119 | | - // Update GUI labels |
120 | | - wordLabel.setText(new String(guessedWord)); |
121 | | - attemptsLabel.setText("Attempts left: " + attempts); |
| 156 | + // Reveal hint if 3 attempts remain |
| 157 | + if (attempts == 3) { |
| 158 | + messageLabel.setText("<html>Hint: " + wordHints.get(word) + "</html>"); |
| 159 | + messageLabel.setForeground(new Color(0, 128, 255)); |
| 160 | + } |
| 161 | + |
| 162 | + updateLabels(); |
122 | 163 |
|
123 | | - // Check for win condition |
124 | 164 | if (new String(guessedWord).equals(word)) { |
| 165 | + wins++; |
125 | 166 | messageLabel.setText("🎉 You Won! Word: " + word); |
| 167 | + messageLabel.setForeground(new Color(0, 200, 0)); |
126 | 168 | guessButton.setEnabled(false); |
127 | | - } |
128 | | - // Check for loss condition |
129 | | - else if (attempts == 0) { |
| 169 | + } else if (attempts == 0) { |
| 170 | + losses++; |
130 | 171 | messageLabel.setText("💀 Game Over! Word: " + word); |
| 172 | + messageLabel.setForeground(Color.RED); |
131 | 173 | guessButton.setEnabled(false); |
132 | 174 | } |
| 175 | + |
| 176 | + scoreLabel.setText("Score: " + wins + " Wins | " + losses + " Losses"); |
133 | 177 | } |
134 | 178 |
|
135 | 179 | /** |
136 | | - * Resets the game to start a new round. |
| 180 | + * Updates labels showing game state. |
137 | 181 | */ |
138 | | - private void restartGame() { |
139 | | - // Select a new random word |
140 | | - word = words[new Random().nextInt(words.length)]; |
141 | | - |
142 | | - // Reset guessed word |
143 | | - guessedWord = new char[word.length()]; |
144 | | - for (int i = 0; i < guessedWord.length; i++) guessedWord[i] = '_'; |
145 | | - |
146 | | - // Reset attempts |
147 | | - attempts = 6; |
148 | | - |
149 | | - // Update GUI labels |
| 182 | + private void updateLabels() { |
150 | 183 | wordLabel.setText(new String(guessedWord)); |
151 | 184 | attemptsLabel.setText("Attempts left: " + attempts); |
152 | | - messageLabel.setText("Enter a letter:"); |
153 | | - |
154 | | - // Enable guess button |
155 | | - guessButton.setEnabled(true); |
| 185 | + usedLabel.setText("Used letters: " + usedLetters.toString()); |
156 | 186 | } |
157 | 187 |
|
158 | 188 | /** |
159 | | - * Main method to start the game. |
| 189 | + * Main method to run the game. |
160 | 190 | */ |
161 | 191 | public static void main(String[] args) { |
162 | 192 | SwingUtilities.invokeLater(HangmanGUI::new); |
|
0 commit comments