-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathWordleApp.java
More file actions
320 lines (285 loc) · 14.5 KB
/
Copy pathWordleApp.java
File metadata and controls
320 lines (285 loc) · 14.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
/**
* The WordleApp program creates a clone of the very popular game Wordle,
* which you can play at https://www.powerlanguage.co.uk/wordle/.
*
* @authors Vikram Bhojanala, Kayetan Protas, Joshua Macdonald
* @version 1.0
* @since 2022-01-27
*/
import javax.swing.*; // Import Swing Class
import java.awt.*; // Import AWT Class
import javax.swing.border.Border; // Import Border Class
import java.awt.event.ActionEvent; // Import ActionEvent Class
import java.awt.event.ActionListener; // Import ActionListener Class
import java.awt.event.KeyAdapter; // Import KeyAdapter Class
import java.awt.event.KeyEvent; // Import KeyEvent Class
import java.io.FileNotFoundException; // Import FileNotFoundException Class
import java.io.IOException; // Import IOException Class
import java.io.File; // Import File Class
import java.util.Scanner; // Import the Scanner Class
public class WordleApp extends JFrame implements ActionListener {
static JTextField[] inputField = new JTextField[30];
private String wordleWord;
private int letterCount[] = new int[26];
private int lettersUsed[] = new int[26];
char alphabet[] = new char[26];
int currentIndex;
JLabel myLabel;
int guessNumber = 0;
static int seconds = 0; // Used in the timer() Method to count time
// Variable definitions
/**
* The setErrorMsg method creates an Error Message using a pop-up window, with the text param.
* @param text the error message in String format.
*/
public static void setErrorMsg(String text) {
Toolkit.getDefaultToolkit().beep();
JOptionPane optionPane = new JOptionPane(text, JOptionPane.ERROR_MESSAGE);
JDialog dialog = optionPane.createDialog("Error");
optionPane.setPreferredSize(new Dimension(500, 600));
dialog.setAlwaysOnTop(false);
dialog.setVisible(true);
}
/**
* The setWinMsg method creates an Informational Message using a pop-up window,
* telling the user that they have won the game.
* The message includes the # of seconds and guesses they took to finish the game.
* @param seconds the # of seconds the user took.
* @param seconds the # of currentIndex of the user.
*/
public static void setWinMsg(int seconds, int currentIndex) {
int guesses = (currentIndex + 1) / 5; // Calculation of guesses using the currentIndex param.
Toolkit.getDefaultToolkit().beep();
JOptionPane optionPane = new JOptionPane("You took " + seconds + " seconds!\n" + "You took " + guesses + " guesses!", JOptionPane.INFORMATION_MESSAGE);
JDialog dialog = optionPane.createDialog("You have Won!");
optionPane.setPreferredSize(new Dimension(300, 300));
dialog.setAlwaysOnTop(false);
dialog.setVisible(true);
}
/**
* The checkWord() Method checks whether the word the user has inputted is valid or not
* by checking the local 5 letter word database.
* @param word the user has inputted in String format.
* @return true if the word exists and false if it does not.
*/
public static boolean checkWord(String word) throws FileNotFoundException {
word = word.toLowerCase(); // sets the word to lowercase
char letter = Character.toLowerCase(word.charAt(0)); // Takes the first letter of the word
Scanner txtscan = new Scanner(new File("Letters\\letter_" + letter + ".txt")); // Locates the file that contains the words that start with the same letter
while (txtscan.hasNext()) {
String str = txtscan.next();
if (str.equals(word)) {
return true;
}
}
return false;
}
/**
* The generateWordle method generates a random Wordle.
* @return the word that is generated.
*/
public static String generateWordle() throws FileNotFoundException {
int num = (int)(Math.random() * (5750 - 1 + 1) + 1); // generates a number between 1 and 5750, which is the number of words in the wordbank
String word = "";
int count = 0;
Scanner txtscan = new Scanner(new File("wordbank.txt"));
while (count != num) {
count++;
word = txtscan.next();
}
word = word.toUpperCase();
return word;
}
/**
* The resetFocusParams method only allows the user to edit the 5 letter line they are currently focused on.
* It disables the user to edit any of the input fields above or below the line.
* @param currentIndex is the current index of the user.
*/
private void resetFocusParams(int currentIndex) {
int IntValue = (int) Math.round((Math.floor(currentIndex / 5.0)) * 5.0);
int IntValueMax = IntValue + 5;
System.out.println(IntValue);
for (int i = 0; i < 30; i++) {
if (i >= IntValue && i < IntValueMax) {
inputField[i].setEditable(true);
} else {
inputField[i].setEditable(false);
}
}
}
/**
* The WordleApp() Method creates the input fields for the main wordle Window.
*/
private WordleApp() throws IOException {
GridBagConstraints positionConstants;
int i, j;
setLayout(new GridBagLayout());
positionConstants = new GridBagConstraints();
wordleWord = generateWordle();
for (i = 0; i < 26; i++) {
alphabet[i] = (char)(i + 65);
letterCount[i] = 0;
lettersUsed[i] = 0;
}
for (i = 0; i < 26; i++) {
for (j = 0; j < wordleWord.length(); j++) {
if (wordleWord.charAt(j) == alphabet[i])
letterCount[i] += 1;
}
}
for (i = 0; i < 30; ++i) {
inputField[i] = new JTextField(1);
inputField[i].setEditable(false);
int IntValue = (int) Math.round((Math.floor(currentIndex / 5.0)) * 5.0);
int IntValueMax = IntValue + 5;
if (i >= IntValue && i < IntValueMax) {
inputField[i].setEditable(true);
}
inputField[i].setText("");
inputField[i].setFont(new Font("Arial", Font.BOLD, 80));
inputField[i].setBackground(Color.WHITE);
inputField[i].setForeground(Color.BLACK);
Border border = BorderFactory.createLineBorder(Color.BLACK, 3);
inputField[i].setBorder(border);
positionConstants.gridx = i % 5;
positionConstants.gridy = i / 5;
add(inputField[i], positionConstants);
inputField[i].addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent event) {
Object source = event.getSource();
JTextField field = (JTextField) source;
char inputChar = event.getKeyChar();
if (Character.isLowerCase((inputChar))) {
event.setKeyChar((Character.toUpperCase(inputChar)));
}
if (field.getText().length() >= 1) {
event.consume();
}
if (inputChar == 0) {
currentIndex -= 1;
}
if (inputChar == 8) {
if (Math.floorMod(currentIndex, 5) != 0) {
currentIndex -= 1;
inputField[currentIndex].setText(field.getText().substring(0, 0));
}
inputField[currentIndex].requestFocus();
} else {
if (Math.floorMod(currentIndex, 5) != 4) {
currentIndex += 1;
inputField[currentIndex].requestFocus();
} else {
inputField[currentIndex].setText(field.getText().substring(0, 0));
inputField[currentIndex].requestFocus();
}
}
}
});
}
JButton EnterButton; // Creates an Enter Button
EnterButton = new JButton("Enter"); // Sets the Button's text to "Enter"
EnterButton.setFont(new Font("Aldous Vertical", Font.PLAIN, 10)); // Sets the font of the button
EnterButton.setPreferredSize(new Dimension(70, 40)); // Sets the demensions of the button
positionConstants.gridx = 5; // Sets the x position of the button
positionConstants.gridy = 5; // Sets the y position of the button
positionConstants.insets = new Insets(4, 4, 4, 4); // Sets the insets of the button
add(EnterButton, positionConstants); // Adds the button to the Window
EnterButton.addActionListener(this); // Sets the button press to execute actionPerformed() method
}
/**
* The actionPerformed method compares the user word with the wordle.
* It sets the letters in the correct position to green.
* It sets the letters that are in the wrong position but are in the word to yellow.
* It sets the letters that are not in the world to grey.
* It does this by:
* 1. Creating 2, 2 multi-dimensional arrays. They will have two rows and five columns. - One will be used by the word of the app other for the user input.
* 2. Then a direct comparison of userArray[i] == appArray[i]. If they are the same make the boxes green and in the second-row mark with "U". (U stands for Unavailable and A stands for Available)
* 3. Now in this step, you will again loop through. If in the second row it is "A" which means it is still available then loop again with the appArray:
* a)First check if appArray[i,1] is available. If it is then check if they are the same. And then make it Yellow and mark userArray[i,1] and appArray[i,1] as "U".
* b)If they are not the same, set the box colour to grey.
* This executes every time the user clicks the Enter button.
*/
@Override
public void actionPerformed(ActionEvent event) {
StringBuilder word = new StringBuilder(); // Create StringBuilder word
char[] inputChar = new char[5]; // Create a char array named inputChar that has 5 spaces
for (int i = 0; i < 5; i++) {
inputChar[i] = inputField[5 * guessNumber + i].getText().charAt(0);
word.append(inputChar[i]); // Fill the StringBuilder word with the user's input
}
String singleString = word.toString(); // Set to String
char[][] appArray = new char[5][2]; // Creates a 2 demensional Array intended to hold the Wordle word
char[][] usersArray = new char[5][2]; // Creates a 2 demensional Array intended to hold the user inputted word
try {
if (checkWord(singleString)) { // Ensures the Word exists by calling the checkWord() method
for (int i = 0; i < 5; i++) {
appArray[i][0] = wordleWord.charAt(i);
usersArray[i][0] = inputChar[i];
if (inputChar[i] == wordleWord.charAt(i)) { // Check if the characters are the same
inputField[5 * guessNumber + i].setBackground(new Color(106, 170, 100)); // Sets Background Color to Green
appArray[i][1] = 'u'; // set as Unavailable
usersArray[i][1] = 'u'; // set as Unavailable
} else {
appArray[i][1] = 'a'; // set as Available
usersArray[i][1] = 'a'; // set as Available
}
}
if (singleString.equals(wordleWord)) { // Checks if the user inputted word is exactly correct
setWinMsg(seconds, currentIndex); // sends win message
}
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (appArray[i][1] == 'a') { // Check if it is Available
if (usersArray[j][1] == 'a') { // Check if it is Available
if (usersArray[j][0] == appArray[i][0]) { // Check if they are the same
inputField[5 * guessNumber + j].setBackground(new Color(201, 180, 88)); // Sets Background Color to Yellow
appArray[i][1] = 'u'; // set as Unavailable
usersArray[j][1] = 'u'; // set as Unavailable
} else { // If they are not the same, set as grey
inputField[5 * guessNumber + j].setBackground(new Color(129, 131, 132)); // Sets Background Color to Grey
}
}
}
}
}
guessNumber += 1;
currentIndex = guessNumber * 5;
inputField[currentIndex].requestFocus();
resetFocusParams(currentIndex);
} else {
setErrorMsg("Word does not exist."); // Sends Error Message if the word does not exist
}
} catch (FileNotFoundException e1) {}
}
/**
* The timer method creates a Thread timer that is used to track the entire time the program has been running,
* by adding to seconds every 1000 milliseconds.
* Once the program has stopped, the method stops adding to seconds.
*/
public static Thread timer = new Thread() {
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
seconds += 1;
}
}
};
/**
* The main method creates a JFrame called myFrame that contains all the contents of the app.
*/
public static void main(String[] args) throws IOException {
timer.start(); // starts the timer
WordleApp myFrame = new WordleApp(); // creates the JFrame
myFrame.setResizable(false); // Doesn't allow the window to be resized
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Exit the application using the System exit method once the window has been closed
myFrame.setBackground(Color.WHITE); // Sets the background color to white
myFrame.getRootPane().setBorder(BorderFactory.createMatteBorder(4, 4, 4, 4, Color.LIGHT_GRAY)); // Sets a Light Grey border
myFrame.pack(); // Causes this Window to be sized to fit the preferred size and layouts of its subcomponents
myFrame.setVisible(true); // Sets the Frame to visable
}
}