Answered step by step
Verified Expert Solution
Link Copied!

Question

00
1 Approved Answer

This is a Java BattleShip Program contaning methods. I need the methods checkWater, addShip, printBoard, placeShip and placeRandomShip. Please check the ones given are correct

This is a Java BattleShip Program contaning methods. I need the methods checkWater, addShip, printBoard, placeShip and placeRandomShip. Please check the ones given are correct and also that addShip is completed. Thanks.

Also I need 2 tests per test method for testCheckWater and testPlaceShip.

Here is the code for the file Battleship.java:

import java.util.Scanner; import java.util.Random;

public class Battleship {

/** * This method converts a String representing a base (or radix) 26 number into a decimal (or * base 10) number. The String representation of the base 26 number uses the letters of the * Latin alphabet to represent the 26 digits. That is, A represents 0, B represents 1, C * represents 2, ..., Y represents 24, and Z represents 25. * * A couple of examples: BAAA = 1 * 26^3 + 0 * 26^2 + 0 * 26^1 + 0 * 26^0 = 17576 ZERTY = 25 * * 26^4 + 4 * 26^3 + 17 * 26^2 + 19 * 26^1 + 24 * 26^0 = 11506714 * * For this method: - use Math.pow to calculate the powers of 26. - don't assume that the input * is in any particular case; use toUpperCase(). - don't check that the input is only 'A' to * 'Z'. - calculate the value of each digit relative to 'A'. - start from either the first or * last character, and calculate the exponent based on the index of each character. * * @param coord The coordinate value in base 26 as described above. * @return The numeric representation of the coordinate. */ public static int coordAlphaToNum(String coord) { int result = 0; for (int i = 0; i < coord.length(); ++i) { int num = Character.toUpperCase(coord.charAt(i)) - 'A'; result = result + (num * (int) Math.pow(26, coord.length() - i - 1)); } return result; }

/** * This method converts an int value into a base (or radix) 26 number, where the digits are * represented by the 26 letters of the Latin alphabet. That is, A represents 0, B represents 1, * C represents 2, ..., Y represents 24, and Z represents 25. A couple of examples: 17576 is * BAAA, 11506714 is ZERTY. * * The algorithm to convert an int to a String representing these base 26 numbers is as follows: * - Initialize res to the input integer - The next digit is determined by calculating the * remainder of res with respect to 26 - Convert this next digit to a letter based on 'A' - Set * res to the integer division of res and 26 - Repeat until res is 0 * * @param coord The integer value to convert into an alpha coordinate. * @return The alpha coordinate in base 26 as described above. If coord is negative, an empty * string is returned. */ public static String coordNumToAlpha(int coord) { String result = ""; while (coord > 0) { int res = coord % 26; res += 'A'; char nextDigit = (char) res; result = nextDigit + result; coord = coord / 26; } return result; }

/** * Prompts the user for an integer value, displaying the following: "Enter the valName (min to * max): " Note: There should not be a new line terminating the prompt. valName should contain * the contents of the String referenced by the parameter valName. min and max should be the * values passed in the respective parameters. * * After prompting the user, the method will read an int from the console and consume an entire * line of input. If the value read is between min and max (inclusive), that value is returned. * Otherwise, "Invalid value." terminated by a new line is output and the user is prompted * again. * * @param sc The Scanner instance to read from System.in. * @param valName The name of the value for which the user is prompted. * @param min The minimum acceptable int value (inclusive). * @param min The maximum acceptable int value (inclusive). * @return Returns the value read from the user. */ public static int promptInt(Scanner sc, String valName, int min, int max) { System.out.print("Enter the " + valName + " (" + min + " to " + max + "): "); int num = sc.nextInt(); if (min <= num && max >= num) { return num; } else { System.out.println("Invalid value."); return promptInt(sc, valName, min, max); } }

/** * Prompts the user for an String value, displaying the following: "Enter the valName (min to * max): " Note: There should not be a new line terminating the prompt. valName should contain * the contents of the String referenced by the parameter valName. min and max should be the * values passed in the respective parameters. * * After prompting the user, the method will read an entire line of input, trimming any trailing * or leading whitespace. If the value read is (lexicographically ignoring case) between min and * max (inclusive), that value is returned. Otherwise, "Invalid value." terminated by a new line * is output and the user is prompted again. * * @param sc The Scanner instance to read from System.in. * @param valName The name of the value for which the user is prompted. * @param min The minimum acceptable String value (inclusive). * @param min The maximum acceptable String value (inclusive). * @return Returns the value read from the user. */ public static String promptStr(Scanner sc, String valName, String min, String max) { System.out.print("Enter the " + valName + " (" + min + " to " + max + "): "); String str = sc.nextLine(); str = str.trim(); String min_ = min.toUpperCase(); String max_ = max.toUpperCase(); str = str.toUpperCase(); if (min_.compareTo(str) <= 0 && str.compareTo(max_) <= 0) { return str; } else { System.out.println("Invalid value."); return promptStr(sc, valName, min, max); } }

/** * Prompts the user for an char value. The prompt displayed is the contents of the String * referenced by the prompt parameter. Note: There should not be a new line terminating the * prompt. * * After prompting the user, the method will read an entire line of input and return the first * non-whitespace character in lower case. * * @param sc The Scanner instance to read from System.in * @param prompt The user prompt. * @return Returns the first non-whitespace character (in lower case) read from the user. If * there are no non-whitespace characters read, the null character is returned. */ public static char promptChar(Scanner sc, String prompt) { System.out.println(prompt); String in = sc.next(); in = in.trim(); in = in.toLowerCase(); return in.charAt(0); }

/** * Initialises a game board so that all the entries are Config.WATER_CHAR. * * @param board The game board to initialise. */ public static void initBoard(char board[][]) { for (int i = 0; i < board.length; ++i) { for (int j = 0; j < board[i].length; ++j) { board[i][j] = Config.WATER_CHAR; } } }

/** * Prints the game boards as viewed by the user. This method is used to print the game boards as * the user is placing their ships and during the game play. * * Some notes on the display: - Each column printed will have a width of Config.MAX_COL_WIDTH. - * Each row is followed by an empty line. - The values in the headers and cells are to be right * justified. * * @param board The board to print. * @param caption The board caption. */ public static void printBoard(char board[][], String caption) { System.out.println(caption); for(int i = 0; i < board.length; ++i) { for(int j = 0;j < board[i].length; ++j) { System.out.print(board[i][j] + " "); } System.out.println(); } }

/** * Determines if a sequence of cells of length len in a game board is clear or not. This is used * to determine if a ship will fit on a given game board. The x and y coordinates passed in as * parameters represent the top-left cell of the ship when considering the grid. * * @param board The game board to search. * @param xcoord The x-coordinate of the top-left cell of the ship. * @param ycoord The y-coordinate of the top-left cell of the ship. * @param len The length of the ship. * @param dir true if the ship will be vertical, otherwise horizontal * @return 1 if the cells to be occupied by the ship are all Config.WATER_CHAR, -1 if the cells * to be occupied are not Config.WATER_CHAR, and -2 if the ship would go out-of-bounds * of the board. */ public static int checkWater(char board[][], int xcoord, int ycoord, int len, boolean dir) { int result = -2; if (dir) { for (int i = 0; i < board.length; ++i) { int counter1 = 0; int counter2 = 0; boolean water = true; for (int j = 0; j < board.length; ++j) { if (board[j][i] == Config.WATER_CHAR) { ++counter1; } if (board[j][i] != Config.WATER_CHAR) { ++counter2; } } if (counter1 == board.length && counter1 >= len) { result = 1; } else if (counter2 == board.length && counter2 >= len) { result = -1; } } } else { for(int i = 0; i < board.length; ++i) { int counter1 = 0; int counter2 = 0; boolean water = true; for(int j = 0; j < board[i].length; ++j) { if (board[i][j] == Config.WATER_CHAR) { ++counter1; } if (board[i][j] != Config.WATER_CHAR) { ++counter2; } } if (counter1 == board[i].length && counter1 >= len) { result = 1; } else if (counter2 == board[i].length && counter2 >= len) { result = -1; } } } return result; }

/** * Checks the cells of the game board to determine if all the ships have been sunk. * * @param board The game board to check. * @return true if all the ships have been sunk, false otherwise. */ public static boolean checkLost(char board[][]) { // FIXME return false; }

/** * Places a ship into a game board. The coordinate passed in the parameters xcoord and ycoord * represent the top-left coordinate of the ship. The ship is represented on the game board by * the Character representation of the ship id. (For this method, you can assume that the id * parameter will only be values 1 through 9.) * * @param board The game board to search. * @param xcoord The x-coordinate of the top-left cell of the ship. * @param ycoord The y-coordinate of the top-left cell of the ship. * @param len The length of the ship. * @param dir true if the ship will be vertical, otherwise horizontal. * @param id The ship id, assumed to be 1 to 9. * @return false if the ship goes out-of-bounds of the board, true otherwise. */ public static boolean placeShip(char board[][], int xcoord, int ycoord, int len, boolean dir, int id) { if (dir == true) { if (ycoord + len >= Config.MAX_HEIGHT) { return false; } for (int i = ycoord; i < ycoord + len; ++i) { board[i][xcoord] = (char) ('0' + id); } return true; } else { if (xcoord + len >= Config.MAX_WIDTH) { return false; } for (int i = xcoord; i < xcoord + len; ++i) { board[ycoord][i] = (char) ('0' + id); } return true; } }

/** * Randomly attempts to place a ship into a game board. The random process is as follows: 1 - * Pick a random boolean, using rand. True represents vertical, false horizontal. 2 - Pick a * random integer, using rand, for the x-coordinate of the top-left cell of the ship. The number * of integers to choose from should be calculated based on the width of the board and length of * the ship such that the placement of the ship won't be out-of-bounds. 3 - Pick a random * integer, using rand, for the y-coordinate of the top-left cell of the ship. The number of * integers to choose from should be calculated based on the height of the board and length of * the ship such that the placement of the ship won't be out-of-bounds. 4 - Verify that this * random location can fit the ship without intersecting another ship (checkWater method). If * so, place the ship with the placeShip method. * * It is possible for the configuration of a board to be such that a ship of a given length may * not fit. So, the random process will be attempted at most Config.RAND_SHIP_TRIES times. * * @param board The game board to search. * @param len The length of the ship. * @param id The ship id, assumed to be 1 to 9.. * @param rand The Random object. * @return true if the ship is placed successfully, false otherwise. */ public static boolean placeRandomShip(char board[][], int len, int id, Random rand) { boolean dir = rand.nextBoolean(); for (int i = 0; i < Config.RAND_SHIP_TRIES; ++i) { int xcoord = rand.nextInt(Config.MAX_WIDTH - len); int ycoord = rand.nextInt(Config.MAX_HEIGHT - len); if (checkWater(board, xcoord, ycoord, len, dir) == 1) { boolean canPlace = placeShip(board, xcoord, ycoord, len, dir, id); if (canPlace == true) { return true; } } } return false; }

/** * This method interacts with the user to place a ship on the game board of the human player and * the computer opponent. The process is as follows: 1 - Print the user primary board, using the * printBoard. 2 - Using the promptChar method, prompt the user with "Vertical or horizontal? * (v/h) ". A response of v is interpreted as vertical. Anything else is assumed to be * horizontal. 3 - Using the promptInt method, prompt the user for an integer representing the * "ship length", where the minimum ship length is Config.MIN_SHIP_LEN and the maximum ship * length is width or height of the game board, depending on the input of the user from step 1. * 4 - Using the promptStr method, prompt the user for the "x-coord". The maximum value should * be calculated based on the width of the board and the length of the ship. You will need to * use the coordAlphaToNum and coordNumToAlpha methods to convert between int and String values * of coordinates. 5 - Using the promptInt method, prompt the user for the "y-coord". The * maximum value should be calculated based on the width of the board and the length of the * ship. 6 - Check if there is space on the board to place the ship. 6a - If so: - Place the * ship on the board using placeShip. - Then, call placeRandomShip to place the opponents ships * of the same length. - If placeRandomShip fails, print out the error message (terminated by a * new line): "Unable to place opponent ship: id", where id is the ship id, and return false. 6b * - If not: - Using promptChar, prompt the user with "No room for ship. Try again? (y/n): " - * If the user enters a 'y', restart the process at Step 1. - Otherwise, return false. * * @param sc The Scanner instance to read from System.in. * @param boardPrime The human player board. * @param boardOpp The opponent board. * @param id The ship id, assumed to be 1 to 9. * @param rand The Random object. * @return true if ship placed successfully by player and computer opponent, false otherwise. */

public static boolean addShip(Scanner sc, char boardPrime[][], char boardOpp[][], int id, Random rand) { printBoard(boardPrime, "My Ships"); char ch = promptChar(sc, "Vertical or horizontal? (v/h) "); boolean dir = ch == 'v' ? true : false; if (dir == true) { int len = promptInt(sc, "ship length", Config.MIN_SHIP_LEN, boardPrime.length); } else { int len = promptInt(sc, "ship length", Config.MIN_SHIP_LEN, boardPrime[0].length); } String xcoordStr = promptStr(sc, "x-coord", coordNumToAlpha(0), coordNumToAlpha(boardPrime[0].length - len)); return false; }

Here is the code for Config.java:

/** * This class contains the constants used in the Battleship program. These constants may be changed * when testing. So, your program should use the constants, not the values. * * @author Marc Renault */ public class Config {

/** * Minimum and maximum values used in the program */ public static final int MIN_WIDTH = 1; //Minimum number of columns public static final int MAX_WIDTH = 675; //Maximum number of columns public static final int MIN_HEIGHT = 1; //Minimum number of rows public static final int MAX_HEIGHT = 99; //Maximum number of rows public static final int MAX_COL_WIDTH = 3; //Maximum number of characters per column public static final int MIN_SHIPS = 1; //Minimum number of ships public static final int MAX_SHIPS = 9; //Maximum number of ships public static final int MIN_SHIP_LEN = 1; //Minimum ship length

/** * Character values for displaying the different statuses of the game board cells. */ public static final char WATER_CHAR = '~'; // Water character (not yet targeted) public static final char HIT_CHAR = '*'; // Hit character public static final char MISS_CHAR = '@'; // Miss character

/** * Constants for the random processes. */ public static final long SEED = 1234; // The random seed public static final int RAND_SHIP_TRIES = 20; // Maximum number of tries to place a ship }

Here is the code for TestBattleship.java:

/** * This file contains testing methods for the Battleship project. These methods are intended to * provide an example of a way to incrementally test your code, and to provide example method calls * for the Battleship methods * * Toward these objectives, the expectation is that part of the grade for the Battleship project is * to write some tests and write header comments summarizing the tests that have been written. * Specific places are noted with FIXME but add any other comments you feel would be useful. */

import java.util.Random; import java.util.Scanner;

/** * This class contains a few methods for testing methods in the Battleship * class as they are developed. These methods are all private as they are only * intended for use within this class. * * @author Marc Renault * @author FIXME add your name here when you add test * */ public class TestBattleship {

/** * This is the main method that runs the various tests. Uncomment the tests when * you are ready for them to run. * * @param args (unused) */ public static void main(String[] args) { // Milestone 1 testCoordAlphaToNum(); testCoordNumToAlpha(); // Milestone 2 testCheckWater(); testPlaceShip(); // Milestone 3 testTakeShot(); testCheckLost(); } private static void testCoordAlphaToNum() { int numTests = 4; int passed = numTests; int res; if((res = Battleship.coordAlphaToNum("BAAA")) != 17576) { System.out.println("FAILED: Battleship.coordAlphaToNum(\"BAAA\") != 17576, but " + res); passed--; } if((res = Battleship.coordAlphaToNum("ZERTY")) != 11506714) { System.out.println("FAILED: Battleship.coordAlphaToNum(\"ZERTY\") != 11506714, but " + res); passed--; } if((res = Battleship.coordAlphaToNum("zerty")) != 11506714) { System.out.println("FAILED: Battleship.coordAlphaToNum(\"zerty\") != 11506714, but " + res); passed--; } if((res = Battleship.coordAlphaToNum("&\"")) != -14747) { System.out.println("FAILED: Battleship.coordAlphaToNum(\"&\\\"\") != -14747, but " + res); passed--; } if((res = Battleship.coordAlphaToNum("baaa")) != 17576) { System.out.println("FAILED: Battleship.coordAlphaToNum(\"baaa\") != 17576, but " + res); passed--; } if ((res = Battleship.coordAlphaToNum("YeEt")) != 425354) { System.out.println("FAILED: Battleship.coordAlphaToNum(\"YeEt\") != 425354, but " + res); } System.out.println("testCoordAlphatoNum: Passed " + passed + " of " + numTests + " tests."); }

private static void testCoordNumToAlpha() { //FIXME } private static void testCheckWater() { //FIXME } private static void testPlaceShip() { //FIXME }

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access with AI-Powered Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Students also viewed these Databases questions