简体   繁体   中英

Creating a typing-game in java swing, i'm having issues with checking if player input equals the falling words

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.

The game looks like this: 左上角的白色标签是点数。每个绿色矩形都是一个等待被淘汰的 JTextField。底部白色矩形是 TextArea,用户将在其中输入要删除的单词。

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 inputed word is there in the falling words"
}

here you can face a problem if the user inputed data is in captial or a single letter that is in captial

so what you can do it

if(JtextFiels.contains(userInput.trim().toLowerCase())// Or .toUpperCase()
{
  //here the user inputed 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 inputed data with you stored in a variable ..in this case let the variable be userInput

Here U have An Array And userInputed data

for(int i=0;i<JtextFiels.length;i++)//here a loop is used to itterate through 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"
      }
   }
}

NOW THE DIFFERENCE BETWEEN THE TWO IS

ArrayList -The Size Is Not Fixed

Array -The size is fixed by the us

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 dont know how many words u use and if the words are dynamically changing then use arraylist

If Hope U Understood This, , if not feel free to ask your queries

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM