How do I debug a NullPointerException? [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
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;
}

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:
this.ships2
`this.ships2[row]
`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]);

Related

ArrayList of ArrayLists is overridden when setting values of a second one

I'm trying to make a battleship game, and this is the part where the players set their boards. When the second player to set the board makes theirs, the first player's board becomes the same as the second player's (when playing the game guessing the locations of that board are misses though, but that's another problem that will hopefully be fixed once this is). For example if I set the first player's ships as being at A1 A2 A3, B1 B2 B3, and C1 C2 C3, then set the second player's ships as D1 D2 D3, E1 E2 E3, and F1 F2 F3, when both lists of ships are printed out I get D1 D2 D3, E1 E2 E3, and F1 F2 F3 for both ships. I've found other questions on here with the same problem, but they always had the problem because they didn't make new lists every time, which I do (at least I'm pretty sure I do), so I can't find where my problem is. Here is the entire main game class, the GetShipLocations, SetShipLocations, and PlayersMakeTheirBoards, functions are what are giving me problems.
import java.util.*;
import java.lang.*;
public class MainGame {
InputReader read = new InputReader();
Grid p1Board = new Grid();
Grid p2Board = new Grid();
Grid p1ShipsBoard = new Grid();
Grid p2ShipsBoard = new Grid();
ArrayList<Ship> p1Ships = new ArrayList<Ship>();
ArrayList<Ship> p2Ships = new ArrayList<Ship>();
String activePlayer = "P1";
public void SetUp() {
p1Board.PrepPrintGrid();
p2Board.PrepPrintGrid();
Ship ship1 = new Ship();
Ship ship2 = new Ship();
Ship ship3 = new Ship();
p1Ships.add(ship1);
p1Ships.add(ship2);
p1Ships.add(ship3);
p2Ships.add(ship1);
p2Ships.add(ship2);
p2Ships.add(ship3);
}
public void GameIntro() {
System.out.println("Welcome to battleship!");
String rulesOption = read.getUserInput("Do you need to see the rules?");
if(rulesOption.equals("Yes") || rulesOption.equals("yes"))
{
System.out.println("Put rules here");
}
System.out.println("Randomly determining which player goes first");
int random = (int) (Math.random() * 2);
if(random == 1)
{
activePlayer = "P2";
}
System.out.println(activePlayer + " starts!");
}
public ArrayList<ArrayList<String>> GetShipLocations(Grid board) {
ArrayList<ArrayList<String>> ships = new ArrayList<ArrayList<String>>();
ArrayList<String> ship1 = new ArrayList<String>();
ArrayList<String> ship2 = new ArrayList<String>();
ArrayList<String> ship3 = new ArrayList<String>();
ships.add(ship1);
ships.add(ship2);
ships.add(ship3);
String[] numbers = {"first", "second", "third"};
board.PrepPrintGrid();
board.PrintGrid();
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
String coordinate = read.getUserInput("Enter the " + numbers[j] + " coordinate of your " + numbers[i] + " ship (3 long):");
ships.get(i).add(coordinate);
board.SetGridDisplay(coordinate, "hit");
board.PrintGrid();
}
}
return ships;
}
public void SetShipLocations(ArrayList<Ship> ship, Grid activeBoard) {
ArrayList<ArrayList<String>> shipLocations = GetShipLocations(activeBoard);
for(int i = 0; i < 3; i++) {
ship.get(i).SetCells(shipLocations.get(i));
}
}
public void PlayersMakeTheirBoards() {
if(activePlayer.equals("P1"))
{
System.out.println("Hand the computer to player one.");
System.out.println("Player one, time to set your board.");
SetShipLocations(p1Ships, p1ShipsBoard);//the effects of this seem to maybe be overriden when the second board is set
for(int i = 0; i < /*100*/3; i++)
{
for(int j = 0; j < 3; j++)
{
System.out.println(p1Ships.get(i).cells.get(j));
}
}
System.out.println("Hand the computer to player two.");
System.out.println("Player two, time to set your board.");
SetShipLocations(p2Ships, p2ShipsBoard);
for(int i = 0; i < /*100*/3; i++)
{
for(int j = 0; j < 3; j++)
{
System.out.println(p2Ships.get(i).cells.get(j));
}
}
for(int i = 0; i < /*100*/3; i++)
{
for(int j = 0; j < 3; j++)
{
System.out.println(p1Ships.get(i).cells.get(j));
}
}
}
else
{
System.out.println("Hand the computer to player two.");
System.out.println("Player two, time to set your board.");
SetShipLocations(p2Ships, p2ShipsBoard);
/*for(int i = 0; i < 100; i++)
{
System.out.println("");
}*/
for(int i = 0; i < /*100*/3; i++)
{
for(int j = 0; j < 3; j++)
{
System.out.println(p2Ships.get(i).cells.get(j));
}
}
System.out.println("Hand the computer to player one.");
System.out.println("Player one, time to set your board.");
SetShipLocations(p1Ships, p1ShipsBoard);
for(int i = 0; i < /*100*/3; i++)
{
for(int j = 0; j < 3; j++)
{
System.out.println(p1Ships.get(i).cells.get(j));
}
}
for(int i = 0; i < /*100*/3; i++)
{
for(int j = 0; j < 3; j++)
{
System.out.println(p2Ships.get(i).cells.get(j));
}
}
}
}
public void PlayTheGame() {
String guess = new String();
String result = new String();
for(int i = 0; i < 100; i++)
{
System.out.println("");
}
while(!p1Ships.isEmpty() && !p2Ships.isEmpty())
{
if(activePlayer.equals("P1"))
{
//print the grid
p1Board.PrintGrid();
//ask user for their guess
guess = read.getUserInput("Player one, enter your guess:");
for(Ship boat:p2Ships)
{
result = boat.CheckYourself(guess);
if(result.equals("hit"))
{
System.out.println(result + "!");
break;
}
if(result.equals("kill"))
{
System.out.println(result + "!");
p2Ships.remove(boat);
break;
}
}
if(result.equals("miss"))
{
System.out.println(result);
}
p1Board.SetGridDisplay(guess, result);
activePlayer = "P2";
}
else
{
p2Board.PrintGrid();
//ask user for their guess
guess = read.getUserInput("Player two, enter your guess:");
for(Ship boat:p1Ships)
{
result = boat.CheckYourself(guess);
if(result.equals("hit"))
{
System.out.println(result + "!");
break;
}
if(result.equals("kill"))
{
System.out.println(result + "!");
p1Ships.remove(boat);
break;
}
}
if(result.equals("miss"))
{
System.out.println(result);
}
p2Board.SetGridDisplay(guess, result);
activePlayer = "P1";
}
}
}
public void EndTheGame() {
String winner = new String();
if(p1Ships.isEmpty())
{
winner = "Player two";
p2Board.PrintGrid();
}
else
{
winner = "Player one";
p1Board.PrintGrid();
}
System.out.println("The game is over!");
System.out.println(winner + " wins! Congratulations!");
}
public static void main(String[] args) {
MainGame game = new MainGame();
game.SetUp();
game.GameIntro();
game.PlayersMakeTheirBoards();
game.PlayTheGame();
game.EndTheGame();
}
}
and here is the Ship class
import java.util.*;
public class Ship {
ArrayList<String> cells = new ArrayList<String>();
//String name = new String();
public void SetCells(ArrayList<String> locations) {
cells = locations;
}
/*public void SetName(String word) {
name = word;
}*/
public String CheckYourself(String guess) {
if(cells.contains(guess))
{
cells.remove(guess);
if(cells.isEmpty())
{
return "kill";
}
else
{
return "hit";
}
}
return "miss";
}
}
The grid and reader classes are working perfectly so I didn't include them.
(This is all based off the dotcom battleship game in headfirst java)
In your setup function:
public void SetUp() {
p1Board.PrepPrintGrid();
p2Board.PrepPrintGrid();
Ship ship1 = new Ship();
Ship ship2 = new Ship();
Ship ship3 = new Ship();
p1Ships.add(ship1);
p1Ships.add(ship2);
p1Ships.add(ship3);
p2Ships.add(ship1);
p2Ships.add(ship2);
p2Ships.add(ship3);
}
You are adding the same instances of ship1-3 to both p1Ships and p2Ships. So when you change the ships of player 2, the p1Ships ArrayList is still pointing to the same ships as p2Ships, and thus will always be the same.

Persistent java.lang.NullPointerException error from String.isEmpty()

I've been trying to search for the bug, but I couldn't find it. Already spent an hour trying to resolve what's wrong. The error begins when the code enters the isPlayerSet method while (!player.isPlayerSet()) {. I already set the used properties to "" but I am still getting this nullpointerexeption error. Please understand that I am fairly new in programming, especially in Java.
Here's the main class
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String playerName = "";
int chosenPokemon = 0;
boolean isANumber = false;;
Player player;
/*
* Initialize Players
*/
Player[] players = new Player[2];
for (int counter = 0; counter < players.length; counter++) {
player = new Player();
}
/*
* Get details of trainers
*/
for (int counter = 0; counter <= players.length-1; counter++) {
player = players[counter];
while (!player.isPlayerSet()) {
/*
* Input player name
*/
if(player.getPlayerName() == "") {
System.out.println("Enter a valid name for Player " + (counter+1) + ":");
player.setPlayerName(playerName);
}
/*
* Choose Pokemon
*/
if(player.getChosenPokemon() == ""){
System.out.println("Choose a starting pokemon for Player " + (counter+1) + ":");
System.out.println("[1] Charmander");
System.out.println("[2] Bulbasaur");
System.out.println("[3] Squirtle");
do {
if(!scanner.hasNextInt())
{
System.out.println("Input must be a valid integer. Try Again.");
scanner.next();
}
else if(!(chosenPokemon >= 1) && !(chosenPokemon <= 3))
{
System.out.println("Input must be a number from 1-3. Try Again.");
scanner.next();
}
else {
chosenPokemon = scanner.nextInt();
isANumber = true;
}
} while(!isANumber);
player.setChosenPokemon(chosenPokemon);
}
} // End of while loop
} // End of for loop
}
}
And here's the player class
public class Player {
Scanner scanner = new Scanner(System.in);
private String playerName = "";
private String chosenPokemon = "";
public String getPlayerName() {
return this.playerName;
}
public void setPlayerName(String playerName) {
do {
playerName = scanner.nextLine();
if(!isAlpha(playerName)) {
System.out.println("Invalid input. Try again");
}
if(playerName.isEmpty()) {
System.out.println("Player name cannot be blank! Try again");
}
} while(!isAlpha(playerName) || playerName.isEmpty());
this.playerName = playerName;
System.out.println("Welcome " + this.playerName);
}
public String getChosenPokemon() {
return chosenPokemon;
}
public void setChosenPokemon(int chosenPokemon) {
if(chosenPokemon == 1) {
this.chosenPokemon = "Charmander";
} else if(chosenPokemon == 2) {
this.chosenPokemon = "Bulbasaur";
} else {
this.chosenPokemon = "Squirtle";
}
}
public boolean isPlayerSet() {
if (this.playerName.isEmpty() && this.chosenPokemon.isEmpty()) {
return false;
}
return true;
}
public static boolean isAlpha(String name) {
char[] chars = name.toCharArray();
for (char c : chars) {
if (!Character.isLetter(c)) {
return false;
}
}
return true;
}
}
I also have another question, is it advisable to replace players[counter] with Player player?
You are creating new Player objects here:
for (int counter = 0; counter < players.length; counter++) {
player = new Player();
}
But: you are not storing those players in the array that you defined above. Thus: the array elements stay at its initial value - meaning that all players in the player array ... are null.
So your loop should say
players[counter] = new Player();
And of course, you really want to read this here.
In the loop
for (int counter = 0; counter < players.length; counter++) {
player = new Player();
}
You initialize the local variable player, so in while (!player.isPlayerSet()) player is null. You need to initialize the instance in the players array
for (int counter = 0; counter < players.length; counter++) {
players[counter] = new Player();
}
You're clobbering the same variable within this loop.
for (int counter = 0; counter < players.length; counter++) {
player = new Player();
}
Option 1:
for (int counter = 0; counter < players.length; counter++) {
players[counter] = new Player();
}
Option 2 (Slightly more concise and elegant):
for (Player p: players) p = new Player();
This
for (int counter = 0; counter < players.length; counter++) {
player = new Player();
}
should be this.
for (int counter = 0; counter < players.length; counter++) {
players[counter] = new Player();
}

Why is my waiting thread not waking up even though it's being notified?

I have a client server tic-tac-toe game which is attempting to run a different thread (in different terminals) for each player, which I have built in eclipse.
My goal is to make each player make their move, .notify() the other player and then .wait() for the other player to make their move, and alternate that process until the game is done.
toSync is the object used for synchronization
public static final Object toSync = new Object()
and it is found in the Player class (which is extended by both XPlayer and OPlayer).
The lines which seem to be causing the problem are commented in XPlayer and Oplayer:
Both Xplayer and OPlayer have main methods, so that they can be run concurrently. X makes the first move then uses a socket to communicate this move to the server.
The server passes this move to O, who then makes its own move and passes it back to the server. This alternates until the game is done.
Making the first move as the x player works fine, but once the intial move is made, o is supposed to display the board and then prompt the user for their move. This however does not happen: x makes its move, and o is supposedly notified, but in fact never wakes up. The curly brace ending the while loop which is commented in OPlayer is never reached (which I know to be true by the debugging I've done so far).
Class XPlayer:
import java.io.*;
public class XPlayer
extends Player
implements Runnable
{
public static volatile boolean xTurn = true;
public XPlayer() throws IOException
{
super();
mark = LETTER_X;
}
public void run()
{
try
{
System.out.println("Okay " + name + ", You will be the X-Player");
synchronized(toSync)
{
Cell move = makeMove();
out.println(move.toString());
board.addMark
(move.row(),move.col(),move.mark());
board.display();
xTurn = false;
toSync.notifyAll(); //THIS IS THE LINE THAT ISNT WORKING!!
System.out.println(WAITING);
}
synchronized(toSync)
{
while (!xTurn)
{toSync.wait();}
}
while (!board.isOver())
{
synchronized(toSync)
{
String line;
do {line = in.readLine();}
while (line == null);
Cell opponentMove = Cell.split(line);
board.addMark
(opponentMove.row(),opponentMove.col(), opponentMove.mark());
String move = makeMove().toString();
out.println(move);
xTurn = false;
toSync.notifyAll();
while (!xTurn)
{toSync.wait();}
}
}
endGame();
sock.close();
in.close();
stdin.close();
out.close();
} catch (InterruptedException ie)
{
System.out.println("IE IN XPLAYER! " + ie.getMessage());
System.exit(1);
} catch (IOException ioe)
{
System.out.println("IOE IN XPLAYER! " + ioe.getMessage());
System.exit(1);
}
}
public static void main(String[] args)
{
try
{
XPlayer x = new XPlayer();
Thread t = new Thread(x);
t.start();
} catch(IOException ioe)
{
System.err.println
("IOE IN XPLAYER MAIN " + ioe.getMessage());
System.exit(1);
}
}
Class OPlayer:
import java.io.*;
public class OPlayer
extends Player
implements Runnable
{
public OPlayer() throws IOException
{
super();
mark = LETTER_O;
}
public void run()
{
try
{
synchronized(toSync)
{
System.out.println("Okay " + name + ", You will be the O-Player");
System.out.println(WAITING);
while(!XPlayer.xTurn)
{toSync.wait();} // THIS IS THE LINE THAT ISN'T WAKING UP
while (!board.isOver())
{
String line;
do {line = in.readLine();}
while (line == null);
Cell opponentMove = Cell.split(line);
board.addMark
(opponentMove.row(),opponentMove.col(),opponentMove.mark());
Cell move = makeMove();
out.println(move.toString());
board.addMark(move.row(),move.col(),move.mark());
board.display();
XPlayer.xTurn = true;
toSync.notifyAll();
System.out.println(WAITING);
while (XPlayer.xTurn)
{toSync.wait();}
}
}
endGame();
sock.close();
in.close();
stdin.close();
out.close();
} catch (InterruptedException ie)
{
System.out.println("IE IN OPLAYER " + ie.getMessage());
System.exit(1);
} catch (IOException ioe)
{
System.err.println("IOE IN OPLAYER " + ioe.getMessage());
System.exit(1);
}
}
public static void main(String[] args)
{
try
{
OPlayer o = new OPlayer();
Thread t = new Thread(o);
t.start();
} catch(IOException ioe)
{
System.err.println("IOE IN OPLAYER MAIN" + ioe.getMessage());
System.exit(1);
}
}
}
As indicated by the code, the toSync.notifyAll() call in XPlayer is not waking up the OPlayer thread, and I am stuck in a deadlock once the first move has been made by the XPlayer
I believe only those 2 classes are needed to resolve the problem but just in case, here are the classes Player Board and TTTServer:
Class Player:
import java.net.*;
import java.io.*;
public class Player
implements Constants
{
protected static final Object toSync = new Object();
protected Socket sock;
protected BufferedReader stdin;
protected BufferedReader in;
protected PrintWriter out;
protected String name;
protected char mark;
protected Board board;
public Player() throws IOException
{
sock = new Socket("localhost",1298);
stdin = new BufferedReader(new InputStreamReader(System.in));
in = new BufferedReader(new
InputStreamReader(sock.getInputStream()));
out = new PrintWriter(sock.getOutputStream(),true);
System.out.println(WELCOME);
System.out.println("Please Enter your name:");
name = stdin.readLine();
board = new Board();
}
public Cell makeMove() throws IOException
{
board.display();
int row = -1;
int col = -1;
do
{
while (row < 0 || row > 2)
{
System.out.println
(name + ", what row would you like your next move to be in?");
row = Integer.parseInt(stdin.readLine());
if (row < 0 || row > 2)
{System.out.println("Invalid entry! Try again...");}
}
while (col < 0 || col > 2)
{
System.out.println
(name + ", what column would you like your next move to be in?");
col = Integer.parseInt(stdin.readLine());
if (col < 0 || col > 2)
{System.out.println("Invalid entry! Try again...");}
}
if (board.getMark(row, col) != SPACE_CHAR)
{System.out.println("That spot is already taken Try again...");}
} while (board.getMark(row,col) != SPACE_CHAR);
return new Cell(row,col,mark);
}
public void endGame()
{
if (board.xWins() == 1) {System.out.println(END + XWIN);}
if (board.oWins() == 1) {System.out.println(END + OWIN);}
else {System.out.println(END + " It was a tie!!");}
}
}
Class TTTServer:
import java.net.*;
import java.io.*;
public class TTTServer
implements Constants
{
public static void main(String[] args)
{
try
{
ServerSocket ss = new ServerSocket(1298,2);
System.out.println("The Server is running...");
Socket sock;
Board board = new Board();
sock = ss.accept();
sock = ss.accept();
BufferedReader in = new BufferedReader(new
InputStreamReader(sock.getInputStream()));
PrintWriter out = new PrintWriter(sock.getOutputStream(),true);
do
{
String moveString;
do {moveString = in.readLine();}
while (moveString == null);
Cell move = Cell.split(moveString);
board.addMark(move.row(), move.col(), move.mark());
out.println(moveString);
} while(!board.isOver());
in.close();
out.close();
ss.close();
sock.close();
} catch(IOException ioe)
{
System.out.println("IOE IN TTTSERVER " + ioe.getMessage());
System.exit(1);
}
}
}
Class Board:
public class Board
implements Constants
{
/**
* A 2D char array stores the game board and
* the total number of marks
*/
private char theBoard[][];
private int markCount;
/**
* Default constructor initializes the array and fills it with
* SPACE_CHARs from the Constants interface
*/
public Board()
{
markCount = 0;
theBoard = new char[3][];
for (int i = 0; i < 3; i++) {
theBoard[i] = new char[3];
for (int j = 0; j < 3; j++)
theBoard[i][j] = SPACE_CHAR;
}
}
/**
* Getter for the mark at the location specified by the arguments
*
* #param row
* #param column
*
* #return mark
*/
public char getMark(int row, int col)
{return theBoard[row][col];}
/**
* Getter for the number of moves which have been made thus far
*
* #return markCount
*/
public int getMarkCount() {return markCount;}
/**
* #return true if the game is over, otherwise false
*/
public boolean isOver()
{
if (xWins() == 1 || oWins() == 1 || isFull())
{return true;}
return false;
}
/**
* #return true if the board has been completely filled with
* X_CHARs and O_CHARs from Constants interface, else false
*/
public boolean isFull()
{return markCount == 9;}
/**
* Runs checkWinner on LETTER_X from Constants interface
*
* #return true if X has won, else false
*/
public int xWins()
{return checkWinner(LETTER_X);}
/**
* Runs checkWinner on LETTER_O from Constants interface
*
* #return true if O has won, else false
*/
public int oWins()
{return checkWinner(LETTER_O);}
/**
* Uses the formatting helper methods to display the board
* in the console
*/
public void display()
{
displayColumnHeaders();
addHyphens();
for (int row = 0; row < 3; row++) {
addSpaces();
System.out.print(" row " + row + ' ');
for (int col = 0; col < 3; col++)
System.out.print("| " + getMark(row, col) + " ");
System.out.println("|");
addSpaces();
addHyphens();
}
}
/**
* Add the mark in the last argument to the location specified by the
* first two arguments
*
* #param row
* #param column
* #param mark
*/
public void addMark(int row, int col, char mark)
{
theBoard[row][col] = mark;
markCount++;
}
/**
* Clears the board by replacing all marks with
* SPACE_CHARs from the Constants interface
*/
public void clear()
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
theBoard[i][j] = SPACE_CHAR;
markCount = 0;
}
/**
* Checks if the player with the argument mark has won the game
*
* #param mark
*
* #return true if the game was won, else false
*/
int checkWinner(char mark) {
int row, col;
int result = 0;
for (row = 0; result == 0 && row < 3; row++) {
int row_result = 1;
for (col = 0; row_result == 1 && col < 3; col++)
if (theBoard[row][col] != mark)
row_result = 0;
if (row_result != 0)
result = 1;
}
for (col = 0; result == 0 && col < 3; col++) {
int col_result = 1;
for (row = 0; col_result != 0 && row < 3; row++)
if (theBoard[row][col] != mark)
col_result = 0;
if (col_result != 0)
result = 1;
}
if (result == 0) {
int diag1Result = 1;
for (row = 0; diag1Result != 0 && row < 3; row++)
if (theBoard[row][row] != mark)
diag1Result = 0;
if (diag1Result != 0)
result = 1;
}
if (result == 0) {
int diag2Result = 1;
for (row = 0; diag2Result != 0 && row < 3; row++)
if (theBoard[row][3 - 1 - row] != mark)
diag2Result = 0;
if (diag2Result != 0)
result = 1;
}
return result;
}
/**
* The final three helper methods are called by display
* to format the board properly in the console
*/
void displayColumnHeaders() {
System.out.print(" ");
for (int j = 0; j < 3; j++)
System.out.print("|col " + j);
System.out.println();
}
void addHyphens() {
System.out.print(" ");
for (int j = 0; j < 3; j++)
System.out.print("+-----");
System.out.println("+");
}
void addSpaces() {
System.out.print(" ");
for (int j = 0; j < 3; j++)
System.out.print("| ");
System.out.println("|");
}
}
Here's your mistake:
Both Xplayer and OPlayer have main methods, so that they can be run concurrently.
If you're running two main() methods, they're not running "concurrently"; they're entirely separate processes. That means no shared threads, variables, objects, notifications etc. If you want to share state, you need to start everything from a single main() method:
class StarterClass {
public static void main(String[] args)
{
// start XPlayer thread
try
{
XPlayer x = new XPlayer();
Thread t = new Thread(x);
t.start();
} catch(IOException ioe)
{
System.err.println
("IOE IN XPLAYER MAIN " + ioe.getMessage());
System.exit(1);
}
// start OPlayer thread
try
{
OPlayer o = new OPlayer();
Thread t = new Thread(o);
t.start();
} catch(IOException ioe)
{
System.err.println("IOE IN OPLAYER MAIN" + ioe.getMessage());
System.exit(1);
}
}
}
If your intent is to have each Player run as a separate client while alternating turns, thread synchronization is the wrong tool for the job. You'll need to implement custom messaging between your server and your clients to keep them in sync.

How to fill a multidimensional array dependant on variables

The program I am working on is a simple shipping program. What I am having difficulty with is populating a multidimensional array factoring in certain variables.
Example
320 items need to be shipped out to 1 receiver using different box sizes.
XL can hold 50 items
LG can hold 20 items
MD can hold 5 items
SM can hold 1 items
Use the least number of boxes so far.
Code
This is my code so far.
import java.util.Scanner;
public class Shipping {
public static void main(String [] args) {
Scanner kbd = new Scanner(System.in);
final int EXTRA_LARGE = 50;
final int LARGE = 20;
final int MEDIUM = 5;
final int SMALL = 1;
String sBusinessName = "";
int iNumberOfGPS = 0;
int iShipmentCount = 0;
displayHeading(kbd);
iShipmentCount = enterShipments(kbd);
int[][] ai_NumberOfShipments = new int [iShipmentCount][4];
String[] as_BusinessNames = new String [iShipmentCount];
for (int iStepper = 0; iStepper < iShipmentCount; iStepper++) {
sBusinessName = varifyBusinessName(kbd);
as_BusinessNames[iStepper] = sBusinessName;
iNumberOfGPS = varifyGPS(kbd);
calculateBoxes(ai_NumberOfShipments[iStepper],iNumberOfGPS, EXTRA_LARGE, LARGE, MEDIUM, SMALL);
}
//showArray(as_BusinessNames);
}
public static void displayHeading(Scanner kbd) {
System.out.println("Red River Electronics");
System.out.println("Shipping System");
System.out.println("---------------");
return;
}
public static int enterShipments(Scanner kbd) {
int iShipmentCount = 0;
boolean bError = false;
do {
bError = false;
System.out.print("How many shipments to enter? ");
iShipmentCount = Integer.parseInt(kbd.nextLine());
if (iShipmentCount < 1) {
System.out.println("\n**Error** - Invalid number of shipments\n");
bError = true;
}
} while (bError == true);
return iShipmentCount;
}
public static String varifyBusinessName(Scanner kbd) {
String sBusinessName = "", sValidName = "";
do {
System.out.print("Business Name: ");
sBusinessName = kbd.nextLine();
if (sBusinessName.length() == 0) {
System.out.println("");
System.out.println("**Error** - Name is required\n");
} else if (sBusinessName.length() >= 1) {
sValidName = sBusinessName;
}
} while (sValidName == "");
return sValidName;
}
public static int varifyGPS(Scanner kbd) {
int iCheckGPS = 0;
int iValidGPS = 0;
do {
System.out.print("Enter the number of GPS receivers to ship: ");
iCheckGPS = Integer.parseInt(kbd.nextLine());
if (iCheckGPS < 1) {
System.out.println("\n**Error** - Invalid number of shipments\n");
} else if (iCheckGPS >= 1) {
iValidGPS = iCheckGPS;
}
} while(iCheckGPS < 1);
return iValidGPS;
}
public static void calculateBoxes(int[] ai_ToFill, int iNumberOfGPS) {
for (int iStepper = 0; iStepper < ai_ToFill.length; iStepper++)
}
//public static void showArray( String[] ai_ToShow) {
// for (int iStepper = 0; iStepper < ai_ToShow.length; iStepper++) {
// System.out.println("Integer at position " + iStepper + " is " + ai_ToShow[iStepper]);
// }
//}
}
Change your definition of calculateBoxes() to also take an array that represents the volume of each of the boxes (in your case this will be {50, 20, 5, 1}:
public static void calculateBoxes(int[] ai_ToFill, int[] boxVolumes, int iNumberOfGPS) {
// for each box size
for (int iStepper = 0; iStepper < ai_ToFill.length; iStepper++) {
// while the remaining items to pack is greater than the current box size
while(iNumberOfGPS >= boxVolumes[iStepper]) {
// increment the current box type
ai_ToFill[iStepper]++;
// subtract the items that just got packed
iNumberOfGPS -= boxVolumes[iStepper];
}
}
}
Another way of calculating this (using / and % instead of a while loop) would be:
public static void calculateBoxes(int[] ai_ToFill, int[] boxVolumes, int iNumberOfGPS) {
// for each box size
for (int iStepper = 0; iStepper < ai_ToFill.length; iStepper++) {
if(iNumberOfGPS >= boxVolumes[iStepper]) {
// calculate the number of boxes that could be filled by the items
ai_ToFill[iStepper] = iNumberOfGPS/boxVolumes[iStepper];
// reset the count of items to the remainder
iNumberOfGPS = iNumberOfGPS%boxVolumes[iStepper];
}
}
}

How to input numbers into a cell of a table?

So far I wrote code that makes a table looking kind of like the table from excel and I am able to input letters words when it compiles, but I cant say for example 1a equals 5 and make the cell in 1a show 5 inside it.this is what my table looks like so far. This is my code to draw up the table:
package table;
public class Spreadsheat {
private int xVal = 137;
private int yVal = 1;
private int[][] table = new int [20][20];
private char yaxis = 'A';
private int xaxis = 0;
public Spreadsheat(){
for(int i = 0; i < xVal; i++){
System.out.print("-");
}
System.out.println();
System.out.print(" |");
for(int i = 0; i < 17; i++){
System.out.print("| " + yaxis + "\t" + "|" );
yaxis = (char) (yaxis + 1);
}
System.out.println();
for(int i = 0; i < xVal; i++){
System.out.print("-");
}
System.out.println();
for(int j = 0; j <10;j++){
System.out.print(" " + xaxis + "|");
for(int i = 0; i < 17; i++){
System.out.print("|" + "\t" + "|" );
}
System.out.println();
xaxis = xaxis + 1;
}
}
public void setxval(int xVal) {
this.xVal = xVal;
}
public int getxVal() {
return xVal;
}
public void setyVal(int yVal) {
this.yVal = yVal;
}
public int getyVal() {
return yVal;
}
public void setTable(int table[][]) {
this.table = table;
}
public int[][] gettable() {
return table;
}
}
And this is my client program:
package Client;
import java.util.Scanner;
import table.Spreadsheat;
public class VisiCalc {
public static void main(String[] args){
Scanner kb = new Scanner(System.in);
Spreadsheat table = new Spreadsheat();
boolean end = false;
while(end == false){
String input = kb.next();
System.out.println(input);
if(input.contains("quit")){
end = true;
}
}
}
}
Your Spreadsheet needs a way to update table. For example, you need a method like this in your Spreadsheet class:
public void setValue(int row, int col, int value) {
if (row >= 0 && row < 20 && col >=0 && col < 20) {
table[row][col] = value;
}
}
You need a method way to convert your keyboard input so you can call table.setValue(...). For example, if you enter "2A=8", your method should parse that string into x=1, y=0, v=8 and call table.setValue(x,y,v). It's up to you if you want the method in Spreadsheet or in your client.
You need a method in Spreadsheet so you can print out your table to the screen with the updated content. You will realize you need to format your content so that your columns line up properly. The easiest way is to set each column to a fixed width say 8 and use java.text.DecimalFormat to convert your int to String.
I guess this is a start.

Categories

Resources