The project is to create a version of the game battleship


Project Assignment: Battleship

The project is to create a version of the game Battleship where the user plays the computer. I think you will enjoy showing the project off to your friends after you finish. Make sure to fully document your code with comments as you write it, use proper indentation, create descriptive identifiers (variable, parameter, and function names), and eliminate all warnings and errors. No function should print to the screen, unless defined to do so in this specification. I will hold you to high standards for this project.

You have the option of choosing a partner to work on this project with you. If you choose to work with a partner, you need to let me know your partner's name by Thursday, November 9th. Otherwise, you will be expected to complete the project on your own.

Rules of the Game

The player has a 10 × 10 grid representing possible locations of the enemy's ships and a 10 × 10 grid where the player will place his or her fleet. The individual squares in the grid are identified by a row letter and a column number (e.g., B3 is the 2nd row and 3rd column). Before play begins, the enemy's fleet of ships is secretly positioned on the board. Likewise, the enemy does not know the locations of the player's ships.

Each ship occupies a number of consecutive tiles (squares) on the grid, arranged either horizontally or vertically. The number of tiles for each ship is determined by the type of the ship. The ships cannot overlap (i.e., only one ship can occupy any given square in the grid). The ship names and corresponding lengths are as follows:

Ship Name

Length

Aircraft Carrier

5

Battleship

4

Submarine

3

Destroyer

3

Patrol Boat

2

After the ships have been positioned, the game proceeds in a series of rounds. In each round, the player types a target coordinate in the opponent's grid which is to be shot at. The enemy then announces whether or not the shot was a "miss" or a "hit". Hits are displayed on the enemy's board as an 'X' and misses are displayed as an 'o'. Then the enemy announces a shot on a target tile on the player's board. The enemy is notified if it is a "miss" or a "hit". The player's board (grid) is updated to show the location of the shot. When all of the tiles of a ship have been hit, the ship is sunk, and the sinking is announced (e.g. "You sank the enemy's battleship!"). If all of a player's ships have been sunk, the game is over and their opponent wins.

Demo of Game

Program Specification

This project is divided into smaller problems that can be completed one at a time. Complete and thoroughly test each part before going on to the next part. Start with the code provided in the attached zip file. You will add your code to the battleship.cpp and gameSpecs.h files. The enemyAI.h file contains code I wrote to allow the computer to make semi-intelligent moves when playing against the human. Feel free to look over the AI code, learn how it works, and make changes, but be careful not to introduce any bugs. The AI sinks all the ships in an average of 50 turns, so there is room for improvement.

These instructions are long, but that is because I am giving you a lot of helpful details to make it easier for you. Follow these instructions carefully.

Part 1: Defining Types and Constants

The first step in creating your battleship game is to specify the important values used in the program. All of the code for this part must be placed in the gameSpecs.h header file between the #define ___GAME_SPECS___ and #endif lines. This custom header will be included in your cpp file and is also used by the provided enemyAI.h header file, so it must follow this specification exactly.

2. First, we need a new data type to store ship placement and hit/miss information. Create an enum type named Tile with the following values in the following order: WATER, AIRCRAFT_CARRIER, BATTLESHIP, SUBMARINE, DESTROYER, PATROL_BOAT, MISS, AIRCRAFT_CARRIER_HIT, BATTLESHIP_HIT, SUBMARINE_HIT, DESTROYER_HIT, and PATROL_BOAT_HIT.

3. Create a constant integer named BOARD_LENGTH that is set to 10, which is the height and width of each of the game boards.

4. Create a constant integer array named SHIP_SIZE where the array values are the sizes of each ship. The values must be ordered so that each index in the array corresponds with the matching Tile value. For example, SHIP_SIZE[AIRCRAFT_CARRIER] should equal 5. Since WATER == 0, the first element in the array should just be set to 0.

5. Create a function named tileToSymbol that accepts a Tile and returns a char. Use a switch statement for this function. For every Tile value representing a ship, the first letter in the ship's name should be returned. The letter should be capital unless the value indicates a "hit". For example, if the value is PATROL_BOAT, a 'P' is returned. If the value is PATROL_BOAT_HIT, the letter 'p' is returned. For WATER return '.' and for MISS return '~'. As a precaution, if the parameter value does not match any of the cases, output an error message to the screen and return a blank space.

6. Create a function named shipToString that accepts a Tile and returns a string value. In this function, use a switch statement to return the name of the tile without the word "Hit." For example, a parameter value of AIRCRAFT_CARRIER or AIRCRAFT_CARRIER_HIT should return "Aircraft Carrier". As a precaution, if none of the cases are matched, return "Error".

That is everything that should be added to gameSpecs.h; put the rest of your code in battleship.cpp. Write some temporary test code in main() to make sure everything is written correctly.

Part 2: Displaying the Game Boards

Before we display the game boards, we need to create them. We are going to use 2D arrays to store the location of ships, hits, and misses. Our Tile type from the previous part comes in handy here. In the main function, create two 2D arrays of type Tile that have BOARD_LENGTH columns and rows. One array is the board for the player's fleet and the other is for the computer's fleet.

Create a function called wipeBoard that accepts a board (2D array of Tiles) and a single Tile value. You do NOT need to pass the length/size of the array as a parameter, because the function may use the global constant BOARD_LENGTH that you defined in Part 1. The function should set all values in the array equal to the value of the second parameter. Give the second parameter a default value of WATER.

Create a function called displayBoards that displays both the player and enemy boards next to each other as shown in the demo video. The boards should be labeled "Enemy's Fleet" and "Your Fleet". Make sure that the board has the proper row letters and column numbers. Make good use of setw ().

The displayBoards function only shows three values on the enemy's board: hit (X), miss (o), and unknown (.). However, on the players board, it should show the player's fleet along with hits and misses (use the tileToSymbol function).

In addition to receiving constant references to the two boards, the function should include a third parameter named showAll with a default value of false. If this value is set to true the enemy's board should be displayed just like the player's board (with all the ship locations). This extra option is necessary to show the boards after the game is finished. It is also helpful for debugging your code.

Add temporary code to main() that wipes the boards, changes some tile locations in the boards to be different Tile values, and then calls displayBoards(). After you are confident that everything is working correctly, remove the temporary test code and you are ready for the next part.

Part 3: Placing the ships on the Boards

We are going to divide the task of placing the ships on the boards into subtasks.

7. Create a function called placeShipHorizontally that adds a ship to one row of the board and has five parameters: theTile value for the ship to be placed, the size/length of the ship, the X and Y coordinate of its top left index (where 0, 0 is A1), and a reference to the 2D board array.

The function is value returning. Before changing any value on the board, the function first checks that the ship position is valid. That means that the front-left index is NOT less than (0, 0) and the bottom-right position does not go beyond what can fit on the board. It also should check that there are no ships currently on the board that overlap with the placement of the new ship. If the ship placement is not valid, the function should return false.

If the ship placement is valid, the function should properly set the Tile values to be the ship's value and return true.

8. Create a function called placeShipVertically that does the same thing as placeShipHorizontally, except it places the ship along one column of the board if the placement is valid.

9. Make sure to test these two functions using displayBoards, before continuing.

10. Create a function called placeShipsRandomly that accepts one parameter: a 2D board array. The function should iterate over all the Tile values from AIRCRAFT_CARRIER to PATROL_BOAT. For each value, the following should be done until the ship is placed in a valid location on the board.

1. A random top-left position should be generated. Hint: review Example 5-6 of the textbook to see how to generate random numbers in C++. Also, check out this video: Random Numbers in C++

2. At random, a call to placeShipVertically or placeShipHorizontally should be performed with the ship type, random top-left position, and the board.

3. If the ship placement was unsuccessful (the call to the ship placement function returned false), then repeat the previous two steps.

Hint: A do...while loop is perfect to handle the repetition until a valid position and orientation is randomly generated.

11. Create a function named placePlayersShips that accepts one parameter, the player's board. This function should do the following:

1. Set all the values of the board to WATER using wipeBoard()

2. Place all the ships randomly on the board using placeShipsRandomly

3. Call displayBoards to show the player the current layout of his/her fleet. Hint: you can pass the player's board as both parameters of displayBoards, since no shots have been fired yet.

4. Repeatedly, ask the user if they want to play with this board until they enter y or n. If they enter something else, ignore everything until a '\n' is reached before asking again.

5. Repeat these steps to get a new layout of the player's fleet until the player enters 'y'.

12. In main(), seed the random number generator using srand(), call placeShipsRandomly() to place ships on the enemy board, and call placePlayersShips() to place the ships on the player's board.

Again, make sure to test your code to make sure it works with a range of inputs before continuing. The more code you have left untested, the harder it becomes to track down bugs when they appear.

Part 4: The Player's Turn

First we need to keep track of how many hits are left on each ship before it sinks. In main(), create two 1D integer arrays of length 6. Initialize their values to be the same as those in the SHIP_SIZE array. One array is for the player's ships and the other is for the enemy's ships. Again, the value at the first index will not be used, but allows us to use the Tile values as indexes into the array.

Create a function called playersTurn that has two parameters: the enemy's board and the array of hits remaining for the enemy's ships. The function should return a string, which will be a message about the player's turn to be displayed. Create a do...while loop that prompts the player to "enter the coordinates for a shot (e.g. B2)." Then read in a character for the row and an integer for the column. Convert these values to indexes (you should allow the user to enter lowercase or uppercase row letters). Make sure the calculated indexes are between 0 and 9 (BOARD_LENGTH - 1). Also, make sure that the user has not fired a shot at these coordinates before. If any of these conditions are not met, output an appropriate error message and ask for a new coordinate.

After validating the input, check the location to see if it is a hit or a miss outside of the loop. If it was a hit, update the appropriate value in the hits-remaining array. The function should not print anything to the screen (unless there is an error), but return a message containing the following:

13. The user's shot coordinates (with a capital row letter). Hint: To concatenate the column number to a string, you will first need to convert the number to a string using to_string(colNumber), where colNumber is an int variable holding the column number.

14. If it was a hit or a miss, followed by a newline character

15. Output the following only if the shot sunk a ship. Append to the message a tab character and then the phrase, "You sunk the enemy's ", followed by the name of the ship (use shipToString()), followed by an exclamation point, and finally a newline character.

Part 5: The Game Loop

The major step is to put it all together in main(). After you have placed the ships on the board, create a do...while loop that contains the following:

16. Display the two boards.

17. Have the player make his/her turn.

18. Display "Your shot: " followed by the message returned by playersTurn() in the previous step.

19. Break out of the loop if the enemy's ships are sunk. I suggest creating a function called isAllZeros that returns true if all the values in the 1D array are zero. Then you can use this to check the array of shots remaining per ship. (Don't forget to include the array's length as parameter for generalizability).

20. Display the boards again.

21. Call enemyTurn(), which is declared in the EnemyAI namespace of enemyAI.h.

22. Display the "Enemy's shot: " followed by the message returned from enemyTurn() in the previous step.

After the loop, print a message indicating if the player won or lost. Then display the boards one last time with all the enemy positions revealed.

Part 6: Simple Animations

It is a little difficult to see the results of player and enemy shots, because so much changes on the screen. To reduce this problem and make things more visually appealing, do the following:

• Included in your battleship.cpp file is a function named randomCoordinatesAnimation. Take a look at the comments to see what it does and how it works. Use that function right before you display the enemy's shot coordinates, but after the words, "Enemy's shot: ". Check that your output matches the demo video.

• Create another void function called displayAsIfTyped that will display a message by adding characters to the screen one at a time with a little delay between displaying them. This function makes it look like the output is being typed. The function should accept three parameters: a constant string reference containing the message to be typed out, an integer containing the time in milliseconds to be taken to output the whole message (with a default value of 1000), and the last parameter is how long to pause after typing the whole message (default set to 500, which is a half second). Hint: use randomCoordinatesAnimation() as an example. You will need to use this_thread::sleep_for() and chrono::milliseconds() to pause between characters.

• Add extra newline characters to the game loop and possibly display the hit information more than once to "clear" old output.

Request for Solution File

Ask an Expert for Answer!!
C/C++ Programming: The project is to create a version of the game battleship
Reference No:- TGS02512942

Expected delivery within 24 Hours