0

New to java here, and I am attempting my first project with GUI. I have a GameConsole class that contains gamePlay() and userTurn(). I have a ButtonListener class that constructs the button with an actionListener that calls userTurn(). However, every time that the button is pressed, I get a NullPointerException. Why is this happening and what do I do to fix it?

Relevant code:

public static final void main (String[] args){
    GameConsole game = new GameConsole();
    game.gamePlay();
}

public class GameConsole {
    public Player user;
    public Player dealer;
    public Deck playingDeck;
    ValidateInput validate = new ValidateInput();

public void gamePlay(){
    //get info from user
    user.addToHand(playingDeck.getTopCard());
    dealer.addToHand(playingDeck.getTopCard());
    user.addToHand(playingDeck.getTopCard());
    dealer.addToHand(playingDeck.getTopCard());

    userTurn();
}

public void userTurn(){
    boolean turn = true;
    do{   //the code breaks at this point. On the first round of gameplay I get the exception pasted
          //below. The second round (after the button is pressed) I get an 
          //Exception in thread "AWT-EventQueue-0      bringing me back here
        JOptionPane.showMessageDialog(null, "The cards you were dealt are: \n" + user.printHand());

        if(user.sumOfHand() == 21){  //no need to continue if user has 21
            System.out.println("You win this round.");
            break;
        } else if (user.sumOfHand() > 21){
            System.out.println("You have busted. You lose this round.");
            break;
        }


        String HSInput = null;
        for(int x = 0; x < 1;){
        HSInput = JOptionPane.showInputDialog("\nThe dealer is showing a " + dealer.getTopCard()
                + "\nYou are currently at " + user.sumOfHand()
                + "\n\nWhat would you like to do?\nHit (H) or Stay (S)?");
        if(validate.containDesiredString(HSInput, "HhSs")) //only accept h and s either caps
            x++;
        }


        if(HSInput.equalsIgnoreCase("H")){  //if the user wants to stay
            user.addToHand(playingDeck.getTopCard()); //deal new card then repeat loop
        } 
        else {
            turn = false;
            }
    } while (turn == true);
}

And the ButtonListener class...

public class ButtonListener implements ActionListener {

    JButton newRoundButton;

    public ButtonListener(JPanel endGamePanel){

        newRoundButton = new JButton("Start another round");
        newRoundButton.setPreferredSize(new Dimension(150, 50));
        endGamePanel.add(newRoundButton);
        newRoundButton.addActionListener(this);

    }


    @Override
    public void actionPerformed(ActionEvent e) {        
        if(e.getSource() == newRoundButton){
            System.out.println("Hi there for a new round");
                     //I know that this method is entered into because this line will print
            GameConsole game = new GameConsole();
            game.userTurn();
        }
    }

I am desperately lost and have been going in circles for the last 2 days. Right now the program won't even enter the userTurn(). I have no idea what I did because a couple hours ago that wasn't a problem. Either way, my ultimate problem is that I can't get the ButtonListener to call the userTurn() class. Why am I now getting a NullPointerException for the userTurn() and what can I do to make the ActionListener call the userTurn() without giving a NullPointerException?

-Hopelessly Lost... ANY help is appreciated!

EDIT: Stack Trace Exception in thread "main" jav

a.lang.NullPointerException
    at blackjackControls.GameConsole.userTurn(GameConsole.java:180)
    at blackjackControls.GameConsole.gamePlay(GameConsole.java:119)
    at blackjackControls.Main.main(Main.java:7)

since it is no longer going into the userTurn() I can't post the trace for that. It did state that it was a thread in the AWT

ButtonListener class has been combined with existing ResultPane class. Full code is:

public class ResultPanel extends JFrame {

    JFrame frame = new JFrame("Blackjack Game");
    JPanel endGamePanel = new JPanel();
    ImageIcon image;
    JLabel lbl;
    JButton newRoundButton;
    JButton endButton;

    public ResultPanel(){

        frame.setSize(800, 600);
        frame.getContentPane().add(endGamePanel);   //add the panel to the frame
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);       

        JButton newRoundButton= new JButton("Start another round");
        newRoundButton.setPreferredSize(new Dimension(150, 50));
//      newRoundButton.addActionListener();
        newRoundButton.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {

                System.out.println("Hi there for a new round");
                GameConsole game = new GameConsole();
                game.userTurn();
            }
        });


        frame.setVisible(true);
    }

    public void winGame(){
        image = new ImageIcon(getClass().getResource("win.jpg"));
        lbl = new JLabel (image);
        endGamePanel.add(lbl);

        frame.setVisible(true);
    }
L. Morrell
  • 45
  • 10
  • 1
    On which specific line is the NPE? Are you sure you have assigned values to user, dealer, and playingDeck? – Vineet Kosaraju Dec 11 '14 at 23:18
  • 2
    Consider providing a [runnable example](https://stackoverflow.com/help/mcve) which demonstrates your problem. This will result in less confusion and better responses – MadProgrammer Dec 11 '14 at 23:21
  • 2
    My "guess" is, `user` is `null`... – MadProgrammer Dec 11 '14 at 23:22
  • 1
    *"New to java here, and I am attempting my first project with GUI."* A programmer should be familiar with how to solve an NPE *before* they attempt to make a GUI! See [What is a stack trace, and how can I use it to debug my application errors?](http://stackoverflow.com/q/3988788/418556) & [What is a Null Pointer Exception, and how do I fix it?](http://stackoverflow.com/q/218384/418556) – Andrew Thompson Dec 11 '14 at 23:26
  • Stack trace is posted and I have verified that user is not null. I have printed data contained in the object before the spot in which the program breaks. right not it is breaking in the line with the first JOptionPane in userTurn() – L. Morrell Dec 11 '14 at 23:38
  • `at blackjackControls.GameConsole.userTurn(GameConsole.java:180)` We cannot tell which is line `180`, but.. For better help sooner, post an [MCVE](http://stackoverflow.com/help/mcve) (Minimal Complete Verifiable Example) or [SSCCE](http://www.sscce.org/) (Short, Self Contained, Correct Example) with a stack trace for the short complete code. – Andrew Thompson Dec 12 '14 at 01:06

3 Answers3

1

As far as I can see you create a new GameConsole object in your main, so I assume this is the object the whole game is played on. If this is the case, why does your button create a new GameConsole object? I assume you're getting a NullPointerException because your button calls the userTurn() method on a new GameConsole object that doesn't have a User object yet, so user.sumOfHand() for example would throw the exception.

Your button should call the userTurn method on the GameConsole object you created in your main, not on a new one.

Code Suggestion:

JButton newRoundButton= new JButton("Start another round");
newRoundButton.setPreferedSize(new Dimension(150, 50));
newRoundButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Hi there for a new round");
        game.userTurn();
    }
});
endGamePanel.add(newRoundButton);

This is assuming that whatever class builds your panel knows about your GameConsole object. If this class is the GameConsole object itself, just remove game. If an object of that class is created in your GameConsole object, just pass your GameConsole object to that class with a parameter GameConsole game in that classes constructor and, if needed make it a field in that class. To pass your GameConsole object from that object, pass this.

Marv
  • 3,517
  • 2
  • 22
  • 47
  • Yes, the whole game is played on GameConsole. How would I use the game object created in main? I keep getting static errors. – L. Morrell Dec 11 '14 at 23:44
  • You could make `GameConsole game` a parameter of your `ButtonListener` construcor and make a field `GameConsole game` in the `ButtonListener` class. Then initialize the field in the constructor. Now you can call `game.userTurn()` inside the `ButtonListener` class without having to create a new `GameConsole` object. – Marv Dec 12 '14 at 00:01
  • The way it is designed, ButtonListener is indirectly called from Game Console. So I would have to go from main() to userTurn() which constructs my ResultPanel class which constructs ButtonListener within that constructor. When I designed it, it all made logical sense, but is passing a paramenter that far down the line good practice? Is there a more direct way? I understand I left that part out of the original information, but this is a rather large program (for what I am used to working with). – L. Morrell Dec 12 '14 at 00:25
  • I usually pass my controller to my UI classes (frames, panels) and as far as I can tell this is a good way to relay information to your UI. One thing I don't understand though is why you are making your buttons ActionListener a seperate class. I would suggest to just add your button directly to your panel. I've updated my original answer with the code. – Marv Dec 12 '14 at 00:37
  • Thank you for being so thorough. I split up the button into another class because I had two buttons (in the same buttonListener class) and I saw a couple tutorials in which the same was done. It made sense to me because a button is its own object with its own properties/actions. I am now getting the same Exception in thread "AWT-EventQueue-0". This occurs at the same place where I am still getting the first NullPointerException. I updated the code to show you exactly where. Thanks so much! – L. Morrell Dec 12 '14 at 01:39
  • Okay, you're still creaing a new `GameConsole` object in your buttons ActionListener. Remove `GameConsole game = new GameConsole();` because **this creates a new game** and you said that the whole game is played on one `GameConsole` object. Change your `ResultPanel`'s constructor to `public ResultPanel(GameConsole game)` and pass your `GameConsole` object to the panel when calling the constructor. That way your button can call the `userTurn()` method on your original `GameConsole` object and as far as I can tell that's what you desire. – Marv Dec 12 '14 at 01:46
  • Sorry. I didn't see the comment come in last night. I did that now, but in main() since game is in main, I now am getting "cannot refer to a non-final variable game inside and inner class defined in a different manner". I feel like I am going in circles and I know I am missing a huge concept. – L. Morrell Dec 12 '14 at 18:16
  • Try declaring your `ResultPanel`'s `GameConsole` field final. See [Cannot refer to a non-final variable inside an inner class defined in a different method](http://stackoverflow.com/questions/1299837/cannot-refer-to-a-non-final-variable-inside-an-inner-class-defined-in-a-differen) for more information on that error. – Marv Dec 12 '14 at 18:53
  • I ended up having to backtrack and take out the final. See the answer solution I posted. You still helped HUGELY. It makes a ton more sense to have the window called in main() – L. Morrell Dec 12 '14 at 21:29
  • No problem. If my answer has helped you, please consider accepting it. Also see [Accepting Answers: How does it work?](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235) for more information. – Marv Dec 12 '14 at 21:43
0

You need to inizialise your objects.

 public class GameConsole {
    public Player user = new Player();
    public Player dealer = new Player();
    public Deck playingDeck = new Deck();

This is how you could do it

Tilion
  • 103
  • 4
  • 10
  • I initialized in the gamePlay() method. I declared on the class level because I wanted to make them available to both methods. – L. Morrell Dec 11 '14 at 23:48
0

After looking at over 1100 lines of code, I user was null because I declared it again in gamePlay() which made it a local variable. ONE WORD stumped me for 3 days. Argh!

L. Morrell
  • 45
  • 10