Question
Assignment overview In this assignment, you will implement the following the classes: Gameboard: Tile Game this program should be less than 10 lines of code.
Assignment overview
In this assignment, you will implement the following the classes:
- Gameboard:
- Tile
- Game
- this program should be less than 10 lines of code.
- there are two players that each have a 10 by 10 grid where ships are placed.
- Battleship that any number of players (>= 2) can play, with any sized two dimensional grids
Phase 1: Gameboard and Tiles
First, implement two simple classes: a Tile class and a Gameboard class.
The Tile class is a representation of a single space on the board. The Tile class should have:
- Three instance variables: wasAttacked, hasShip, and displayLetter. Instance variable wasAttacked stores whether or not an attack was made on this Tile. Instance variable hasShip stores true if there is a ship placed on this Tile. Finally, displayLetter is the char potentially shown by the Tile. The way the tiles are displayed is described below.
- Constructor Tile() that sets displayLetter to the character ~, which represents a wave. Note that the constructor takes no parameters.
- Method setDisplayLetter(char letter). This is a mutator/setter method for displayLetter.
-
- A getDisplay(boolean isOpponent) instance method. The method returns the character, as a String, to display when showing this tile to the user. o If this gameboard is the players (that is, isOpponent == false) Show the character saved in displayLetter if it has not been attacked, and has a ship.
- Show a wave (~) if this tile has not been attacked, and does not have a ship.
- Show a splash (^) if this tile does not have a ship, and has been attacked.
- Show an explosion (*) if this tile has been attacked, and does have a ship.
- o If this gameboard belongs to the opponent. We do not show the ship locations for opponent boards. Show a wave (~) if this tile has not been attacked.
- Show a splash (^) if this tile does not have a ship, and has been attacked.
- Show an explosion (*) if this tile has been attacked, and does have a ship.
- Method attack() which sets wasAttacked to true.
- Method canPlaceShip(), that returns a boolean. The method returns true if a ship could be placed on this Tile. A ship can be placed if this tile has not been attacked, and does not have a ship placed on it already.
- Method activeShip(), that returns true if there is a ship on this tile, and it has not been attacked.
The Gameboard class is a two-dimensional array of Tile objects, creating a game board for a single player. Complete the following:
- Gameboard has two instance variables. A two-dimensional array of Tile objects for the gameboard, and a boolean isOpponent that stores whether or not this is a player board, or an opponent board.
- A Constructor that accepts three values: int row the number of rows, int column the number of columns, and boolean isOpponent true if this board is owned by your opponent.
- A toString() method which returns a string representation of the entire gameboard. If this is an opponents board, then the ship locations should not be shown.
- Method getRow(int rowNum), which fetches row rowNum from the board, returning it as a String. The returned String should not have a newline character in it. Use class Tiles getDisplay method to fetch the values from the Tiles, not showing the opponent ship locations to the user. This method is used to extract a single row from the gameboard for displaying to the user.
- Method doAttack(int row, int column). This method sets the isAttacked flag on the tile at index row, column.
Sample output from A2TestPhase1.java:
Should be a wave ~: ~
Should be a splash ^: ^
Should be a splash ^: ^
Should be a C: C
Should be a ~: ~
Should be an explosion *: *
Print a 2x2 board of waves ~:
~~
~~
Should have a splash ^ on second row, second column
~~
~^
Should be ^~ : ^~
Should be ~^ : ~^
Print splashes down the x=y axis of a 3x3 board:
^~~
~^~
~~^
Phase 2: Extracting and reshaping data
We need to be able to pull data out of our gameboard. These methods will be used in later phases. Add the following methods to Gameboard:
- Method extractRow(int row). This method returns a 1D Tile array containing the contents of the specified row. Do not simply return the array from the gameboard, this will cause issues later. Create a new array, and fill it with references to the Tile objects in the desired row.
- Method extractColumn(int column). This method returns a 1D Tile array containing the contents of the specified column. Create an array that is the same length as the number of rows in the gameboard. Fill this array with the references to the Tiles from the desired column.
- A static void method reverse(Tile [] data). The provided array is reversed in place. This method does not return anything. Example: o reverse is given array [~, ~, ^, ^, *]
- o When method completes, the array should be [*, ^, ^, ~, ~]
Sample output from A2TestPhase2.java:
Print a 2x3 board of waves ~:
~~~
~~~
Should have a splash on second row, second and third column
~~~
~^^
Should be ~^^
~^^
Should be ^^~
^^~
Should be ~^
~^
Should be ^~
^~
The original should be unchanged
~~~
~^^
Phase 3: Ships and victory
In this phase, we begin adding ships to the board. Add the method boolean addShip(int row, int col, int length, int direction, char display). It has the following arguments:
- int row The row index of the start of the ship
- int col The column index of the start of the ship
- int length The length the ship being place is
- int direction The direction of the ship should be placed. Place the ship, starting at the index given by row and col. The value passed will be one of the constants UP, DOWN, LEFT, RIGHT, defining which direction to go from the provided starting point.
- char display The letter this ship will be represented as on the game board.
The addShip method should return true if the ship could be placed, and false if the ship could not be placed. If the ship can be placed, the tiles the ship occupies are updated with the char passed as display. The addShip method, or its helper methods, must validate if the ship can be placed on the board. The ship cannot be placed if:
- There is a different ship already placed in the same place (or in some of the tiles)
- The ship would run off the side of the board.
- The ship would be placed on a Tile that has been attacked.
The direction of the ship is controlled by constants. Create public static final int constants in Gameboard named UP, DOWN, LEFT, and RIGHT. You can set any values for these constants, provided you do not use the same number twice.
The addShip method should call methods extractColumn, extractRow and reverse to fetch the data, and adjust the data. Create the following helper methods to break the addShip method into smaller pieces:
- private static boolean method canPlaceShipInArray(Tile [] tiles, int start, int length). The method checks to see if a ship could be placed in this array, starting at the start point, with the provided length. The method returns true if the ship can be placed, and false if the ship cannot be placed. Example: o The array starts as boardData = [~, ~, ~, ~, ~]
- o canPlaceShipInArray( boardData, 1, 3); would return true, the ship can be placed.
- private static void method placeShipInArray(Tile [] tiles, int start, int length, char letter). This method adds a ship into this array. Use the setDisplayLetter method on each Tile object where a ship will be placed, providing the display letter passed. Do not create new Tiles here. Only update the Tiles provided. For example, continuing from above: o boardData is currently [~, ~, ~, ~, ~]
- o placeShipInArray(boardData, 1, 3, A) is called
- o boardData is now [~, A, A, A, ~]
Even with the helper methods, addShip is somewhat long. If it is well-written, it will be about 30 lines of code. Your code may be longer. These helper method should be set to be private.
Finally, add the method boolean hasLost(), which returns true if the player has lost. A player has lost if all their tiles that are occupied by ships have been attacked by the opponent.
Sample output from A2TestPhase3.java:
Print a 5x5 board of waves ~:
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
Added ship, should be true: true
Print a 5x5 with one ship, starting at [1,1]. with length 2:
~~~~~ ~~~~~
~AA~~ ~AA~~
~~~~~ ~~~~~
~~~~~ ~~~~~
~~~~~ ~~~~~
Added ship, should be true: true
Print a 5x5 with one ship, starting at [1,4]. with length 2:
~~~~~ ~~~~B
~AA~B ~AA~B
~~~~B ~~~~~
~~~~~ ~~~~~
~~~~~ ~~~~~
Added ship, should be true: true
Print a 5x5 with one ship, starting at [3,4]. with length 2:
~~~~~ ~~~~B
~AA~B ~AA~B
~~~~B ~~~~~
~~~CC ~~CC~
~~~~~ ~~~~~
Added ship, should be true: false
Print a 5x5 with one ship, starting at [4,2]. with length 2:
~~~~~ ~~~~B
~AA~B ~AA~B
~~~~B ~~~~~
~~DCC ~~CC~
~~D~~ ~~~~~
Added ship, should be false: false
Should be unchanged
~~~~B
~AA~B
~~~~~
~~CC~
~~~~~
Added ship, should be false: false
Should be unchanged
~~~~B
~AA~B
~~~~~
~~CC~
~~~~~
Added ship, should be false: false
Should be unchanged
~~~~B
~AA~B
~~~~~
~~CC~
~~~~~
Added ship, should be false: false
Should be unchanged
~~~~B
~AA~B
~~~~~
~~CC~
~~~~~
Should be waves
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
Should have an explosion * at 1, 1:
~~~~~
~*~~~
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
They should not have lost yet, should be false: false
Should have a splash ^ at 0, 0:
^~~~~
~*~~~
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
They should not have lost yet, should be false: false
Should have an explosion * at 9,3 and 9,4 :
^~~~~
~**~~
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
~~~~~
~~~~*
~~~~*
They should have lost, should be true: true
Phase 4: Game
Create a class that has two or more players that take turns attacking the other players ships. Create a new class named Game with the following specifications:
- Instance variable int turn, and an array of Gameboards. The turn variable is an integer, starting at 0. The player is always player 0, all non-zero players are computer players. Gameboard at index 0 is player 0s board, index 1 is player 1s board, and so on.
- Constructor Game(int height, int width, int numPlayers), which define the height and width of the game boards, and number of players in the game. Initialize the array of Gameboards to the number of players provided. Initialize all the Gameboards in the array.
- Method void randomAttack(), which randomly chooses any of the boards, and randomly chooses a single tile to attack on that board. Print out the index of board that has been attacked as well as the indices of the attacked Tile. Do not attack boards that have already lost, and do not attack the board of the current player. You may attack spots that have already been attacked. There are multiple ways to do this task. One solution is to write a loop that randomly selects boards until it finds a board that is not the current players, and has not lost. Creating a list of attackable boards, and randomly choosing an element from the list would also be a good solution.
- Method void attack(int playerID, int row, int column). Attack the player specified by player ID at the given row and column.
- Method void addShip(int player, int row, int col, int length, int direction, char letter). The method adds a ship on the board indicated by player.
- Method void playGame(), which plays the game. The method goes through the players, giving each player a turn to attack, going back to player 0 after all players have had a turn. A game ends when only one board has active ships. On a given turn: o If it is the players turn (player 0), show all the boards, then ask the user for a player ID to attack, and the row and column to attack. You may assume the user provides integer numbers for all the provided input. Use Scanner to read data from System.in. If the user provides bad input (player ID that does not exist, row or column index that does not exist), they miss their turn, and do not get to make an attack this round.
- o If it is a computer players turn, use the randomAttack method from above
-
- o When there is only one board with active ships, congratulate the player, and exit the method
To create random integers from 0 up to (and not including) a maximum number, you can use the following method
public static int random(int max) {
return (int)(Math.random() * max);
}
A2TestPhase4.java runs the game you have created. It adds two ships, and plays the game. Have fun with this stage, making games to play against the computer.
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started