0

I am trying to place ships on a console based board game, I have the following errors and not sure how to debug them.

Exception in thread "main" java.lang.NullPointerException at NavalBattle.Board.print(Board.java:570) at NavalBattle.Board.placeShipsP1(Board.java:267) at NavalBattle.Board.(Board.java:61) at NavalBattle.Controller.start(Controller.java:29) at NavalBattle.Controller.main(Controller.java:21)

line 570 is value = this.ships2[row][col].toString();

import java.util.Scanner;

  public class Controller {

    /**
     * The board that represents the current state of the game.
     */
    private Board board;

    public Controller() {}

    /**
     * This creates one Library object and calls its start method.
     * 
     * @Param args
     */
    public static void main(String[] args) {
        new Controller().start();
    }
    int PL;
    /**
     * The PLrimary method that starts and coordinates a game. Call this to
     * begin a new game.
     */
    public void start() {
        this.board = new Board();

        Scanner scanner = new Scanner(System.in);
        this.board.moveShip();
        while (!this.board.isGameOver()) {
            PL = 1;
            this.board.moveShip();
            PL = 2;
            this.board.moveShip2(null);
            this.board.remap();
            this.board.moveShip2(null);
        System.out.println("Enter a row and column number at which to shoot (e.g., 2,3): ");
        String[] coordinates = scanner.nextLine().split(",");
        if (coordinates.length != 2) {
        System.out.println("PLlease enter coordinates in the correct format.");
            continue;
            }
            int row = Integer.parseInt(coordinates[0].trim());
            int column = Integer.parseInt(coordinates[1].trim());
            this.board.bombOp(row, column);
        }
        if (PL == 1);{
        System.out.println("Game Over Player 2 wins");
        }
        if (PL == 2){
        System.out.println("Game Over Player 1 wins");  
        }
    }
}


// Board Class

import java.util.ArrayList;
import java.util.Scanner;

public class Board {

    int x = 0;
    int y = 0;

    ArrayList<Ships> player1 = new ArrayList<>();
    ArrayList<Ships> player2 = new ArrayList<>();
    /**
     * The number of shots that have hit ships
     */
    private int hitCount;

    /**
     * Track the locations of the board that have been fired upon
     */
    private boolean[][] locationsFiredUpon;

    /**
     * Track the ships in the game
     */
    private Ships[][] ships;

    private Ships[][] ships2;

    private Ships[][] shipsM;

    /**
     * The number of ships sunk
     */
    private int shipsSunk;

    /**
     * The number of shots fired
     */
    private int shotsFired;

    /**
     * Constructor. Initializes internal counters and populates the game
     * board with randomly placed ships.
     */
    public Board() {
        this.hitCount = 0;
        this.shipsSunk = 0;
        this.shotsFired = 0;
        board();
        this.ships = new Ships[6][9];
        this.ships2 = new Ships[6][9];
        this.locationsFiredUpon = new boolean[6][9];
        for (int row=0; row < this.ships.length; row++) {
            for (int col=0; col < this.ships[row].length; col++) {
                this.ships[row][col] = new Conflict();
                this.locationsFiredUpon[row][col] = false;
            }
        }

        this.placeShipsP1();
        this.placeShipsP2();
        this.moveShip();
        this.moveShip2(player1);
    }

    public void remap() {
        board();
        this.locationsFiredUpon = new boolean[6][9];
        for (int row=0; row < this.ships.length; row++) {
            for (int col=0; col < this.ships[row].length; col++) {
                this.ships[row][col] = new Conflict();
                this.locationsFiredUpon[row][col] = false;
            }
        }
    }

    /**
     * Constructor for testing. Accepts an input ship array and does not
     * attempt to place ships
     * @param shipArray
     */
    public Board(Ships[][] shipArray) {
        this.hitCount = 0;
        this.shipsSunk = 0;
        this.shotsFired = 0;
        this.ships = shipArray;
        this.locationsFiredUpon = new boolean[6][9];
        for (int row=0; row < this.ships.length; row++) {
            for (int col=0; col < this.ships[row].length; col++) {              
                this.locationsFiredUpon[row][col] = false;
            }
        }
    }

    public void board(){
        this.ships = new Ships[6][9];
        this.ships2 = new Ships[6][9];
    }

    /**
     * Get the number of shots fired that have hit a ship.
     * @return  The number of shots fired that have hit a ship
     */
    public int getHitCount() {
        return this.hitCount;
    }

    /**
     * Get the game board.
     * @return  A 2-D array of Ships representing the game
     */
    public Ships[][] getShipArray() {
        return this.ships;
    }

    public Ships[][] getShipArray2() {
        return this.ships2;
    }

    /**
     * Get the number of ships sunk.
     * @return  The number of ships sunk
     */
    public int getShipsSunk() {
        return this.shipsSunk;
    }

    /**
     * Get the number of shots fired so far.
     * @return  The number of shots fired
     */
    public int getShotsFired() {
        return this.shotsFired;
    }



    /**
     * Create an list of ships that can be placed on the board:
     * - 1 battleship
     * - 2 cruisers
     * - 3 destroyers
     * - 4 submarines
     * @return  ships to be placed on the board
     */
    private ArrayList<Ships> generateInitialShipArrayList1() {
        ArrayList<Ships> ship = new ArrayList<Ships>();

        for (int i=0; i<1; i++) {
            ship.add(new Battleship());
        }   
        for (int i=0; i<0; i++) {
            ship.add(new Minesweeper());
        }
        for (int i=0; i<0; i++) {
            ship.add(new Destroyer());
        }
        for (int i=0; i<0; i++) {
            ship.add(new Submarine());
        }   
        for (int i=0; i<0; i++) {
            ship.add(new Mines());
        }   
        return ship;
    }

    private ArrayList<Ships> generateInitialShipArrayList2() {
        ArrayList<Ships> ship2 = new ArrayList<Ships>();

        for (int i=1; i<2; i++) {
            ship2.add(new Battleship());
        }   
        for (int i=1; i<1; i++) {
            ship2.add(new Minesweeper());
        }
        for (int i=1; i<1; i++) {
            ship2.add(new Destroyer());
        }
        for (int i=1; i<1; i++) {
            ship2.add(new Submarine());
        }   
        for (int i=1; i<1; i++) {
            ship2.add(new Mines());
        }   
        return ship2;
    }

    /**
     * Indicate whether the game is over by checking if all ships have been 
     * sunk.
     * @return  true if all ships are sunk; otherwise false
     */
    public boolean isGameOver() {

        return (this.shipsSunk == 1);
    }

    /**
     * Whether the specified position is occupied by a ship and is not empty
     * sea.
     * @param row
     * @param column
     * @return true if the position has a ship; else false
     */
    public boolean isOccupied(int row, int column) {
        System.out.println("Occupardo, you no go here");
        return !(this.ships[row][column] instanceof Conflict);
    }

    public void placeShipsP1() {
        System.out.println("");
        print();

        ArrayList<Ships> shipsToMove = this.generateInitialShipArrayList1();
        player1 = this.generateInitialShipArrayList1();

        boolean okToPlaceShipHere = false;
        int row = 0;
        int column = 0;
        String Tp = "1";
        boolean horizontal = false;
        if(okToPlaceShipHere = false){
                System.out.println("Occupardo, you no go here");
            }
        for (Ships ship : player1) {
            while (!okToPlaceShipHere) {

                Scanner scanner = new Scanner( System.in );

                System.out.println("player1 enter a row and column (e.g., 2,3)");

                System.out.println("please enter the row of " + ship.getShipType());

                String[] coordinates = scanner.nextLine().split(",");
                if (coordinates.length != 2) {
                    System.out.println("Please enter coordinates in the correct format.");
                    continue;
                }
                row = Integer.parseInt(coordinates[0].trim());
                column = Integer.parseInt(coordinates[1].trim());
                ship.setX(row);
                ship.setY(column);
                System.out.println(ship.getX() + " " + ship.getY());

               // row = Random.nextInt(6);
               // column = Random.nextInt(9);
                horizontal = true;

                okToPlaceShipHere = ship.okToPlaceShipAt(row,  column, horizontal, this);

            }
            if( okToPlaceShipHere = true){
                this.bombOp(row, column);
            }

            ship.setBowColumn(column);
            ship.setBowRow(row);
            ship.setPlayer(Tp);
            ship.setX(row);
            ship.setY(column);
            System.out.println(ship.getX() + " " + ship.getY()  + " " + ship.getPlayer());
            ship.setHorizontal(horizontal);
            this.placeShipIntoShipsArray(ship);
            okToPlaceShipHere = false;
            System.out.println("");
            print();
        }       
    }

    public void placeShipsP2() {
        System.out.println("");
        print();

        ArrayList<Ships> shipsToPlace = this.generateInitialShipArrayList1();
        player2 = this.generateInitialShipArrayList2();

        boolean okToPlaceShipHere = false;
        int row = 0;
        int column = 0;
        String Tp = "2";
        boolean horizontal = false;
        if(okToPlaceShipHere = false){
                System.out.println("Occupardo, you no go here");
            }
        for (Ships ship : player2) {
            while (!okToPlaceShipHere) {

                Scanner scanner = new Scanner( System.in );

                System.out.println("Player 2 enter a row and column (e.g., 2,3)");

                System.out.println("please enter the row of " + ship.getShipType());

                String[] coordinates = scanner.nextLine().split(",");
                if (coordinates.length != 2) {
                    System.out.println("Please enter coordinates in the correct format.");
                    continue;
                }
                row = Integer.parseInt(coordinates[0].trim());
                column = Integer.parseInt(coordinates[1].trim());
                ship.setX(row);
                ship.setY(column);
                System.out.println(ship.getX() + " " + ship.getY());

//              row = random.nextInt(6);
//              column = random.nextInt(9);
                horizontal = true;

                okToPlaceShipHere = ship.okToPlaceShipAt(row,  column, horizontal, this);

            }


            ship.setBowColumn(column);
            ship.setBowRow(row);
            ship.setPlayer(Tp);
            ship.setX(row);
            ship.setY(column);
            System.out.println(ship.getX() + " " + ship.getY() + " " + ship.getPlayer());
            ship.setHorizontal(horizontal);
            this.placeShipIntoShipsArray(ship);
            okToPlaceShipHere = false;
            System.out.println("");
            print();
        }       
    }

    /**
     * Place the given ship into locations in the
     * 2Darray that tracks ship positions.
     * @param ship
     */
    private void placeShipIntoShipsArray(Ships ship) {
        int row = ship.getBowRow();
        int column = ship.getBowColumn();

//      player1.add.ship;
        player1.removeAll(player1);
        player2.removeAll(player2);

        if (ship.isHorizontal()) {
            for (int i=0; i < ship.getLength(); i++) {              
                this.ships[row][(column+i)] = ship;
            }
        }
        else {
            for (int i=0; i < ship.getLength(); i++) {              
                this.ships[(row+i)][column] = ship;
            }
        }
    }

    public void ifship(){
        for (int i=0; i < 1; i++){
            board();
        }

    }

    private void placeShipIntoShipsArray2(Ships ship) {
        int row = ship.getBowRow();
        int column = ship.getBowColumn();


        //player1.add.ships;
        player1.removeAll(player1);
        player2.removeAll(player2);
        //ship.clear();

        if (ship.isHorizontal()) {
            for (int i=0; i < ship.getLength(); i++) {              
                this.ships2[row][(column+i)] = ship;
            }
        }
        else {
            for (int i=0; i < ship.getLength(); i++) {              
                this.ships2[(row+i)][column] = ship;
            }
        }

    }
public void display() {

        System.out.print("    ");
        for (int i=0; i < 9; i++) {
            System.out.print(i + "  ");
        }
        System.out.print("\n");

        for (int row=0; row < 6; row++) {
            System.out.print(" " + row + "  ");
            for (int col=0; col < 9; col++) {
                String value = "";
                if (this.locationsFiredUpon[row][col]) {
                    value = "-";
                }
                if (this.ships2[row][col] != null) {
                    value = this.ships2[row][col].toString() ;
                }
                else {
                    value = "-";
                }

                System.out.print(value + "  ");
            }
            System.out.print("\n");
        }
        remap();
    } 


    boolean pr = false;
    boolean pr2 = false;

    public void moveShip(){
        System.out.println("So you wanna move a ship");
        System.out.println(player1);

        for (int i=0; i > 1; i++) {
            print();
            System.out.println("map 1");
            pr = true;
        }
        if (pr = true){
            display();
        }

        //ArrayList<Ships> shipsToMove = new ArrayList<>();
        ArrayList<Ships> shipsToMove = new ArrayList<>();
        ArrayList<Ships> shipsToMove1 = player1;
        boolean notMoved = false;
        int rowM = 0;
        int columnM = 0;
        String Tp = "1";
        boolean horizontal = false;
        if(notMoved = false){
                System.out.println("Occupardo, you no go here");
            }
        System.out.println("gets here 1");

        for (Ships shipM : shipsToMove1) {
            System.out.println("gets here 2");
            while (!notMoved) {


                Scanner scanner1 = new Scanner( System.in );

                System.out.println("Enter a area to move to (e.g., 2,3)");

                System.out.println("please enter a movement for the: " + shipM.getShipType() + shipM.getBowRow());

                String[] coordinates = scanner1.nextLine().split(",");
                if (coordinates.length != 2) {
                    System.out.println("Please enter coordinates in the correct format.");
                    continue;
                }
                rowM = Integer.parseInt(coordinates[0].trim());
                columnM = Integer.parseInt(coordinates[1].trim());

//              row = random.nextInt(6);
//              column = random.nextInt(9);
                horizontal = true;

                notMoved = shipM.okToPlaceShipAt(rowM,  columnM, horizontal, this);             
            }

            if( notMoved = true){
                this.bombOp(rowM, columnM);
            }

            shipM.setBowColumn(columnM);
            shipM.setBowRow(rowM);
            shipM.setHorizontal(horizontal);
            this.placeShipIntoShipsArray2(shipM);
            notMoved = false;
            System.out.println("");
            display();
        }       
    }

    public void moveShip2(ArrayList<Ships> player2){
        System.out.println("So you wanna move a ship");

        for (int i=0; i > 1; i++) {
            display();
            pr2 = true;
        }
        if (pr2 = true){
            display();
        }

        ArrayList<Ships> shipsToMove = new ArrayList<>();
        player2 = this.player2;
        boolean notMoved = false;
        int rowM = 0;
        int columnM = 0;
        String Tp = "1";
        boolean horizontal = false;
        if(notMoved = false){
                System.out.println("Occupardo, you no go here");
            }
        System.out.println("gets here 1");

        for (Ships ship : player2) {
            System.out.println("gets here 2");
            while (!notMoved) {

                Scanner scanner1 = new Scanner( System.in );

                System.out.println("Enter a area to move to (e.g., 2,3)");

                System.out.println("please enter a movement for the: " + ship.getShipType());

                String[] coordinates = scanner1.nextLine().split(",");
                if (coordinates.length != 2) {
                    System.out.println("Please enter coordinates in the correct format.");
                    continue;
                }
                rowM = Integer.parseInt(coordinates[0].trim());
                columnM = Integer.parseInt(coordinates[1].trim());

//              row = random.nextInt(6);
//              column = random.nextInt(9);
                horizontal = true;

                notMoved = ship.okToPlaceShipAt(rowM,  columnM, horizontal, this);              
            }
            if( notMoved = true){
                this.bombOp(rowM, columnM);
            }

            ship.setBowColumn(columnM);
            ship.setBowRow(rowM);
            ship.setHorizontal(horizontal);
            this.placeShipIntoShipsArray2(ship);
            notMoved = false;
            System.out.println("");
            display();
            display();
        }       
    }




    /**
     * Print the current state of the game.
     */
    public void print() {

        System.out.print("    ");
        for (int i=0; i < 9; i++) {
            System.out.print(i + "  ");
        }
        System.out.print("\n");

        for (int row=0; row < 6; row++) {
            System.out.print(" " + row + "  ");
            for (int col=0; col < 9; col++) {
                String value = "";
                if (this.locationsFiredUpon[row][col]) {
                    value = "-";
                }
                **if (this.ships[row][col] != null) {
                    value = this.ships[row][col].toString() ;**
                }

                if (this.locationsFiredUpon[row][col]) {
                    value = this.ships2[row][col].toString();
                }
                if (this.ships2[row][col] != null) {
                value = this.ships2[row][col].toString() ;
                }
                else {
                    value = "-";
                }

                System.out.print(value + "  ");
            }
            System.out.print("\n");
        }

    } 


    public void print2() {

        System.out.print("    ");
        for (int i=0; i < 9; i++) {
            System.out.print(i + "  ");
        }
        System.out.print("\n");

        for (int row=0; row < 6; row++) {
            System.out.print(" " + row + "  ");
            for (int col=0; col < 9; col++) {
                String value = "";
                if (this.locationsFiredUpon[row][col]) {
                    value = "-";
                }
                if (this.shipsM[row][col] != null) {
                    value = this.shipsM[row][col].toString() ;
                }
                if (this.locationsFiredUpon[row][col]) {
                value = this.ships2[row][col].toString();
            }
                if (this.ships2[row][col] != null) {
                value = this.ships2[row][col].toString() ;
            }
                else {
                    value = "-";
                }

                System.out.print(value + "  ");
            }
            System.out.print("\n");
        }
        board();
    }
    /**
     * Handle a shot fired at the specified position.
     * @param row
     * @param column
     * @return  true if a ship was hit; else false
     */
    public boolean bombOp(int row, int column) {
        this.shotsFired++;
        this.locationsFiredUpon[row][column] = true;

        Ships shipAtLocation = this.ships[row][column];     

        if (shipAtLocation.isSunk()) {
            return false;
        }

        boolean shipWasHit = shipAtLocation.bombOp(row, column);

        if (shipWasHit) {
            this.hitCount++;
        }

        if (shipAtLocation instanceof Conflict) {
            return shipWasHit;
        }

        if (shipAtLocation.isSunk()) {
            shipsSunk++;
        }

        return shipWasHit;
    }
user1886323
  • 1,179
  • 7
  • 15
Alias K
  • 17
  • 7
  • 1
    You should consider changing the title of this question to "How do I debug a NullPointerException?". "Console Based Board Game" doesn't really tell anyone anything about your problem. – user1886323 Aug 02 '15 at 18:43
  • I suggest you read: http://stackoverflow.com/help/how-to-ask a bit more thoroughly. "_Include just enough code to allow others to reproduce the problem. For help with this, read How to create a Minimal, Complete, and Verifiable example._" specifically that part. Your question is pretty clear, but there is simply too much code to go through. Last, when you got this workin I suggest you give http://codereview.stackexchange.com/ a go with all of your _working_ code. – Emz Aug 02 '15 at 20:03
  • You also have an `;` in the wrong place in your `Controller`. Not related to the error you are recieving. `if (PL == 1);{`. I guess it should be without there. You can also use an else case instead of checking `PL == 2`. There are also errors of how you toggle between `1` and `2`. – Emz Aug 02 '15 at 20:15

1 Answers1

4

The best way to debug NullPointerException is to look at the first line of the stack trace, which is:

NavalBattle.Board.print(Board.java:570)

What this means is that the error occurred on line number 570 in the Board.java file. You should go to this line in the file and look at which variables could be null on that line.

Line 570 is value = this.ships2[row][col].toString();. On this line, only 3 things can possibly be null:

  1. this.ships2
  2. `this.ships2[row]
  3. `this.ships2[row][col]

If you cannot immediately see which of these is null, use your IDE to set a breakpoint there and start your program in debug mode. When the IDE stops at that line, create a "watch expression" for each of the above 3 expressions, or use the "evaluate expression" feature. One of them should be null.

Without debugging, I can only guess, but I think I can make a good guess. this.ship2 is unlikely to be null because I can see that you have initialised it in your code. I also don't think that this.ships2[row] is null - You have initialised the 2D array in the constructor correctly I think. Therefore, I think it is this.ships2[row][col] that is null, and calling toString() on null is throwing the NPE. To confirm my theory you could replace the line with:

value = String.valueOf(this.ships2[row][col]);
user1886323
  • 1,179
  • 7
  • 15
  • This is my line 570: if (this.locationsFiredUpon[row][col]) { value = this.ships2[row][col].toString(); } – Alias K Aug 02 '15 at 18:49
  • I can't find a null variable, hence needing some help. – Alias K Aug 02 '15 at 18:50
  • You should add the line to your question, not as a comment. But here's a hint - put a new line before value and then the line number in the stack trace could be 570 or 571 - this narrows down the possible places the null can be. – user1886323 Aug 02 '15 at 18:53
  • 1
    Also, can you confirm that you have put a breakpoint on that line and used the IDE to look at the expressions? – user1886323 Aug 02 '15 at 18:54
  • Actually I can see in your code you already have it on multiple lines - Can you tell us which line is actually 570? your comment has multiple lines of code in it. – user1886323 Aug 02 '15 at 18:56
  • I have added it to the question. 570 is in the print method. – Alias K Aug 02 '15 at 19:10
  • Please point out exactly which line it is. You have pointed out TWO lines. Show exactly which line is 570. – user1886323 Aug 02 '15 at 19:21
  • This is line 570: value = this.ships2[row][col].toString(); – Alias K Aug 02 '15 at 19:40
  • @AliasK The array `ships2` obviously contains `null` which is no suprise, because `null` is the default value of each index. – Tom Aug 02 '15 at 19:58
  • actually the elements of ships2 are all non-null arrays. It is the element of these arrays that are null. Also, I don't think anything is obvious to this guy... – user1886323 Aug 02 '15 at 20:01
  • You said "This is my line 570: if (this.locationsFiredUpon[row][col]) { value = this.ships2[row][col].toString(); } – " Pro tip: don't put lots of code onto one line. Here you have essentially three separate statements. Introduce a variable to represent "this.locationsFiredUpon[row][col]" and another one for "this.ships2[row][col]". Now when you get the null pointer you know exactly which line it is. We actually have a requirement in our code style that we do this for exactly this reason. Without effort (or it may even be impossible) it's difficult to work out why the NPE happened. – Egwor Aug 02 '15 at 20:02
  • Egwor - I made the same comment above but then realised his code is formatted correctly - he just quoted multiple lines in the comment. – user1886323 Aug 02 '15 at 20:07
  • @user1886323 when I make the changes: value = String.valueOf(this.ships2[row][col]); I get different errors Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at java.util.ArrayList$Itr.next(Unknown Source) at NavalBattle.Board.placeShipsP1(Board.java:226) at NavalBattle.Board.(Board.java:61) at NavalBattle.Controller.start(Controller.java:29) at NavalBattle.Controller.main(Controller.java:21) – Alias K Aug 02 '15 at 21:34
  • bingo - then mark this as the answer and ask a new question! – user1886323 Aug 02 '15 at 22:08