I have created a game where I summon JTextFields at random X-position at the top of the screen with random words added to the fields.
I don't know how to properly setup a method to check if the input from the user equals the JTextFields words on the board. I'm looking for any ideas to change the "checkWordSpelling" method inside of my "GamePanel" class to make the comparison between the JTextFields word and the users input viable.
Right now I store the object in:
ArrayList<EnemyTextFields> textFieldsCurrentlyOnBoard = new ArrayList<>();
to begin with I thought this would be a good idea because I could track the current object to the String it has but since it's a thread(and I want each JTextField to be a thread) I could not compare them(?).
I've tried replacing my ArrayList with a HashMap which takes the currentThread and String(k,v) but the way i implemented it, neither did that work. I've tried alot of different stuff but I can't name them all.
I have the "EnemyTextField" private class inside of the "GamePanel" class. This is where each JTextField is a separate Thread:
private class EnemyTextField extends Thread {
private Random rng;
private int xPlace, yPlace;
private JTextField txtField;
private String currWord;
private int velocityOfTextField;
public EnemyTextField(String currWord,int velocityOfTextField) {
this.currWord = currWord;
this.velocityOfTextField = velocityOfTextField;
rng = new Random();
xPlace = rng.nextInt(600);
txtField = new JTextField(currWord);
}
/**
* Check if the textfield hits the bottom of the screen, and if it does, the application ends
* @return
*/
public boolean hitBottomOfScreen() {
if(yPlace >= height){
endGame();
return true;
}
return false;
}
/**
* Increments the textfield which belongs to the thread by 10.
*/
public void updateEnemyTextField() {
yPlace = yPlace +10;
txtField.setLocation(xPlace, yPlace);
}
/**
* adding the textfield to the JPanel(UI)
*/
public void createTextField(){
txtField.setLocation(xPlace, yPlace);
txtField.setSize(50+(currWord.length()*2), 50);
txtField.setBackground(Color.GREEN);
add(txtField);
}
@Override
public void run() {
while(!hitBottomOfScreen()) {
try {
//Sleeping for 1 second(1000milliseconds) between each "tick" or "refresh/update".
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
createTextField();
updateEnemyTextField();
}
}
}
}
Here i have the JPanel code which the JTextFields are created on:
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.util.*;
import java.util.Timer;
public class GamePanel extends JPanel {
private JTextField guessingTextField;
private Label pointLabel;
private Label timeLabel;
private int width = 800;
private int height = 600;
private int currentTime;
private int points;
//Here is the Array of all the words from the textfile
ArrayList<String> listOfWordsFromFile;
//Here is where i save the k,v for the different JTextFields
ArrayList<EnemyTextField> textFieldsCurrentlyOnBoard;
private Timer timer;
public GamePanel() throws IOException {
setSize(width, height);
setLayout(null);
setBackground(Color.LIGHT_GRAY);
guessingTextField = new JTextField();
guessingTextField.setSize(120, 30);
guessingTextField.setLocation(width / 2 - 60, 530);
guessingTextField.setForeground(Color.BLACK);
guessingTextField.setBackground(Color.WHITE);
pointLabel = new Label();
pointLabel.setBackground(Color.WHITE);
pointLabel.setForeground(Color.BLACK);
pointLabel.setSize(120, 30);
pointLabel.setLocation(140, 1);
timeLabel = new Label();
timeLabel.setBackground(Color.WHITE);
timeLabel.setForeground(Color.BLACK);
timeLabel.setSize(30,30);
timeLabel.setLocation(155,1);
timeLabel.setText("1");
add(timeLabel);
add(pointLabel);
add(guessingTextField);
//inserts the ArrayList of words into "words" array.
listOfWordsFromFile = WordBox.getRandomWord("resources/Random words.txt");
setVisible(true);
guessingTextField.addActionListener(e -> {
//checkWord();
});
startTheGameAndResetValues();
checkWordSpelling();
}
/**
*This is the Method im struggling with.
*/
public void checkWordSpelling(){
Thread thread = new Thread(() -> {
while(true) {
try {
System.out.println(guessingTextField.getText());
java.util.Iterator<EnemyTextField> iterator = textFieldsCurrentlyOnBoard.iterator();
while(iterator.hasNext()){
EnemyTextField currentWord = iterator.next();
System.out.println(currentWord);
//
if(currentWord.equals(guessingTextField.getText())){
remove(currentWord.txtField);
iterator.remove();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}
/*private void removeWord(EnemyTextField entry) {
java.util.Iterator<EnemyTextField> iterator = textFieldsCurrentlyOnBoard.values().iterator();
while (iterator.hasNext()){
EnemyTextField current = iterator.next();
if (textFieldsCurrentlyOnBoard.containsKey(entry)) {
remove(current.txtField);
iterator.remove();
}
}
}*/
/**
* gets called when game is over, displays an ending "popup".
*/
public void endGame() {
//cancel the while loop and make the game stop
JOptionPane.showInputDialog(null,"You lost, Game over.");
timer.cancel();
}
/**
* Method to reset all the values from what the previous round had.
*
* Creates a TimerTask which acts as the measurement of difficulty
* set to 3000milliseconds(3seconds), lower it to have words appear
* more frequently and higher it if you want the words to appear slower
*/
public void startTheGameAndResetValues() {
currentTime = 0;
points = 0;
textFieldsCurrentlyOnBoard = new ArrayList<>();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
while(true){
initNewWord();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Timer time = new Timer();
time.schedule(timerTask,3000);
}
/**
* starts the "threading"
*/
public void initNewWord(){
String rngWord = randomWord();
EnemyTextField newWordForTextField = new EnemyTextField(rngWord,2);
//textFieldsCurrentlyOnBoard.add(newWordForTextField);
textFieldsCurrentlyOnBoard.add(newWordForTextField);
newWordForTextField.start();
}
/**
* Picks a random word from the ArrayList words.
* @return
*/
public String randomWord() {
Random rng = new Random();
System.out.println(listOfWordsFromFile);
int rngIndex = rng.nextInt(listOfWordsFromFile.size());
return listOfWordsFromFile.get(rngIndex);
}
Here is the "WordBox" class which grabs the words from "Random words.txt" in resource directory:
import java.io.*;
import java.util.ArrayList;
public class WordBox {
static ArrayList<String> listWords = new ArrayList<>();
/**
* Grabs all the words and puts each word
* @param filePath Grabs filepath from GamePanel
* @return ArrayList of all the words in the textfile.
* @throws IOException
*/
public static ArrayList<String> getRandomWord(String filePath) throws IOException {
try {
File file = new File(filePath);
BufferedReader br = new BufferedReader(new FileReader(file));
listWords = new ArrayList<>();
String strTemp;
while((strTemp = br.readLine())!= null) {
listWords.add(strTemp);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(listWords);
return listWords;
}
}
And here is my Main method:
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
new GameFrame();
}
}
Here are some random words that you can put into the "Random words.txt" file for anyone interested in testing my code:
flowers
skillful
home
channel
delirious
muddled
aware
blushing
unpack
neck
animated
supreme
snow
connect
skin
Besides the problem if anyone finds any way I could improve my code, i'm very open to suggestions and guidelines!
If you are using array-list to store the data then use this method
ArrayList<String> JtextFiels = new ArrayList<String>();
JtextFiels.add("flowers");
JtextFiels.add("skillful");
JtextFiels.add("home");
JtextFiels.add("channel");
// I assume that user input is stored in a variable and for this case it is store in " userInput " variable
now here you have your array-list and user input store in a variable
if(JtextFiels.contains(userInput.trim())//here JtextFiels are your arraylist and userInput has the data stored which was entered by user
{
//here you can continue your code ..for example - "show a message that the user entered word is there in the falling words"
}
Here you can face a problem if the user entered data is in capital or a single letter that is in capital
So what you can do it
if(JtextFiels.contains(userInput.trim().toLowerCase())// Or .toUpperCase()
{
// here the user entered text is converted to lower case ...you can change it upper case according to your requirement
}
OR
You can use an array to store the data, I will tell you the difference at the end.
String[] JtextFiels=new String[100];//here 100 is the size of the array
JtextFiels[0]="flowers";//index 0
JtextFiels[1]="skillful";//index 1
JtextFiels[2]="home";//index 2
JtextFiels[3]="channel";//index 3
//arrays start from the index 0
//same as above you have the user entered data with you stored in a variable ..in this case let the variable be userInput
Here you have an array and user entered data
for(int i=0;i<JtextFiels.length;i++)//here a loop is used to iterate over each index of array
{
if(JtextFiels[i]!=null)//checks if the index exists or not
{
if(JtextFiels[i].trim().equalsIgnoreCase(userInput.trim()))
{
//here you can continue your code ..for example - "show a message that the user inputed word is there in the falling words"
}
}
}
The difference between the two is:
ArrayList
Array
Many more differences but for now this much is enough.
What should you choose? Arraylist or array?
It depends on your data:
if the number of falling words are fixed or you know the maximum words .. then use the array
if then number of falling words are not fixed or limit and you don't know how many words u use and if the words are dynamically changing then use arraylist
If hope you understood this! If not feel free to ask your questions