views:

144

answers:

3

Hello, I am trying to write a program in Java that takes a random number from 1-1000 and then as the guess it the background color changes to blue(cold) or red(warm) if they are in the number. I am new to java GUI, but I think the rest of the logic is right, not sure. It compiles, but the guess button doesn't work. Any guidance will be appreciated.

package guessGame;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.color.*;
import java.util.Random;


import java.util.Random;
import java.util.logging.FileHandler;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class GuessGame extends JFrame
{
    private JFrame mainFrame;
    private JButton GuessButton;
    private JButton QuitButton;
    private JLabel prompt1, prompt2;
    private JTextField userInput;
    private JLabel comment = new JLabel("What is your destiny?");
    private JLabel comment2 = new JLabel (" ");
    //private int number, guessCount;
    //private int lastGuess;
    private int randomNumber;
    private Color background;


    public GuessGame()
    {
        mainFrame = new JFrame ("Guessing Game!");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //Creates components
        GuessButton = new JButton("Guess");
        QuitButton  = new JButton("Quit");
        prompt1 = new JLabel("I have a number between 1 and 1000.");
        prompt2 = new JLabel("Can you guess my number? Enter your Guess:");
        comment = new JLabel ("What is your destiny?");
        comment2 = new JLabel (" ");
        userInput = new JTextField(5);
        //userInput.addActionListener(new GuessHandler());

        //content pane
        Container c = mainFrame.getContentPane();
        c.setLayout(new FlowLayout());

        //adding component to the pane
        c.add(prompt1);
        c.add(prompt2);
        c.add(userInput);
        c.add(comment2);
        c.add(GuessButton);
        c.add(QuitButton);
        c.add(comment);

        GuessButton.setMnemonic('G');
        QuitButton.setMnemonic('Q');

        mainFrame.setSize(300,200);
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setVisible(true);
        mainFrame.setResizable(false);

        // define and register window event handler
    //  mainFrame.addWindowListener(new WindowAdapter() {
    //      public void windowClosing(WindowEvent e) 
    //      { System.exit(0); }
    //  });

        //creating the handler
        GuessButtonHandler ghandler = new GuessButtonHandler(); //instantiate new object
        GuessButton.addActionListener(ghandler); // add event listener

        QuitButtonHandler qhandler = new QuitButtonHandler(); 
        QuitButton.addActionListener(qhandler); 



    }

    public void paint (Graphics g)
    {
        super.paint(g);
        setBackground(background);
    }

    class QuitButtonHandler implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            System.exit(0);
        }
    }

    class GuessButtonHandler implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            int getUserInput=0;
            int diff;
            int Difference;
            randomNumber = new Random().nextInt(1001);
            try {
                getUserInput = Integer.parseInt(
                        userInput.getText().trim());
            } catch (NumberFormatException ex){
                comment.setText("Enter a VALID number!");
                return;
            }
            if (getUserInput == randomNumber){
                JOptionPane.showMessageDialog(null, "CONGRATULATIONS! You got it!!",
                        "Random Number: " + randomNumber, 
                        JOptionPane.INFORMATION_MESSAGE);
                randomNumber = new Random().nextInt(1000) + 1;
                return;
            }
            if (getUserInput > randomNumber){
                comment.setText( "Too High. Try a lower number." );
                diff=getUserInput - randomNumber;
                Difference=Math.abs(diff);
            } else {
                comment.setText( "Too Low. Try a higher number." );
                diff=randomNumber - getUserInput;
                Difference=Math.abs(diff);
            }

            if(Difference<=25){
                comment2.setText("Cold");
                setBackgroundColor(Color.blue);
            }

            if(Difference<=10){
                comment2.setText("Warm");
                setBackgroundColor(Color.red);
            }

            else {
            }
        }
        private void setBackgroundColor(Color color) {
               setBackgroundColor(color);
            }
    }


    public static void main(String args[]) {
        //instantiate gueesgame object
        GuessGame app = new GuessGame();

    }
}
+1  A: 

You have more Swing components than you need, and you seem to be adding one set to the frame while manipulating another set. For example, you have two JTextFields, fieldBox and userInput. You add userInput to the frame, but check fieldBox for input in the Guess button handler. Since fieldBox is always empty, the NumberFormatException is caught by your exception handler (which should really just catch NumberFormatException, not Exception), and comment is updated with "Enter a VALID number!". However, just like with the double text area, comment isn't actually added to the frame, prompt1 and prompt2 are, so you can't see the change

Michael Mrozek
Ok, so I fixed the comment part, and it works and shows now, and I changed it to numberFormatException, but I am a bit confused what you mean and what I should do with the fieldBox for the input.
David
@David You have two JTextFields, `fieldBox` and `userInput`, and you use `fieldBox` in some places and `userInput` in other places. You only need one, for the user to type in. You need to pick one, delete the other, and change all the uses to the one you kept
Michael Mrozek
Oh sweet it is working now. If you could help me once more it would be outstanding, the background colors aren't changing accordingly. And every time I run it, the first random number is always 0, and then it changes to a new number.
David
You reset the randomNumber field in GuessButtonHandler, which is run every time the guess button is clicked.
Jes
+1  A: 

I would write your logic without a UI first and test it until it was 100% correct. Just use a command line, text UI at first. Once that's done, put a GUI in front of it. It'll help to isolate your problems: once the text-driven logic is right, you'll know that future problems are due to UI.

It makes your MVC separation cleaner as well.

duffymo
+3  A: 

The colors aren't changing because your setBackgroundColor always uses Color.black. Change it to:

private void setBackgroundColor(Color color) {
   setBackground(color);
}

As for the number always being zero. You do not instantiate the randomNumber field. Add this to your constructor:

randomNumber = new Random().nextInt(1001);

Another problem I noticed was you added a window listener to ensure the program exits when you close the window. This is implemented in JFrame. In the constructor add:

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Instead of using the deprecated method:

mainFrame.show();

use the not deprecated:

mainFrame.setVisible(true);

Furthermore you have a field, which is never queried:

private Color background;

It's best to do the logic before connecting it to the gui. It's a lot easier to test and find the worst bugs.

Refactored code:

  import javax.swing.*;
  import java.awt.*;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.util.Random;

  public class GuessGame extends JFrame {
     private JTextField userInput;
     private JLabel comment = new JLabel("What is your destiny?");
     private JLabel comment2 = new JLabel(" ");

     private int randomNumber;

     public GuessGame() {
        super("Guessing Game!");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Creates components
        JButton guessButton = new JButton("Guess");
        JButton quitButton = new JButton("Quit");
        JLabel prompt1 = new JLabel("I have a number between 1 and 1000.");
        JLabel prompt2 = new JLabel("Can you guess my number? Enter your Guess:");

        comment = new JLabel("What is your destiny?");
        comment2 = new JLabel(" ");
        userInput = new JTextField(5);

        //content pane
        Container c = getContentPane();
        setLayout(new FlowLayout());

        //adding component to the pane
        c.add(prompt1);
        c.add(prompt2);
        c.add(userInput);
        c.add(comment2);
        c.add(guessButton);
        c.add(quitButton);
        c.add(comment);

        guessButton.setMnemonic('G');
        quitButton.setMnemonic('Q');

        setSize(300, 200);
        setLocationRelativeTo(null);
        setVisible(true);
        setResizable(false);

        initializeNumber();

        //creating the handler
        GuessButtonHandler ghandler = new GuessButtonHandler(); //instantiate new object
        guessButton.addActionListener(ghandler); // add event listener

        QuitButtonHandler qhandler = new QuitButtonHandler();
        quitButton.addActionListener(qhandler);
     }

     private void initializeNumber() {
        randomNumber = new Random().nextInt(1000) + 1;
     }

     class QuitButtonHandler implements ActionListener {
        public void actionPerformed(ActionEvent e) {
           System.exit(0);
        }
     }

     class GuessButtonHandler implements ActionListener {
        public void actionPerformed(ActionEvent e) {
           int getUserInput;
           int diff;
           int Difference;
           try {
              getUserInput = Integer.parseInt(userInput.getText().trim());
              if (getUserInput == randomNumber) {
                 JOptionPane.showMessageDialog(null, "CONGRATULATIONS! You got it!!",
                         "Random Number: " + randomNumber,
                         JOptionPane.INFORMATION_MESSAGE);
                 initializeNumber();
                 return;
              }
              if (getUserInput > randomNumber) {
                 comment.setText("Too High. Try a lower number.");
                 diff = getUserInput - randomNumber;
                 Difference = Math.abs(diff);
              } else {
                 comment.setText("Too Low. Try a higher number.");
                 diff = randomNumber - getUserInput;
                 Difference = Math.abs(diff);
              }

              if (Difference <= 25) {
                 comment2.setText("Cold");
                 GuessGame.this.setBackgroundColor(Color.blue);
              }

              if (Difference <= 10) {
                 comment2.setText("Warm");
                 GuessGame.this.setBackgroundColor(Color.red);
              }
           } catch (NumberFormatException ex) {
              comment.setText("Enter a VALID number!");
           }
        }


     }

     private void setBackgroundColor(Color color) {
        getContentPane().setBackground(color);
     }

     public static void main(String args[]) {
        //instantiate gueesgame object
        GuessGame app = new GuessGame();

     }
  }
Jes
Thanks man, that helps a lot, but I am still getting no colors, along with this error:at guessGame.GuessGame$GuessButtonHandler.setBackgroundColor(GuessGame.java:143) at guessGame.GuessGame$GuessButtonHandler.setBackgroundColor(GuessGame.java:143) at guessGame.GuessGame$GuessButtonHandler.setBackgroundColor(GuessGame.java:143)And when I narrow it down, like 244 (it says too low) and then 245 (it says its too high), so I am not sure.
David
It would help if you posted the updated code. I am not sure why the background isn't changed, and even less sure how it happens that 245 is too high and 244 is too low.
Jes
I have kept the code updated, and I have just changed it again with what I have edited.
David
@David: You're getting a stack overflow because setBackgroundColor just calls itself infinitely. The answer asked you to call `setBackground`, not `setBackgroundColor`. I don't think you even need the method `setBackgroundColor` nor do you need to override the behaviour of paint(). Just call `setBackground(Color.RED)` followed by `repaint()`.
Mark Peters
See the edited code in the answer. I've also refactored it for you so it's a little cleaner. You had, as Mark says, setBackground calling itself, which led to an overflow. You also had some minor field naming issues, guessButton was named GuessButton. It was no semantic issue, but non the less it looks weird.You had a return statement in your buttons action handler. Avoid unconditional breaks. I refactored it so the number checking etc. gets done within the try block.Furthermore I've removed the mainFrame field, which was not needed, since GuessGame extends JFrame. Take a look at the code.
Jes
Remember to accept the answer.
Jes