Reputation: 31
So I am creating a number guessing game. The computer generates a random number, the user inputs a guess, then the computer lets the user know if they've won, or if the guess was less than or more than the random number. This goes on until they've got it right, or press play again (which resets it).
I want to count and display the number of guesses a user makes each round. So I am incrementing 'tallyValue' for each guess. I know it is counting and incrementing the values correctly. However for instance if the user guesses twice in a row values that are less than the random number, then the tally value doesn't update on the .setText output. It will only update when the users guesses alternate from less than the random number to more than the random number.
What am I missing? I've tried removing and then setting the text but I don't understand why this happens.
MyFrame() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //exit out of app
this.setLayout(new FlowLayout());
//add labels, buttons and input fields
button = new JButton("Submit");
button.addActionListener(this); //can just pass in this because we already pass actionlistener above
JLabel instruction = new JLabel();
instruction.setText("Input Your Guess (must be between 1 and 100");
textField = new JTextField();
textField.setPreferredSize(new Dimension(250,40));
tally = new JLabel();
tally.setText("Number of guesses: " + tallyValue);
outputMessage = new JLabel();
outputMessage.setText("Take a guess!");
playAgainButton = new JButton("Play Again");
playAgainButton.addActionListener(this);
this.add(instruction);
this.add(textField);
this.add(button);
this.add(playAgainButton);
this.add(outputMessage);
this.add(tally);
this.setTitle("Number Guessing Game");
this.setVisible(true); //make frame visible
this.pack(); //frame size adjusts to components
ImageIcon icon = new ImageIcon("res/game-icon.png"); //creates an image icon
this.setIconImage(icon.getImage());//changes icon of frame
System.out.println(randomNumber); //for testing purposes
}
//add any unimplemented methods because we are using an interface
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==button) {
int textFieldValue;
this.remove(outputMessage);
try {
textFieldValue = Integer.parseInt(textField.getText());
//if guess is correct
if(textFieldValue == randomNumber) {
outputMessage.setText("Congratulations you guessed correctly!");
this.add(outputMessage);
tallyValue++;
displayCount(tallyValue);
this.pack();
textFieldValue = 0; //reset text field val
}
//if guess is less than randomNumber
if(textFieldValue < randomNumber) {
outputMessage.setText("Incorrect - the number I am thinking of is more than that");
this.add(outputMessage);
tallyValue++;
displayCount(tallyValue);
this.pack();
textFieldValue = 0; //reset text field val
}
//if guess is more than randomNumber
if(textFieldValue > randomNumber) {
outputMessage.setText("Incorrect - the number I am thinking of is less than that");
this.add(outputMessage);
tallyValue++;
System.out.println(tallyValue);
displayCount(tallyValue);
this.pack();
textFieldValue = 0; //reset text field val
}
}
catch (NumberFormatException ex){
outputMessage.setText("You must insert a valid number");
this.add(outputMessage);
this.pack();
}
}
if(e.getSource()==playAgainButton) {
System.out.println("pa");
this.remove(outputMessage);
randomNumber = rand.nextInt(101);
outputMessage.setText("Take a guess!");
this.add(outputMessage);
tallyValue = 0;
displayCount(tallyValue);
this.pack();
}
}
private void displayCount (int tv) {
this.remove(tally);
tally.setText("Number of guesses:" + tv);
this.add(tally);
this.pack();
}
Upvotes: 0
Views: 143
Reputation: 324137
It will only update when the users guesses alternate from less than the random number to more than the random number.
There is no need to increment the tally in 3 different places. The tally should be incremented right after you Integer.parseInt(...) statement. That is it will be updated every guess, no matter what the guess is.
Then you would just update the text of your tally label with the new count. There is no need to remove/add the label from the frame. There is no need to pack() the frame. Just setting the text will cause the label to repaint. So there is no need for the displayCount() method.
You should also be learning how to use layout manager correctly. Currently you are using a FlowLayout will will just cause the components to display in a row and then wrap to the next line. This is not a very effective layout as all the components will shift if the frame is ever resized.
Read the Swing tutorial on Layout Managers. You can nest panels with different layout managers to achieve a more flexible layout.
textField = new JTextField();
textField.setPreferredSize(new Dimension(250,40));
Don't use magic numbers for the size of a component. Instead use the API properly so the text field can determine its own preferred size:
textField = new JTextField(10);
The "10" will allow the text field to size itself to display 10 "W" characters before scrolling of the text.
Also, you should not use a shared ActionListener for your buttons.
One approach is to use a lamba to separate the functionality:
//playAgainButton.addActionListener(this);
playAgainButton.addActionListener((e) -> playAgain());
Then you create a private method playAgain()
in your class. Now the code is separated into methods by function.
Upvotes: 3