0

Could somebody explain why I am getting a NullPointerException error when I try to place a counter on my Connect Four board:

Exception in thread "main" java.lang.NullPointerException
at Counter.canMakeMove(Counter.java:26)
at Main.main(Main.java:31)

I understand that a NullPointerException error occurs when the program attempts to reference an object that has null value, however I cannot understand where it is deriving this null value from?

I am trying to make my code for Object Oriented, so would also appreciate any comments / tips going forward!

Main.java

import java.io.InputStreamReader;
import java.util.Random;
import java.io.BufferedReader;
import java.io.IOException;

public class Main {

public static void main(String args[])throws IOException{

    Board Connect4 = new Board();
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    System.out.println("Welcome to Connect 4");
    System.out.println("There are 2 players red and yellow");
    System.out.println("Player 1 is Red, Player 2 is Yellow");
    System.out.println("To play the game type in the number of the boardColumn you want to drop you counter in");
    System.out.println("A player wins by connecting 4 counters in a row - vertically, horizontally or diagonally");
    System.out.println("");
    Connect4.printBoard();
    outer:

        while(true){

            int boardColumn = 0;

            //Player One Logic ----------------------------------------------------------------
            while(true){
                System.out.println("");
                System.out.println("Player 1, please select your column:");
                boardColumn = Integer.parseInt(br.readLine());
                if(Connect4.canMakeMove(boardColumn)){
                    if(Connect4.placeCounter(boardColumn, 1)){
                        Connect4.printBoard();
                        System.out.println("");
                        System.out.println("Congratulations! Player 1 has won the game");
                        break outer;
                    }
                    break;
                }
                else
                    System.out.println("Column "+boardColumn+" is already full!!");
            }
            Connect4.printBoard();

            //Player Two Logic ---------------------------------------------------------------   
            while(true){
                System.out.println("");
                System.out.println("The Computer has selected a column and played a counter");
                System.out.println("");

                Random r = new Random();
                int num = r.nextInt(7);

                boardColumn = num;

                if(Connect4.canMakeMove(boardColumn)){
                    if(Connect4.placeCounter(boardColumn, 2)){
                        Connect4.printBoard();
                        System.out.println("");
                        System.out.println("Unlucky! The Computer has won this game");
                        break outer;
                    }
                    break;
                }
                else
                    System.out.println("Column "+boardColumn+" is already full!!");
            }
            Connect4.printBoard();

            if(Connect4.gameDrawn()){
                System.out.print("The game has ended in a draw. Please start the game again.");
                break;
            }
        }
}

Board.java

public class Board extends Counter {

static int totalPlayed;
static int[][] gameBoard;
static int widthOfBoard=7;
static int heightOfBoard=7;

public static int [][] getBoard() {
    return gameBoard;
}

public static int getWidth() {
    return widthOfBoard;
}

public static int getHeight() {
    return heightOfBoard;
}

public static int getTotal() {
    return totalPlayed;
}

public Board(){
    gameBoard = new int[heightOfBoard][widthOfBoard];
    totalPlayed=0;
}

public void printBoard(){
    for(int i=0;i<gameBoard.length;i++){
        for(int j=0;j<gameBoard[0].length;j++){
            if(gameBoard[i][j] == 0)
                System.out.print(".  ");
            else
                System.out.print(gameBoard[i][j]+"  ");
        }
        System.out.println("");
    }
    System.out.println("--------------------");
    System.out.println("0  1  2  3  4  5  6");
}


}

Counter.Java

public abstract class Counter {


int widthOfBoard = Board.getWidth();
int [][] gameBoard = Board.getBoard();
int heightOfBoard = Board.getHeight();
int totalPlayed = Board.getTotal();

public boolean placeCounter(int boardColumn, int playerNum){
    int i=0;
    for(i=0;i<widthOfBoard;i++){
        if(gameBoard[i][boardColumn] == 1 || gameBoard[i][boardColumn] == 2){
            gameBoard[i-1][boardColumn]=playerNum;
            break;
        }
    }
    if(i == widthOfBoard)
        gameBoard[i-1][boardColumn]=playerNum;

    totalPlayed++;
    return isConnected(i-1,boardColumn);
}

public boolean canMakeMove(int boardColumn){
    return gameBoard[0][boardColumn] == 0; 
}

public boolean gameDrawn(){
    return totalPlayed == widthOfBoard * heightOfBoard;
}

public boolean isHorizontal(int x, int y) {
    int count = 0;
    int i=y;
    int num=gameBoard[x][y];

    //HORIZONTAL.
    while(i<widthOfBoard && gameBoard[x][i] == num){
        count++;
        i++;
    }
    i=y-1;
    while(i>=0 && gameBoard[x][i] == num){
        count++;
        i--;
    }
    if(count == 4)
        return true;
    return false;
}

public boolean isVertical(int x, int y) {
    //VERTICAL.
    int count=0;
    int j=x;
    int num=gameBoard[x][y];

    while(j<widthOfBoard && gameBoard[j][y] == num){
        count++;
        j++;
    }
    if(count == 4)
        return true;
    return false;
}

public boolean isRightDiagonal(int x, int y) {
    //SECONDARY DIAGONAL.
    int count=0;
    int i=x;
    int j=y;
    int num=gameBoard[x][y];

    while(i<widthOfBoard && j<widthOfBoard && gameBoard[i][j] == num){
        count++;
        i++;
        j++;
    }

    if(count == 4)
        return true;
    return false;
}

public boolean isLeftDiagonal(int x, int y) {
    //LEADING DIAGONAL.
    int count=0;
    int i = x;
    int j=y;
    int num=gameBoard[x][y];

    while(i<widthOfBoard && j>=0 && gameBoard[i][j] == num){
        count++;
        i++;
        j--;
    }

    if(count == 4)
        return true;
    return false;
}

public boolean isConnected(int x, int y){

    isHorizontal(x, y);

    isVertical(x, y);

    isRightDiagonal(x, y);

    isLeftDiagonal(x, y);

    return false;

}
}
Poppo123
  • 65
  • 6

2 Answers2

1

Move your array and play counter initializations into a static block. This ensures that the board is initialized before any methods are called:

static {
    gameBoard = new int[heightOfBoard][widthOfBoard];
    totalPlayed=0;
}
Benjamin Urquhart
  • 1,626
  • 12
  • 18
1

First some rudimentary Java programming tips:

  • Every variable name, reference should be lowerCamelCase(Connect4 -> connect4)
  • connect4 is an instance of the Board object and the fields totalPlayed, gameBoard... are Board specific, so they should not be static

Now for the problem your class Board extends the abstract class Counter. The class Counter has fields: totalPlayed, gameBoard, widthOfBoard and heightOfBoard. And all the methods in the abstract class reference them.

Your class Board has a copy of all these fields which can be accessed by calling super.totalPlayed, etc. You should not create new fields in your Board class. And this is why your error occurs. The field gameBoard in the abstract class is null, but in your Board class, you initialize a different gameBoard and never set the one the abstract class uses.

Zetko
  • 46
  • 3