I am still very new to programming. I've only taken three programming classes, one in C++ and two in Java.
I decided I wanted to build my own version of Battleship. I've more or less got the entire project finished. My issue has been providing means of user validation to make sure that the user is actually inputting valid information.
I have a huge chunk of code inside of nested do-while loops, each one repeating if a specific condition returns false.
I've created a Board class that represents the game boards. This is the code minus the methods.
public class Board
{
// Create class-wide arrays to represent each board
private static int p1[][] = new int[10][10];
private static int p2[][] = new int[10][10];
// Create other class-wide variables
private static int p1Targets[][] = new int[10][10];
private static int p2Targets[][] = new int[10][10];
private static int boatOneLocationP1[][] = new int[2][2];
private static boolean boatOneP1Sunk = false;
private static int boatTwoLocationP1[][] = new int[3][2];
private static boolean boatTwoP1Sunk = false;
private static int boatThreeLocationP1[][] = new int[3][2];
private static boolean boatThreeP1Sunk = false;
private static int boatFourLocationP1[][] = new int[4][2];
private static boolean boatFourP1Sunk = false;
private static int boatFiveLocationP1[][] = new int[5][2];
private static boolean boatFiveP1Sunk = false;
private static int boatOneLocationP2[][] = new int[2][2];
private static boolean boatOneP2Sunk = false;
private static int boatTwoLocationP2[][] = new int[3][2];
private static boolean boatTwoP2Sunk = false;
private static int boatThreeLocationP2[][] = new int[3][2];
private static boolean boatThreeP2Sunk = false;
private static int boatFourLocationP2[][] = new int[4][2];
private static boolean boatFourP2Sunk = false;
private static int boatFiveLocationP2[][] = new int[5][2];
private static boolean boatFiveP2Sunk = false;
}
This is the entire placeBoats() method
This is my placeBoats() method. The Player class has a static variable for the total number of Player objects created and each object has its own unique player number.
void placeBoats(Player p, Scanner kb)
{
// Player is shown a menu, he must select all 5 options to place his
// boats.
// Once user has selected which boat he is placing, display the ocean
// and ask the user for start and end coordinates
// Use arrays for Menu Choices and for User Choices
int[] menuChoices = new int[5];
int[] userChoices = new int[5];
// Initialize arrays
for (int i = 0; i < userChoices.length; i++)
{
userChoices[i] = 0;
}
for (int i = 0; i < menuChoices.length; i++)
{
/*
* 1. Two-Length Ship 2. Three-Length Ship 1 3. Three-Length Ship 2
* 4. Four-Length Ship 5. Five-Length Ship
*
* Repeat the do-while loop until userChoices[] == 1.
*/
menuChoices[i] = i + 1;
}
// Begin do-while loop
int num = 0;
int boatLength = 0;
int row1 = 0, col1 = 0, row2 = 0, col2 = 0;
boolean notReady = true;
boolean boatPresent = false;
boolean validCoords = false;
String starting, ending;
do
{ // Jump to end
do
{ // Jump to Place Boats
boatPresent = false;
do
{ // Jump to boat validation (making sure no boats already exist
// in area)
validCoords = false;
// Display Menu
System.out.println("Menu");
if (menuChoices[0] == 1)
{
System.out.println("1. Two-Length Ship");
}
if (menuChoices[1] == 2)
{
System.out.println("2. Three-Length Ship 1");
}
if (menuChoices[2] == 3)
{
System.out.println("3. Three-Length Ship 2");
}
if (menuChoices[3] == 4)
{
System.out.println("4. Four-Length Ship");
}
if (menuChoices[4] == 5)
{
System.out.println("5. Five-Length Ship");
}
// Get user input
System.out.print("\nEnter your menu choice: ");
num = kb.nextInt();
kb.nextLine();
// Input Validation- input must be a valid menu choice
while ((num != 1 && num != 2 && num != 3 && num != 4 && num != 5))
{
System.out.print("Enter your menu choice: ");
num = kb.nextInt();
kb.nextLine();
}
// Further Validation- Make sure number has not been picked
// before yet
while (userChoices[num - 1] == 1)
{
System.out.print("Enter your menu choice: ");
num = kb.nextInt();
kb.nextLine();
}
// Set boat length
if (num == 1)
boatLength = 2;
if (num == 2)
boatLength = 3;
if (num == 3)
boatLength = 3;
if (num == 4)
boatLength = 4;
if (num == 5)
boatLength = 5;
// ////////////////////////////////////////////////////////////////////////////////////////
// Display ocean
if (p.getPlayerNumber() == 1)
{
showP1Board();
System.out.println();
}
if (p.getPlayerNumber() == 2)
{
showP2Board();
System.out.println();
}
// Ask the user for the start and end coordinates (as a
// String)
System.out.print("Enter the starting coordinate for a "
+ boatLength + "-length ship: \n");
starting = kb.nextLine();
// Validate - Make sure the given values are valid
while (starting.charAt(0) != 'A'
&& starting.charAt(0) != 'B'
&& starting.charAt(0) != 'C'
&& starting.charAt(0) != 'D'
&& starting.charAt(0) != 'E'
&& starting.charAt(0) != 'F'
&& starting.charAt(0) != 'G'
&& starting.charAt(0) != 'H'
&& starting.charAt(0) != 'I'
&& starting.charAt(0) != 'J'
&& starting.charAt(0) != 'a'
&& starting.charAt(0) != 'b'
&& starting.charAt(0) != 'c'
&& starting.charAt(0) != 'd'
&& starting.charAt(0) != 'e'
&& starting.charAt(0) != 'f'
&& starting.charAt(0) != 'g'
&& starting.charAt(0) != 'h'
&& starting.charAt(0) != 'i'
&& starting.charAt(0) != 'j')
{
System.out.print("Enter the starting coordinate for a "
+ boatLength + "-length ship: ");
starting = kb.nextLine();
}
while (starting.charAt(1) != '1'
&& starting.charAt(1) != '2'
&& starting.charAt(1) != '3'
&& starting.charAt(1) != '4'
&& starting.charAt(1) != '5'
&& starting.charAt(1) != '6'
&& starting.charAt(1) != '7'
&& starting.charAt(1) != '8'
&& starting.charAt(1) != '9')
{
System.out.print("Enter the starting coordinate for a "
+ boatLength + "-length ship: ");
starting = kb.nextLine();
}
System.out.println("[" + starting.charAt(0) + "]["
+ starting.charAt(1) + "]");
System.out.println();
// Set Row and Column 1
switch (starting.charAt(0))
{
case 'a':
case 'A':
row1 = 0;
break;
case 'b':
case 'B':
row1 = 1;
break;
case 'c':
case 'C':
row1 = 2;
break;
case 'd':
case 'D':
row1 = 3;
break;
case 'e':
case 'E':
row1 = 4;
break;
case 'f':
case 'F':
row1 = 5;
break;
case 'g':
case 'G':
row1 = 6;
break;
case 'h':
case 'H':
row1 = 7;
break;
case 'i':
case 'I':
row1 = 8;
break;
case 'j':
case 'J':
row1 = 9;
break;
} // end switch statement
switch (starting.charAt(1))
{
case 49:
case 1:
col1 = 0;
break;
case 50:
case 2:
col1 = 1;
break;
case 51:
case 3:
col1 = 2;
break;
case 52:
case 4:
col1 = 3;
break;
case 53:
case 5:
col1 = 4;
break;
case 54:
case 6:
col1 = 5;
break;
case 55:
case 7:
col1 = 6;
break;
case 56:
case 8:
col1 = 7;
break;
case 57:
case 9:
col1 = 8;
break;
}
System.out.println(starting.length());
if (starting.length() >= 3)
{
if ((starting.charAt(1) == 1 || starting.charAt(1) == 49)
&& (starting.charAt(2) == 0 || starting
.charAt(2) == 48))
{
col1 = 9;
}
}
System.out.println("Row1 = " + row1 + "\tCol1 = " + col1);
// //////////////////////////////////////////////////////////////////////
System.out.print("Enter the ending coordinate for a "
+ boatLength + "-length ship: \n");
ending = kb.nextLine();
// Validate - Make sure the given values are valid
while (ending.charAt(0) != 'A' && ending.charAt(0) != 'B'
&& ending.charAt(0) != 'C'
&& ending.charAt(0) != 'D'
&& ending.charAt(0) != 'E'
&& ending.charAt(0) != 'F'
&& ending.charAt(0) != 'G'
&& ending.charAt(0) != 'H'
&& ending.charAt(0) != 'I'
&& ending.charAt(0) != 'J'
&& ending.charAt(0) != 'a'
&& ending.charAt(0) != 'b'
&& ending.charAt(0) != 'c'
&& ending.charAt(0) != 'd'
&& ending.charAt(0) != 'e'
&& ending.charAt(0) != 'f'
&& ending.charAt(0) != 'g'
&& ending.charAt(0) != 'h'
&& ending.charAt(0) != 'i'
&& ending.charAt(0) != 'j')
{
System.out.print("Enter the ending coordinate for a "
+ boatLength + "-length ship: ");
ending = kb.nextLine();
}
while (ending.charAt(1) != '1' && ending.charAt(1) != '2'
&& ending.charAt(1) != '3'
&& ending.charAt(1) != '4'
&& ending.charAt(1) != '5'
&& ending.charAt(1) != '6'
&& ending.charAt(1) != '7'
&& ending.charAt(1) != '8'
&& ending.charAt(1) != '9')
{
System.out.print("Enter the ending coordinate for a "
+ boatLength + "-length ship: ");
ending = kb.nextLine();
}
System.out.println("[" + ending.charAt(0) + "]["
+ ending.charAt(1) + "]");
System.out.println();
// Set Row and Column 2
switch (ending.charAt(0))
{
case 'a':
case 'A':
row2 = 0;
break;
case 'b':
case 'B':
row2 = 1;
break;
case 'c':
case 'C':
row2 = 2;
break;
case 'd':
case 'D':
row2 = 3;
break;
case 'e':
case 'E':
row2 = 4;
break;
case 'f':
case 'F':
row2 = 5;
break;
case 'g':
case 'G':
row2 = 6;
break;
case 'h':
case 'H':
row2 = 7;
break;
case 'i':
case 'I':
row2 = 8;
break;
case 'j':
case 'J':
row2 = 9;
break;
} // end switch statement
switch (ending.charAt(1))
{
case 49:
case 1:
col2 = 0;
break;
case 50:
case 2:
col2 = 1;
break;
case 51:
case 3:
col2 = 2;
break;
case 52:
case 4:
col2 = 3;
break;
case 53:
case 5:
col2 = 4;
break;
case 54:
case 6:
col2 = 5;
break;
case 55:
case 7:
col2 = 6;
break;
case 56:
case 8:
col2 = 7;
break;
case 57:
case 9:
col2 = 8;
break;
}
if (ending.length() >= 3)
{
if ((ending.charAt(1) == 1 || ending.charAt(1) == 49)
&& (ending.charAt(2) == 0 || ending.charAt(2) == 48))
{
col2 = 9;
}
}
// end set rows and cols
System.out.println("Row2 = " + row2 + "\tCol2 = " + col2);
// Make sure the coordinates are valid start and end
// coordinates for the given length ship.
if (((row1 == row2) && ((col2 == col1 + (boatLength - 1)) || (col2 == col1
- (boatLength - 1))))
|| ((col1 == col2) && ((row2 == row1
+ (boatLength - 1)) || (row2 == row1
- (boatLength - 1)))))
validCoords = true;
if (!validCoords)
System.out.println("Error: Invalid coordinates for a "
+ boatLength + " -length ship.\n");
} while (!validCoords); // end inner do-while
// Make sure there is not a boat already in that area.
// Loop through part of the array and check for 1's and 2's
// (boat present on coordinate)
// If there are, a boat is present and these coordinates are
// therefore invalid.
if (p.getPlayerNumber() == 1)
{
if (row1 == row2)
{
if (col1 + boatLength > 9)
{
for (int r = row1; r < row1 + 1; r++)
{
for (int c = col1; c > col1 - boatLength; c--)
{
if (p1[r][c] == 1 || p1[r][c] == 2)
boatPresent = true;
}
}
} else
{
for (int r = row1; r < row1 + 1; r++)
{
for (int c = col1; c < col1 + boatLength; c++)
{
if (p1[r][c] == 1 || p1[r][c] == 2)
boatPresent = true;
}
}
}
} else
{
if (row1 + boatLength > 9)
{
for (int r = row1; r > row1 - boatLength; r--)
{
for (int c = col1; c < col1 + 1; c++)
{
if (p1[r][c] == 1 || p1[r][c] == 2)
boatPresent = true;
}
}
} else
{
for (int r = row1; r < row1 + boatLength; r++)
{
for (int c = col1; c < col1 + 1; c++)
{
if (p1[r][c] == 1 || p1[r][c] == 2)
boatPresent = true;
}
}
}
}
}
if (p.getPlayerNumber() == 2)
{
if (row1 == row2)
{
if (col1 + boatLength > 9)
{
for (int r = row1; r < row1 + 1; r++)
{
for (int c = col1; c > col1 - boatLength; c--)
{
if (p2[r][c] == 1 || p2[r][c] == 2)
boatPresent = true;
}
}
} else
{
for (int r = row1; r < row1 + 1; r++)
{
for (int c = col1; c < col1 + boatLength; c++)
{
if (p2[r][c] == 1 || p2[r][c] == 2)
boatPresent = true;
}
}
}
} else
{
if (row1 + boatLength > 9)
{
for (int r = row1; r > row1 - boatLength; r--)
{
for (int c = col1; c < col1 + 1; c++)
{
if (p2[r][c] == 1 || p2[r][c] == 2)
boatPresent = true;
}
}
} else
{
for (int r = row1; r < row1 + boatLength; r++)
{
for (int c = col1; c < col1 + 1; c++)
{
if (p2[r][c] == 1 || p2[r][c] == 2)
boatPresent = true;
}
}
}
}
}
if (boatPresent)
System.out
.println("Error: Invalid coordinates, a boat is present in this location.");
} while (boatPresent); // end outer do-while
// Place the boat on the ocean
if (p.getPlayerNumber() == 1)
{
if (row1 == row2)
{
if (col1 + boatLength - 1 > 9
|| (starting.charAt(1) > ending.charAt(1)))
{
for (int r = row1; r < row1 + 1; r++)
{
for (int c = col1, counter = 0; c > col1
- boatLength; c--, counter++)
{
// place boat
p1[r][c] = 1;
// Record coordinates in the static arrays for
// boat location
switch (num)
{
case 1:
boatOneLocationP1[counter][0] = r;
boatOneLocationP1[counter][1] = c;
break;
case 2:
boatTwoLocationP1[counter][0] = r;
boatTwoLocationP1[counter][1] = c;
break;
case 3:
boatThreeLocationP1[counter][0] = r;
boatThreeLocationP1[counter][1] = c;
break;
case 4:
boatFourLocationP1[counter][0] = r;
boatFourLocationP1[counter][1] = c;
break;
case 5:
boatFiveLocationP1[counter][0] = r;
boatFiveLocationP1[counter][1] = c;
break;
}
}
}
} else
{
for (int r = row1; r < row1 + 1; r++)
{
for (int c = col1, counter = 0; c < col1
+ boatLength; c++, counter++)
{
p1[r][c] = 1;
// Record coordinates in the static arrays for
// boat location
switch (num)
{
case 1:
boatOneLocationP1[counter][0] = r;
boatOneLocationP1[counter][1] = c;
break;
case 2:
boatTwoLocationP1[counter][0] = r;
boatTwoLocationP1[counter][1] = c;
break;
case 3:
boatThreeLocationP1[counter][0] = r;
boatThreeLocationP1[counter][1] = c;
break;
case 4:
boatFourLocationP1[counter][0] = r;
boatFourLocationP1[counter][1] = c;
break;
case 5:
boatFiveLocationP1[counter][0] = r;
boatFiveLocationP1[counter][1] = c;
break;
}
}
}
}
} else
// Columns the same
{
// Going backwards
if (row1 + boatLength - 1 > 9
|| (starting.charAt(0) > ending.charAt(0)))
{
for (int r = row1, counter = 0; r > row1 - boatLength; r--, counter++)
{
for (int c = col1; c < col1 + 1; c++)
{
p1[r][c] = 1;
// Record coordinates in the static arrays for
// boat location
switch (num)
{
case 1:
boatOneLocationP1[counter][0] = r;
boatOneLocationP1[counter][1] = c;
break;
case 2:
boatTwoLocationP1[counter][0] = r;
boatTwoLocationP1[counter][1] = c;
break;
case 3:
boatThreeLocationP1[counter][0] = r;
boatThreeLocationP1[counter][1] = c;
break;
case 4:
boatFourLocationP1[counter][0] = r;
boatFourLocationP1[counter][1] = c;
break;
case 5:
boatFiveLocationP1[counter][0] = r;
boatFiveLocationP1[counter][1] = c;
break;
}
}
}
} else
// going forwards
{
for (int r = row1, counter = 0; r < row1 + boatLength; r++, counter++)
{
for (int c = col1; c < col1 + 1; c++)
{
p1[r][c] = 1;
// Record coordinates in the static arrays for
// boat location
switch (num)
{
case 1:
boatOneLocationP1[counter][0] = r;
boatOneLocationP1[counter][1] = c;
break;
case 2:
boatTwoLocationP1[counter][0] = r;
boatTwoLocationP1[counter][1] = c;
break;
case 3:
boatThreeLocationP1[counter][0] = r;
boatThreeLocationP1[counter][1] = c;
break;
case 4:
boatFourLocationP1[counter][0] = r;
boatFourLocationP1[counter][1] = c;
break;
case 5:
boatFiveLocationP1[counter][0] = r;
boatFiveLocationP1[counter][1] = c;
break;
}
}
}
}
}
}
if (p.getPlayerNumber() == 2)
{
if (row1 == row2)
{
if (col1 + boatLength - 1 > 9
|| (starting.charAt(1) > ending.charAt(1)))
{
for (int r = row1; r < row1 + 1; r++)
{
for (int c = col1, counter = 0; c > col1
- boatLength; c--, counter++)
{
p2[r][c] = 1;
// Record coordinates in the static arrays for
// boat location
switch (num)
{
case 1:
boatOneLocationP2[counter][0] = r;
boatOneLocationP2[counter][1] = c;
break;
case 2:
boatTwoLocationP2[counter][0] = r;
boatTwoLocationP2[counter][1] = c;
break;
case 3:
boatThreeLocationP2[counter][0] = r;
boatThreeLocationP2[counter][1] = c;
break;
case 4:
boatFourLocationP2[counter][0] = r;
boatFourLocationP2[counter][1] = c;
break;
case 5:
boatFiveLocationP2[counter][0] = r;
boatFiveLocationP2[counter][1] = c;
break;
}
}
}
} else
{
for (int r = row1; r < row1 + 1; r++)
{
for (int c = col1, counter = 0; c < col1
+ boatLength; c++, counter++)
{
p2[r][c] = 1;
// Record coordinates in the static arrays for
// boat location
switch (num)
{
case 1:
boatOneLocationP2[counter][0] = r;
boatOneLocationP2[counter][1] = c;
break;
case 2:
boatTwoLocationP2[counter][0] = r;
boatTwoLocationP2[counter][1] = c;
break;
case 3:
boatThreeLocationP2[counter][0] = r;
boatThreeLocationP2[counter][1] = c;
break;
case 4:
boatFourLocationP2[counter][0] = r;
boatFourLocationP2[counter][1] = c;
break;
case 5:
boatFiveLocationP2[counter][0] = r;
boatFiveLocationP2[counter][1] = c;
break;
}
}
}
}
} else
// Columns the same
{
if (row1 + boatLength - 1 > 9
|| (starting.charAt(0) > ending.charAt(0)))
{
// Going backwards
for (int r = row1, counter = 0; r > row1 - boatLength; r--, counter++)
{
for (int c = col1; c < col1 + 1; c++)
{
p2[r][c] = 1;
// Record coordinates in the static arrays for
// boat location
switch (num)
{
case 1:
boatOneLocationP2[counter][0] = r;
boatOneLocationP2[counter][1] = c;
break;
case 2:
boatTwoLocationP2[counter][0] = r;
boatTwoLocationP2[counter][1] = c;
break;
case 3:
boatThreeLocationP2[counter][0] = r;
boatThreeLocationP2[counter][1] = c;
break;
case 4:
boatFourLocationP2[counter][0] = r;
boatFourLocationP2[counter][1] = c;
break;
case 5:
boatFiveLocationP2[counter][0] = r;
boatFiveLocationP2[counter][1] = c;
break;
}
}
}
} else
// going forwards
{
for (int r = row1, counter = 0; r < row1 + boatLength; r++, counter++)
{
for (int c = col1; c < col1 + 1; c++)
{
p2[r][c] = 1;
// Record coordinates in the static arrays for
// boat location
switch (num)
{
case 1:
boatOneLocationP2[counter][0] = r;
boatOneLocationP2[counter][1] = c;
break;
case 2:
boatTwoLocationP2[counter][0] = r;
boatTwoLocationP2[counter][1] = c;
break;
case 3:
boatThreeLocationP2[counter][0] = r;
boatThreeLocationP2[counter][1] = c;
break;
case 4:
boatFourLocationP2[counter][0] = r;
boatFourLocationP2[counter][1] = c;
break;
case 5:
boatFiveLocationP2[counter][0] = r;
boatFiveLocationP2[counter][1] = c;
break;
}
}
}
}
}
}
// userChoices[num-1] = 1; update statements
userChoices[num - 1] = 1;
menuChoices[num - 1] = 0;
// Check to see if we are ready to continue out of the loop.
notReady = true;
if (userChoices[0] == 1 && userChoices[1] == 1
&& userChoices[2] == 1 && userChoices[3] == 1
&& userChoices[4] == 1)
notReady = false;
System.out.println();
} while (notReady);
}
Everything seems to work just fine when I run the program in a driver class, unless during the lines....
// Get user input
System.out.print("\nEnter your menu choice: ");
num = kb.nextInt();
.... the user enters a String. In that case, the compiler throws an InputMismatchException.
I understand why I'm getting this error, but how can I prevent the user from inputting a String? I thought that the two while() statements I have following the user-input line would take care of that, but if given a String it still throws an Exception...
Any ideas on how to fix this? By the way, this is my first post here, so sorry if I posted way too much code. Figured I'd be more specific than vague.
EDIT: Thank you C.B. , ccjmne, and ryvantage, and everyone else who replied. All of your input led me to my final solution, which I'm showing below. If there's a better way of doing it, please let me know.
//Prompt user for menu choice
try
{
// Prompt user
System.out.print("Enter your menu choice: ");
// Get input from user
num = kb.nextInt();
} catch (InputMismatchException e)
{
System.out
.println("Error, invalid input. Try again.\n");
kb.next();
}
kb.nextLine();
// Input Validation- input must be a valid menu choice
while ((num != 1 && num != 2 && num != 3 && num != 4 && num != 5))
{
try
{
// Prompt user
System.out.print("Enter your menu choice: ");
// Get input from user
num = kb.nextInt();
} catch (InputMismatchException e)
{
System.out
.println("Error, invalid input. Try again.\n");
}
kb.nextLine();
}
// Further Validation- Make sure number has not been picked
// before yet
while (userChoices[num - 1] == 1)
{
try
{
// Prompt user
System.out.print("Enter your menu choice: ");
// Get input from user
num = kb.nextInt();
} catch (InputMismatchException e)
{
System.out
.println("Error, invalid input. Try again.\n");
}
kb.nextLine();
}
You need to catch
the InputMismatchException
and loop back around so that you can continue. Basically, your code needs to be:
while (userChoices[num - 1] == 1)
{
try {
System.out.print("Enter your menu choice: ");
num = kb.nextInt();
kb.nextLine();
} catch (InputMismatchException e) {
System.out.println("Error. Invalid input. Try again."); // Or whatever error message you want.
}
}
To further your programming skills, you should read up more about Exception handling in Java.
EDIT: Typically, you want to avoid catching Exceptions as a means of controlling program flow. The best practice is to avoid exceptions through better logic, but I'm really not well versed with console-based I/O, so I have no idea how you'd manage that. Especially when parsing numbers from String
s, I usually just use a try/catch hehe #guilty