0

I'm making a Checkers game in java and I'm trying to use a GUI to do so. I get a successful build message, but when I try to run my program it says this:

Exception in thread "main" java.lang.NullPointerException at java.awt.Container.addImpl(Container.java:1097) at java.awt.Container.add(Container.java:417) at finalproject.Checkers.(Checkers.java:71) at finalproject.Checkers.main(Checkers.java:25) Java Result: 1

Line 71 in Checkers: add(newGameButton);

Line 25 in Checkers: Checkers content = new Checkers();

I don't understand why main is not running. Please help me. I have two other class called "CheckerMove" and "Play".

Red player is ==1, black player is == 2, red king is == 3, black king == 4, empty space == 0.

package finalproject;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.ArrayList;

public class Checkers extends JPanel {

    /**
     * Main routine makes it possible to run Checkers as a stand-alone
     * application.  Opens a window showing a Checkers panel; the program
     * ends when the user closes the window.
     */
    public static void main(String[] args) {
        System.out.println("Hello");
        JFrame window = new JFrame("Checkers");
        Checkers content = new Checkers();
        window.setContentPane(content);
        window.pack();
        Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize();
        window.setLocation((screensize.width - window.getWidth()) / 2, (screensize.height - window.getHeight()) / 2);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setResizable(false);
        window.setVisible(true);
    }

    /**
     * Nested applet class that can be used to run Checkers as an
     * applet.  Size of the applet should be 350-by-250
     */
    public class Applet extends JApplet {
        public void init() {
            setContentPane(new Checkers());
        }
    }

    public JButton newGameButton; // Button for starting a new game.
    public JButton resignButton; // Button that a player can use to end 
    // the game by resigning.

    public JLabel message; // Label for displaying messages to the user.

    /**
     * The constructor creates the Board (which in turn creates and manages
     * the buttons and message label), adds all the components, and sets
     * the bounds of the components.  A null layout is used.  (This is
     * the only thing that is done in the main Checkers class.)
     */
    public Checkers() {

        setLayout(null); // I will do the layout myself.
        setPreferredSize(new Dimension(350, 250));

        setBackground(new Color(0, 150, 0)); // Dark green background.

        /* Create the components and add them to the applet. */

        Board board = new Board(); // Note: The constructor for the
        //   board also creates the buttons
        //   and label.
        add(board);
        add(newGameButton);
        add(resignButton);
        add(message);

        /* Set the position and size of each component by calling
       its setBounds() method. */

        board.setBounds(20, 20, 164, 164); // Note:  size MUST be 164-by-164 !
        newGameButton.setBounds(210, 60, 120, 30);
        resignButton.setBounds(210, 120, 120, 30);
        message.setBounds(0, 200, 350, 30);

    } // end constructor
} //end checkers class





class Board extends JPanel implements ActionListener, MouseListener {


    public JButton newGameButton; // Button for starting a new game.
    public JButton resignButton; // Button that a player can use to end 
    // the game by resigning.

    public JLabel message; // Label for displaying messages to the user.



    Play board; // The data for the checkers board is kept here.
    //    This board is also responsible for   generating
    //    lists of legal moves.

    boolean gameInProgress; // Is a game currently in progress?

    /* The next three variables are valid only when the game is in     progress. */

    int currentPlayer; // Whose turn is it now?  The possible values
    //    are 1 and Play.BLACK.

    int selectedRow, selectedCol; // If the current player has selected a piece to
    //     move, these give the row and column
    //     containing that piece.  If no piece is
    //     yet selected, then selectedRow is -1.

    CheckerMove[] legalMoves; // An array containing the legal moves for the
    //   current player.


    /**
     * Constructor.  Create the buttons and lable.  Listens for mouse
     * clicks and for clicks on the buttons.  Create the board and
     * start the first game.
     */
    Board() {
        setBackground(Color.BLACK);
        addMouseListener(this);
        resignButton = new JButton("Resign");
        resignButton.addActionListener(this);
        newGameButton = new JButton("New Game");
        newGameButton.addActionListener(this);
        message = new JLabel("", JLabel.CENTER);
        message.setFont(new Font("Serif", Font.BOLD, 14));
        message.setForeground(Color.green);
        board = new Play();
        doNewGame();
    }


    /**
     * Respond to user's click on one of the two buttons.
     */
    public void actionPerformed(ActionEvent evt) {
        Object src = evt.getSource();
        if (src == newGameButton) doNewGame();
        else if (src == resignButton) doResign();
    }


    /**
     * Start a new game
     */
    void doNewGame() {
        if (gameInProgress == true) {
            // This should not be possible, but it doens't hurt to check.
            message.setText("Finish the current game first!");
            return;
        }
        board.createGame(); // Set up the pieces.
        currentPlayer = 1; // RED moves first.
        legalMoves = board.getLegalMoves(1); // Get RED's legal moves.
        selectedRow = -1; // RED has not yet selected a piece to move.
        message.setText("Red:  Make your move.");
        gameInProgress = true;
        newGameButton.setEnabled(false);
        resignButton.setEnabled(true);
        repaint();
    }


    /**
     * Current player resigns.  Game ends.  Opponent wins.
     */
    void doResign() {
        if (gameInProgress == false) {
            message.setText("There is no game in progress!");
            return;
        }
        if (currentPlayer == 1) gameOver("RED resigns.  BLACK wins.");
        else gameOver("BLACK resigns.  RED wins.");
    }


    /**
     * The game ends.  The parameter, str, is displayed as a message
     * to the user.  The states of the buttons are adjusted so playes
     * can start a new game.  This method is called when the game
     * ends at any point in this class.
     */
    void gameOver(String str) {
        message.setText(str);
        newGameButton.setEnabled(true);
        resignButton.setEnabled(false);
        gameInProgress = false;
    }


    /**
     * This is called by mousePressed() when a player clicks on the
     * square in the specified row and col.  It has already been checked
     * that a game is, in fact, in progress.
     */
    void doClickSquare(int row, int col) {

        /* If the player clicked on one of the pieces that the player
          can move, mark this row and col as selected and return.  (This
          might change a previous selection.)  Reset the message, in
          case it was previously displaying an error message. */

        for (int i = 0; i < legalMoves.length; i++)
        if (legalMoves[i].fromY == row && legalMoves[i].fromX == col) {
            selectedRow = row;
            selectedCol = col;
            if (currentPlayer == 1) message.setText("RED:  Make your move.");
            else message.setText("BLACK:  Make your move.");
            repaint();
            return;
        }

        /* If no piece has been selected to be moved, the user must first
          select a piece.  Show an error message and return. */

        if (selectedRow < 0) {
            message.setText("Click the piece you want to move.");
            return;
        }

        /* If the user clicked on a squre where the selected piece can be
          legally moved, then make the move and return. */

        for (int i = 0; i < legalMoves.length; i++)
        if (legalMoves[i].fromY == selectedRow && legalMoves[i].fromX == selectedCol && legalMoves[i].toY == row && legalMoves[i].toX == col) {
            doMakeMove(legalMoves[i]);
            return;
        }

        /* If we get to this point, there is a piece selected, and the square where
          the user just clicked is not one where that piece can be legally moved.
          Show an error message. */

        message.setText("Click the square you want to move to.");

    } // end doClickSquare()


    /**
     * This is called when the current player has chosen the specified
     * move.  Make the move, and then either end or continue the game
     * appropriately.
     */
    void doMakeMove(CheckerMove pMove) {

        board.move(pMove);

        /* If the move was a jump, it's possible that the player has another
          jump.  Check for legal jumps starting from the square that the player
          just moved to.  If there are any, the player must jump.  The same
          player continues moving.
          */

        if (pMove.jumpMove()) {
            //legalMoves = board.getLegalJumpsFrom(currentPlayer,pMove.toY,pMove.toX);
            legalMoves = board.getLegalMoves(currentPlayer);
            if (legalMoves != null) {
                if (currentPlayer == 1) message.setText("RED:  You must continue jumping.");
                else message.setText("BLACK:  You must continue jumping.");
                selectedRow = pMove.toY; // Since only one piece can be moved, select it.
                selectedCol = pMove.toX;
                repaint();
                return;
            }
        }

        /* The current player's turn is ended, so change to the other player.
          Get that player's legal moves.  If the player has no legal moves,
          then the game ends. */

        if (currentPlayer == 1) {
            currentPlayer = 2;
            legalMoves = board.getLegalMoves(currentPlayer);
            if (legalMoves == null) gameOver("BLACK has no moves.  RED wins.");
            else if (legalMoves[0].jumpMove()) message.setText("BLACK:  Make your move.  You must jump.");
            else message.setText("BLACK:  Make your move.");
        } else {
            currentPlayer = 1;
            legalMoves = board.getLegalMoves(currentPlayer);
            if (legalMoves == null) gameOver("RED has no moves.  BLACK wins.");
            else if (legalMoves[0].jumpMove()) message.setText("RED:  Make your move.  You must jump.");
            else message.setText("RED:  Make your move.");
        }

        /* Set selectedRow = -1 to record that the player has not yet selected
          a piece to move. */

        selectedRow = -1;

        /* As a courtesy to the user, if all legal moves use the same piece, then
          select that piece automatically so the use won't have to click on it
          to select it. */

        if (legalMoves != null) {
            boolean sameStartSquare = true;
            for (int i = 1; i < legalMoves.length; i++)
            if (legalMoves[i].fromY != legalMoves[0].fromY || legalMoves[i].fromX != legalMoves[0].fromX) {
                sameStartSquare = false;
                break;
            }
            if (sameStartSquare) {
                selectedRow = legalMoves[0].fromY;
                selectedCol = legalMoves[0].fromX;
            }
        }

        /* Make sure the board is redrawn in its new state. */

        repaint();

    } // end doMakeMove();


    /**
     * Draw  checkerboard pattern in gray and lightGray.  Draw the
     * checkers.  If a game is in progress, hilite the legal moves.
     */
    public void paintComponent(Graphics g) {

        /* Draw a two-pixel black border around the edges of the canvas. */

        g.setColor(Color.black);
        g.drawRect(0, 0, getSize().width - 1, getSize().height - 1);
        g.drawRect(1, 1, getSize().width - 3, getSize().height - 3);

        /* Draw the squares of the checkerboard and the checkers. */

        for (int row = 0; row < 8; row++) {
            for (int col = 0; col < 8; col++) {
                if (row % 2 == col % 2) g.setColor(Color.LIGHT_GRAY);
                else g.setColor(Color.GRAY);
                g.fillRect(2 + col * 20, 2 + row * 20, 20, 20);
                switch (board.getPiece(row, col)) {
                    case 1:
                        g.setColor(Color.RED);
                        g.fillOval(4 + col * 20, 4 + row * 20, 15, 15);
                        break;
                    case 2:
                        g.setColor(Color.BLACK);
                        g.fillOval(4 + col * 20, 4 + row * 20, 15, 15);
                        break;
                    case 3:
                        g.setColor(Color.RED);
                        g.fillOval(4 + col * 20, 4 + row * 20, 15, 15);
                        g.setColor(Color.WHITE);
                        g.drawString("K", 7 + col * 20, 16 + row * 20);
                        break;
                    case 4:
                        g.setColor(Color.BLACK);
                        g.fillOval(4 + col * 20, 4 + row * 20, 15, 15);
                        g.setColor(Color.WHITE);
                        g.drawString("K", 7 + col * 20, 16 + row * 20);
                        break;
                }
            }
        }

        /* If a game is in progress, hilite the legal moves.   Note that legalMoves
          is never null while a game is in progress. */

        if (gameInProgress) {
            /* First, draw a 2-pixel cyan border around the pieces that can be moved. */
            g.setColor(Color.cyan);
            for (int i = 0; i < legalMoves.length; i++) {
                g.drawRect(2 + legalMoves[i].fromX * 20, 2 + legalMoves[i].fromY * 20, 19, 19);
                g.drawRect(3 + legalMoves[i].fromX * 20, 3 + legalMoves[i].fromY * 20, 17, 17);
            }
            /* If a piece is selected for moving (i.e. if selectedRow >= 0), then
                draw a 2-pixel white border around that piece and draw green borders 
                around each square that that piece can be moved to. */
            if (selectedRow >= 0) {
                g.setColor(Color.white);
                g.drawRect(2 + selectedCol * 20, 2 + selectedRow * 20, 19, 19);
                g.drawRect(3 + selectedCol * 20, 3 + selectedRow * 20, 17, 17);
                g.setColor(Color.green);
                for (int i = 0; i < legalMoves.length; i++) {
                    if (legalMoves[i].fromX == selectedCol && legalMoves[i].fromY == selectedRow) {
                        g.drawRect(2 + legalMoves[i].toX * 20, 2 + legalMoves[i].toY * 20, 19, 19);
                        g.drawRect(3 + legalMoves[i].toX * 20, 3 + legalMoves[i].toY * 20, 17, 17);
                    }
                }
            }
        }

    } // end paintComponent()


    /**
     * Respond to a user click on the board.  If no game is in progress, show 
     * an error message.  Otherwise, find the row and column that the user 
     * clicked and call doClickSquare() to handle it.
     */
    public void mousePressed(MouseEvent evt) {
        if (gameInProgress == false) message.setText("Click \"New Game\" to start a new game.");
        else {
            int col = (evt.getX() - 2) / 20;
            int row = (evt.getY() - 2) / 20;
            if (col >= 0 && col < 8 && row >= 0 && row < 8) doClickSquare(row, col);
        }
    }


    public void mouseReleased(MouseEvent evt) {}
    public void mouseClicked(MouseEvent evt) {}
    public void mouseEntered(MouseEvent evt) {}
    public void mouseExited(MouseEvent evt) {}


} // end class Board
Yassin Hajaj
  • 21,337
  • 9
  • 51
  • 89
  • The NPE is due to newGameButton being null. You can see that you declare the variable within the Checkers class but never initialize it, so it shouldn't be a surprise that you're seeing this exception. Consider assigning an object to the variable before using it. – Hovercraft Full Of Eels Dec 11 '15 at 21:11
  • I agree, I don't see were new game Button gets initialized, although a comment says it should have been created in Boards constructor. Maybe have a method to get it out of the Board? – Charles Spencer Dec 11 '15 at 21:13
  • @CharlesSpencer: oh a newGameButton variable is certainly initialized within the Board constructor, but it's not the same variable, so I have to wonder if there might be some magical thinking involved that if a variable of the same name in another class is initialized then the same named variable in the Checkers class will automatically be initialized, but as we both now, that won't work. – Hovercraft Full Of Eels Dec 11 '15 at 21:14

0 Answers0