p4-battleship

EECS 183 Project 4: Battleship

Due Friday, April 9th at 8:00 p.m. (accepted until 11:59:59 p.m.)

In this project, you will use C++ to create the classic Battleship game. You will implement it as a one-player game so a user will always be playing against the computer’s CPU. If you’re not a familiar with the game, take a look at the wikipedia page. Your game program will be able to read the player and CPU grids –containing the locations of war ships– using text files. Once the grids are set up, a user will continuously play the game by typing the moves they wish to play against the CPU. In turn, the CPU will retaliate with its own move. The game ends when all ships from either the user or the CPU are taken down, or when the maximum number of rounds is reached.

Beware the autograder-cheat-detector magic machine, see the Honor Code for further information.

board game

sunk

Learning Objectives

Honor Code

All students in the class are presumed to be decent and honorable, and all students in the class are bound by the College of Engineering Honor Code.

Any violation of the honor policies appropriate to each piece of coursework will be reported to the Honor Council, and if guilt is established penalties may be imposed by the Honor Council and Faculty Committee on Discipline. Such penalties can include, but are not limited to, letter grade deductions or expulsion from the University.

We run every submission against every other submission and determine similarities using a program called MOSS, developed at Stanford University specifically for the purpose of detecting software plagiarism. Code shared between students will cause MOSS to identify both students’ programs as “too similar”.

We also search the web for solutions posted online and compare them to your solutions. Searching the web, by the way, is something that we are very good at.

All projects that are “too similar” are forwarded to the Engineering Honor Council.

Note that on all cases forwarded to the Engineering Honor Council the LSA Dean of Academic Affairs is also notified. Furthermore, please be aware that by LSA administrative policy students involved in honor violations cannot withdraw from nor drop the course.

Grading

Testing (10 points)
Write a test suite in test.cpp. To receive a 5% bonus for this part, submit it no later than April 7th. To receive a 2.5% bonus, submit no later than April 8th.

Correctness (60 points)
Implement functions in Position.cpp, Ship.cpp, Player.cpp, and Game.cpp. To what extent does your code implement the features required by our specification? To what extent is your code consistent with our specifications and free of bugs? To receive a 5% bonus for this part, submit it no later than April 7th. To receive a 2.5% bonus, submit no later than April 8th.

Style (10 points)
To what extent is your code written well? To what extent is your code readable?

And some reminders:

Working with a Partner

Starter Files

We’ve written some code to get you started. You can download the starter files using this link.

After uncompressing starter-files.zip, you’ll find the following files:

WARNING: The files must be named exactly as they appear above, including capitalization. — Don’t change the file names. Altering the function declarations (prototypes) will cause you to fail the autograder.

To get started, just create a project as you have done before and add each of these into the project, one file at a time.

Start with test.cpp. This will hold all tests for the member functions of different classes. Create tests for each class and test each thoroughly before going onto the next class.

WARNING: DO NOT ALTER any of the .h files, utility.cpp, or the functions already implemented in the .cpp files.

Ultimately, you’ll need to edit the following files, and we suggest working on them in the orderering shown:

Again, it is strongly recomended to start with `test.cpp`!

To handle text files in your project make sure that any .txt file is in the same directory as the .cpp and .h files. You can make use of a filestream to read .txt files from your code.

Suggested Timeline

As an approximate timeline, you will be on track if by:

Testing

Classes

When it comes to a class, getting it to compile is only the beginning. There are many errors that do not show up at all until you call the different member functions. Therefore, in your testing, make sure you call every constructor and every member function.

To test class files, the best way is to set up a “driver” to test all member functions, including the constructors. Consider (and feel free to use) the following snippet of code as an example. Notice how we need to first declare a Position (p1 in this case) before we can test any of its member functions.

#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>

#include "Position.h"
#include "Ship.h"
#include "Player.h"
#include "Game.h"
#include "utility.h"

using namespace std;


void test_position();
void test_ship();
void test_player();
void test_game();

void startTests() {
    test_position();
    test_ship();
    test_player();

    return;
}

void test_position() {

    // test of default constructor
    Position p1;
    // test of the other constructor
    Position p2(3, 9);

    // test of member function: set_row(int row_in)
    p1.set_row(5);
    // test of member function: set_col(int col_in)
    p1.set_col(3);

    // test of member functions get_row() and get_col()
    cout << "( " << p1.get_row()
         << ", " << p1.get_col()
         << " )" << endl;

    // you can also do cin >> p1;
    p1.read(cin);
    cout << p1 << endl;
    return;
}

void test_ship() {
    // Write your tests here
    return;
}

void test_player() {
    // Write your tests here
    return;
}


void startTests() {

}

NOTE: Whenever you open a file for reading or writing, you will be reading or writing from the start of the file. If you open a file in a function, then reopen the same file in another function it will start at the beginning of the file again.

Position

The Position class represents a single set of coordinates on the player grid. Positions can be read in using two different text formats:

Positions in Battleship will be used to represent ships and moves. Every position has underlying integer values to represent an index in the grid. For a position (1,A), its underlying integer value will be 0 for the row and 0 for the col. The grid below has the underlying integer values of the positions in the first row, column, and diagonal.

Position

A Position of (1,A) will be stored as having row being 0 and col being 0

A valid position is any position on a valid grid (grid of max size: MAX_GRID_SIZE * MAX_GRID_SIZE).

The RME for Position::read() states: col is NOT case senstive, so reading should work for, e.g., "(1,a)" or "1a". A useful function to help with this is toupper(), which you can find in zyBooks. Be careful though - toupper() returns an int. Make sure to explicitly cast it to a char before using it!

Ship

The Ship class will be used to represent a ship in the Battleship game. Each ship has a start and end position that determines its size. For instance, if the starting position is (1,A) and the ending position is (1,C), the size of this ship will be 3. In the previous example, the start and end positions had the same row value, which indicates that the ship will be horizontal on the grid. Conversely, if the start and end positions of a ship had the same col value, the ship will be vertical on the grid. Note that the end position can come before the start position. For instance start can be (8,E), end can be (4,E), and this ship should have a size of 5. This means that the start position could have a greater value than the end position.

HINT: you may find it the abs() function useful for calculating ship sizes.

Ship

Ships will be represented by their start and end positions in a file as follows, (8,A) (8,B), where (8,A) is the start position and (8,B) is the end position. A valid ship will have length [2-5] inclusive.

A ship also keeps track of the number of times it was hit using its num_hits member variable. num_hits will be utilized when a ship is attacked and to determine whether or not a ship has sunk

A single ship can either be only in one column or one row (No ‘L’-shaped or diagonal-placed ships). Ships can not overlap the same location or intersect.

Player

A Player represents a player in the Battleship game. Below are explanations of each of the member variables in the Player class.

If a player has the ships represented by the following positions,

their grid will look as follows,

Player_grid

The asterisks (*) denotes a position that is a part of a ship and a dash (-) denotes an empty position.

Suppose your opponent attacks you at positions (1, A) and (4, A). Since (1, A) was not a part of your ships, that is a miss ('X'). On the other hand, (4, A) is a part of one of your ships of size 3, that is a hit ('O'). The result of the two moves are shown in the grid below.

Hit_miss

You can find the mapping of characters in `utility.h`.

Unfortunately, your grid on the console will not be color coded.

If hitting the ship causes that ship to sink, decrement the opponent’s remaining_ships, and use announce_ship_sunk() to print appropriate message.

Announcing ships by name,

The load_grid_file() function

As part of the Player class, you will implement a function to read in the start and end positions for each ship to be added to the player’s grid. Below are two examples of valid .txt files containing the ship inputs for a grid. These are also included in the distribution code.

grid1.txt
-----------
(8,A) (8,B)
(6,H) (8,H)
(1,G) (1,H)
(3,F) (3,H)
(3,A) (7,A)

grid2.txt
-----------
3F 3G
(1,A) (1,C)
1E 1G
(3,A) (6,A)
(8,D) (8,H)

To play a full game, a grid file should contain

  1. One ship of size 2, two ships of size 3, one ship of size 4 and one ship of size 5.

  2. On each row of the file, the first position is the start and the second position is the end of a ship.

  3. For each position, the row value must be in the range of [1, 8] and the col value should be between 'A' and 'H' inclusive.

A game of battleships typically has 5 ships. However, the input file contains an arbitrary number of ships, so there can be less than 5 ships or more than 5 ships. You should read all contents of the file and only add each ship represented by the start and end positions if there is still room for it.

NOTE: positions can be come in two different formats (see Position section). We’ll need to be able to read both.

Game

A Game represents a gameplay of Battleship. Each game has two players, player1 and player2.

`player2` will always be the CPU, and have the name `"CPU"`.

Non-default constructor

The Game class has a non-default constructor, which takes on two string-type parameters grid1 and grid2 along with two Player-type parameters called player1 and player2. grid1 and grid2 are the names of the files that will be used to initialize the player1 and player2 grids, respectively. Note that a human user will always be player1 and the computer will always be player2. If grid1 or grid2 are empty strings, the grid should be randomly generated for the respective players using the already-defined generate_random_grid function. There are four possible combinations as listed below,

Check out the load_grid_file() function in Player to see how a grid should be initialized from file.

When generating grids randomly, the Player class member functions print_grid() and print_guess_grid() may come in handy for debugging, since you will not know the positions of those player’s ships. These functions will print the grid of those players with the positions of their ships.

The start() function

The start() will start the game and keep on going until one of the players has all their ships sunk (i.e. destroyed) or the number of completed rounds has reached max_rounds. The following functions should be called inside the start() function:

get_move()

The human player will enter moves in the format <row><col>, where row is a number in the range [1, 8] and col is a letter from [A to H] inclusive. You do NOT need to check that the input is valid in this function.

Prompt for input: <p1 name> enter your move:

Example input: 2B

Other examples of the input format are included in the sample runs portion of the spec.

check_valid_move() (error handling)

The move is not valid if:

In start(), you must call get_move() first and then re-prompt the user for an input while the input is invalid.

HINT: Think of how you can utilize the return value of check_valid_move() in a conditional here.

REMEMBER: move.length() is a string library function that return the length of move as an integer.

Making the move

If your input is valid, then

  1. p2 will be attacked at that position. You will have to make use of the member function attack() to do so.

  2. p2 will attack you. This will be handled by calling the member function opponent_make_move(). You should pass difficulty that was passed into the start() function into opponent_make_move().

Printing the grids

After both p1 and p2 makes their moves, you must print out their grids in the following format:

Your grid
<grid>
CPU's grid
<opponent grid>

NOTE: You should utilize the member functions print_grid() and print_guess_grid() to print the grids.

End of game

If either one of the players has had all of their ships sunk (i.e. destroyed) or the number of completed rounds has reached max_rounds, print a message with the name of the winner and the number of rounds that have passed. If there is no winner, the name printed should be no one. The format of the message is as follows (the <> characters will not be printed).

Game over, winner is <winner name> in <number of rounds> rounds

The round in which either p1 or p2 wins should be counted. Also, the grids for both players should be printed regardless of whether the round is a winning round.

If either player has won during a round, the following player should not be able to make a move since they already lost.

Operator Overloading

In the distribution header file Position.h, you will notice the following code:

istream &operator>>(istream &ins, Position &pos);
ostream &operator<<(ostream &outs, Position pos);

These are special function declarations that are used to “overload” the functionality of the >> and << operators. Here are a few notes on how to interpret the first declaration:

  1. The function returns a object of type istream (the & just means that you are actually returning a reference to an istream).

  2. operator>> is actually just the name of the function. However, this function name is special because it tells C++ that you want this function to be called whenever a developer uses the >> operator like cin >> x;.

  3. Notice that, when you use the >> operator, there are two operands involved (e. g., cin and x in the previous sample statement). The two declared function parameters (the first of type istream and the second of type Position) lets C++ know that these are the left and right operands to be used, respectively, when calling >>. We’ve provided an example of this below.

  4. Similar to other functions, its implementation looks like:

    istream &operator>>(istream &is,  Position &pos) {
        pos.read(is);
        return is;
    }
    

In general, this practice is known as operator overloading and its pretty standard and useful in C++. It helps us here by allowing us to read or write data types beyond the primatives (int, bool, double, etc).

Example use of operator overloading for Position:

cout << "Please enter a position, in the form (row, col)"
    << endl << "where row is an integer between 1 and 8"
    << endl << "and col is a letter between A and H: ";
Position test_pos;
cin >> test_pos;

cout << test_pos << endl;

The above code would produce the following output:

Please enter a position, in the form (row, col)
where row is an integer between 1 and 8
and col is a letter between A and H: (1, A)
(1, A)

(File) I/O

File Locations

Xcode

There are a few things that must be done for Xcode. First, ensure that Derived Data is stored relative to your project folder. Select Xcode > Preferences in the menu bar, click on Locations icon at the top on the window and choose Relative next to Derived Data. This will ensure that executables are saved in your Project folder.

derivedData

Then, tell Xcode to look for files in the folder where all other project files are stored. From the menu bar, choose Product > Scheme > Edit Scheme.

editScheme

Select Run on the left, Options on top and then select the checkbox Use custom working directory and navigate to your Project folder where you will store input files.

customWorkingDir

Now you can place input txt files right with your .h and .cpp files.

REMEMBER: If you move your project folder, you’ll have to reset the project’s working directory.

Visual Studio

Fortunately, Visual Studio’s working directory is the project folder itself. So head to the project folder that is named the same as the project. There should be another folder with that same name. Place the input files in that second folder.

battleship.cpp

This file has already been implemented for you. You will not submit battleship.cpp to the autograder and should not modify this file.

The driver for the game of battleship has been implemented as the battleship() function in battleship.cpp.

A menu choice 3 indicates that the human player would like to emulate the CPU. This may help you during debugging. This logic is implemented for you already in the opponent_make_move function in Game.cpp. For the base project, if the menu choice provided is 2 (indicating that the user selected Play against medium AI), print the following message and prompt the user again with Menu Options.

Under Construction

Only the S’more version needs to handle a menu option of 2 and implement medium AI.

CPU emulation will NOT be tested in the autograder. It is for you to use during debugging. As such, there is no validation on input for CPU emulation.

Sample Run

Sample run 1

In the following sample run, both the player’s board are generated randomly. Note that the game does not end in this sample run, and the CPU’s move are determined randomly. Because of the random nature of this run, you aren’t expected to match the output exactly.

----------------------------------------
               EECS 183
              Battleship
----------------------------------------

Enter your name: Alice

Read your grid from file grid1.txt? (y or n): n

Read CPU grid from file grid2.txt? (y or n): n

Generating random grid for Alice
Generating random grid for CPU


         Menu Options
------------------------------
1) Play against easy AI
2) Play against medium AI (S'more)
3) Play while emulating CPU (CPU moves entered by player)
4) Quit

Choice --> 1

Starting game with EASY AI

Alice enter your move: 1A

Alice (1,A) hit
CPU (2,D) hit
You received an attack at (2,D)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   -   -   -

2   -   -   -   O   -   -   -   -

3   -   *   -   *   -   -   *   -

4   -   *   -   -   -   -   *   -

5   -   *   -   -   *   -   *   -

6   -   *   *   -   *   -   *   -

7   -   -   *   -   *   -   *   -

8   -   -   *   -   -   -   -   -

CPU's grid

    A   B   C   D   E   F   G   H

1   O   -   -   -   -   -   -   -

2   -   -   -   -   -   -   -   -

3   -   -   -   -   -   -   -   -

4   -   -   -   -   -   -   -   -

5   -   -   -   -   -   -   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Alice enter your move: 2D

Alice (2,D) miss
CPU (5,D) miss
You received an attack at (5,D)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   -   -   -

2   -   -   -   O   -   -   -   -

3   -   *   -   *   -   -   *   -

4   -   *   -   -   -   -   *   -

5   -   *   -   X   *   -   *   -

6   -   *   *   -   *   -   *   -

7   -   -   *   -   *   -   *   -

8   -   -   *   -   -   -   -   -

CPU's grid

    A   B   C   D   E   F   G   H

1   O   -   -   -   -   -   -   -

2   -   -   -   X   -   -   -   -

3   -   -   -   -   -   -   -   -

4   -   -   -   -   -   -   -   -

5   -   -   -   -   -   -   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Alice enter your move: 5F

Alice (5,F) miss
CPU (1,D) miss
You received an attack at (1,D)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   X   -   -   -   -

2   -   -   -   O   -   -   -   -

3   -   *   -   *   -   -   *   -

4   -   *   -   -   -   -   *   -

5   -   *   -   X   *   -   *   -

6   -   *   *   -   *   -   *   -

7   -   -   *   -   *   -   *   -

8   -   -   *   -   -   -   -   -

CPU's grid

    A   B   C   D   E   F   G   H

1   O   -   -   -   -   -   -   -

2   -   -   -   X   -   -   -   -

3   -   -   -   -   -   -   -   -

4   -   -   -   -   -   -   -   -

5   -   -   -   -   -   X   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Sample run 2

In the following sample run, both the player’s board are generated from files and we emulate the CPU, so all of the output can (and should) be the same when you run it. Note that the game does not end in this sample run.

----------------------------------------
               EECS 183
              Battleship
----------------------------------------

Enter your name: Bob

Read your grid from file grid1.txt? (y or n): y

Read CPU grid from file grid2.txt? (y or n): y



         Menu Options
------------------------------
1) Play against easy AI
2) Play against medium AI (S'more)
3) Play while emulating CPU (CPU moves entered by player)
4) Quit

Choice --> 3

Starting game with CPU EMULATION

Bob enter your move: 12B

Bob you entered an invalid input
Bob enter your move: 3P

Bob you entered an invalid position
Bob enter your move: 1C

Bob (1,C) hit
Enter CPU emulation move: 1D

CPU (1,D) miss
You received an attack at (1,D)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   X   -   *   *   *

2   -   -   -   -   -   -   -   -

3   *   -   -   -   *   *   *   *

4   *   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   *

7   *   -   -   -   -   -   -   *

8   -   *   *   -   -   -   -   *

CPU's grid

    A   B   C   D   E   F   G   H

1   -   -   O   -   -   -   -   -

2   -   -   -   -   -   -   -   -

3   -   -   -   -   -   -   -   -

4   -   -   -   -   -   -   -   -

5   -   -   -   -   -   -   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Sample run 3

In the following sample run, both the player’s board are generated from files and we emulate the CPU, so all of the output can (and should) be the same when you run it. Note that the game does not end in this sample run.

----------------------------------------
               EECS 183
              Battleship
----------------------------------------

Enter your name: Alice

Read your grid from file grid1.txt? (y or n): y

Read CPU grid from file grid2.txt? (y or n): y



         Menu Options
------------------------------
1) Play against easy AI
2) Play against medium AI (S'more)
3) Play while emulating CPU (CPU moves entered by player)
4) Quit

Choice --> 3

Starting game with CPU EMULATION

Alice enter your move: 3F

Alice (3,F) hit
Enter CPU emulation move: 8B

CPU (8,B) hit
You received an attack at (8,B)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   *   *   *

2   -   -   -   -   -   -   -   -

3   *   -   -   -   *   *   *   *

4   *   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   *

7   *   -   -   -   -   -   -   *

8   -   O   *   -   -   -   -   *

CPU's grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   -   -   -

2   -   -   -   -   -   -   -   -

3   -   -   -   -   -   O   -   -

4   -   -   -   -   -   -   -   -

5   -   -   -   -   -   -   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Alice enter your move: 3G

Alice (3,G) hit
Congratulations Alice! You sunk a Destroyer
Enter CPU emulation move: 8C

CPU (8,C) hit
Congratulations CPU! You sunk a Destroyer
You received an attack at (8,C)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   *   *   *

2   -   -   -   -   -   -   -   -

3   *   -   -   -   *   *   *   *

4   *   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   *

7   *   -   -   -   -   -   -   *

8   -   O   O   -   -   -   -   *

CPU's grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   -   -   -

2   -   -   -   -   -   -   -   -

3   -   -   -   -   -   O   O   -

4   -   -   -   -   -   -   -   -

5   -   -   -   -   -   -   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Sample run 4

In the following sample run, both the player’s board are generated from a file.

----------------------------------------
               EECS 183
              Battleship
----------------------------------------

Enter your name: Bob

Read your grid from file grid1.txt? (y or n): y

Read CPU grid from file grid2.txt? (y or n): y



         Menu Options
------------------------------
1) Play against easy AI
2) Play against medium AI (S'more)
3) Play while emulating CPU (CPU moves entered by player)
4) Quit

Choice --> 4


----------------------------------------
           Thanks for playing
              Battleship
----------------------------------------

Sample run 5

In the following sample run, both the player’s board are generated from files and we emulate the CPU, so all of the output can (and should) be the same when you run it. Alice wins after 17 rounds.

----------------------------------------
               EECS 183
              Battleship
----------------------------------------

Enter your name: Alice

Read your grid from file grid1.txt? (y or n): y

Read CPU grid from file grid2.txt? (y or n): y



         Menu Options
------------------------------
1) Play against easy AI
2) Play against medium AI (S'more)
3) Play while emulating CPU (CPU moves entered by player)
4) Quit

Choice --> 3

Starting game with CPU EMULATION

Alice enter your move: 3F

Alice (3,F) hit
Enter CPU emulation move: 8B

CPU (8,B) hit
You received an attack at (8,B)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   *   *   *

2   -   -   -   -   -   -   -   -

3   *   -   -   -   *   *   *   *

4   *   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   *

7   *   -   -   -   -   -   -   *

8   -   O   *   -   -   -   -   *

CPU's grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   -   -   -

2   -   -   -   -   -   -   -   -

3   -   -   -   -   -   O   -   -

4   -   -   -   -   -   -   -   -

5   -   -   -   -   -   -   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Alice enter your move: 3G

Alice (3,G) hit
Congratulations Alice! You sunk a Destroyer
Enter CPU emulation move: 8C

CPU (8,C) hit
Congratulations CPU! You sunk a Destroyer
You received an attack at (8,C)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   *   *   *

2   -   -   -   -   -   -   -   -

3   *   -   -   -   *   *   *   *

4   *   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   *

7   *   -   -   -   -   -   -   *

8   -   O   O   -   -   -   -   *

CPU's grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   -   -   -

2   -   -   -   -   -   -   -   -

3   -   -   -   -   -   O   O   -

4   -   -   -   -   -   -   -   -

5   -   -   -   -   -   -   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Alice enter your move: 1A

Alice (1,A) hit
Enter CPU emulation move: 6H

CPU (6,H) hit
You received an attack at (6,H)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   *   *   *

2   -   -   -   -   -   -   -   -

3   *   -   -   -   *   *   *   *

4   *   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   O

7   *   -   -   -   -   -   -   *

8   -   O   O   -   -   -   -   *

CPU's grid

    A   B   C   D   E   F   G   H

1   O   -   -   -   -   -   -   -

2   -   -   -   -   -   -   -   -

3   -   -   -   -   -   O   O   -

4   -   -   -   -   -   -   -   -

5   -   -   -   -   -   -   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Alice enter your move: 1B

Alice (1,B) hit
Enter CPU emulation move: 7H

CPU (7,H) hit
You received an attack at (7,H)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   *   *   *

2   -   -   -   -   -   -   -   -

3   *   -   -   -   *   *   *   *

4   *   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   O

7   *   -   -   -   -   -   -   O

8   -   O   O   -   -   -   -   *

CPU's grid

    A   B   C   D   E   F   G   H

1   O   O   -   -   -   -   -   -

2   -   -   -   -   -   -   -   -

3   -   -   -   -   -   O   O   -

4   -   -   -   -   -   -   -   -

5   -   -   -   -   -   -   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Alice enter your move: 1C

Alice (1,C) hit
Congratulations Alice! You sunk a Submarine
Enter CPU emulation move: 8H

CPU (8,H) hit
Congratulations CPU! You sunk a Submarine
You received an attack at (8,H)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   *   *   *

2   -   -   -   -   -   -   -   -

3   *   -   -   -   *   *   *   *

4   *   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   O

7   *   -   -   -   -   -   -   O

8   -   O   O   -   -   -   -   O

CPU's grid

    A   B   C   D   E   F   G   H

1   O   O   O   -   -   -   -   -

2   -   -   -   -   -   -   -   -

3   -   -   -   -   -   O   O   -

4   -   -   -   -   -   -   -   -

5   -   -   -   -   -   -   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Alice enter your move: 1E

Alice (1,E) hit
Enter CPU emulation move: 1F

CPU (1,F) hit
You received an attack at (1,F)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   O   *   *

2   -   -   -   -   -   -   -   -

3   *   -   -   -   *   *   *   *

4   *   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   O

7   *   -   -   -   -   -   -   O

8   -   O   O   -   -   -   -   O

CPU's grid

    A   B   C   D   E   F   G   H

1   O   O   O   -   O   -   -   -

2   -   -   -   -   -   -   -   -

3   -   -   -   -   -   O   O   -

4   -   -   -   -   -   -   -   -

5   -   -   -   -   -   -   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Alice enter your move: 1F

Alice (1,F) hit
Enter CPU emulation move: 1G

CPU (1,G) hit
You received an attack at (1,G)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   O   O   *

2   -   -   -   -   -   -   -   -

3   *   -   -   -   *   *   *   *

4   *   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   O

7   *   -   -   -   -   -   -   O

8   -   O   O   -   -   -   -   O

CPU's grid

    A   B   C   D   E   F   G   H

1   O   O   O   -   O   O   -   -

2   -   -   -   -   -   -   -   -

3   -   -   -   -   -   O   O   -

4   -   -   -   -   -   -   -   -

5   -   -   -   -   -   -   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Alice enter your move: 1G

Alice (1,G) hit
Congratulations Alice! You sunk a Submarine
Enter CPU emulation move: 1H

CPU (1,H) hit
Congratulations CPU! You sunk a Submarine
You received an attack at (1,H)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   O   O   O

2   -   -   -   -   -   -   -   -

3   *   -   -   -   *   *   *   *

4   *   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   O

7   *   -   -   -   -   -   -   O

8   -   O   O   -   -   -   -   O

CPU's grid

    A   B   C   D   E   F   G   H

1   O   O   O   -   O   O   O   -

2   -   -   -   -   -   -   -   -

3   -   -   -   -   -   O   O   -

4   -   -   -   -   -   -   -   -

5   -   -   -   -   -   -   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Alice enter your move: 3A

Alice (3,A) hit
Enter CPU emulation move: 3E

CPU (3,E) hit
You received an attack at (3,E)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   O   O   O

2   -   -   -   -   -   -   -   -

3   *   -   -   -   O   *   *   *

4   *   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   O

7   *   -   -   -   -   -   -   O

8   -   O   O   -   -   -   -   O

CPU's grid

    A   B   C   D   E   F   G   H

1   O   O   O   -   O   O   O   -

2   -   -   -   -   -   -   -   -

3   O   -   -   -   -   O   O   -

4   -   -   -   -   -   -   -   -

5   -   -   -   -   -   -   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Alice enter your move: 4A

Alice (4,A) hit
Enter CPU emulation move: 3F

CPU (3,F) hit
You received an attack at (3,F)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   O   O   O

2   -   -   -   -   -   -   -   -

3   *   -   -   -   O   O   *   *

4   *   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   O

7   *   -   -   -   -   -   -   O

8   -   O   O   -   -   -   -   O

CPU's grid

    A   B   C   D   E   F   G   H

1   O   O   O   -   O   O   O   -

2   -   -   -   -   -   -   -   -

3   O   -   -   -   -   O   O   -

4   O   -   -   -   -   -   -   -

5   -   -   -   -   -   -   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Alice enter your move: 5A

Alice (5,A) hit
Enter CPU emulation move: 3G

CPU (3,G) hit
You received an attack at (3,G)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   O   O   O

2   -   -   -   -   -   -   -   -

3   *   -   -   -   O   O   O   *

4   *   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   O

7   *   -   -   -   -   -   -   O

8   -   O   O   -   -   -   -   O

CPU's grid

    A   B   C   D   E   F   G   H

1   O   O   O   -   O   O   O   -

2   -   -   -   -   -   -   -   -

3   O   -   -   -   -   O   O   -

4   O   -   -   -   -   -   -   -

5   O   -   -   -   -   -   -   -

6   -   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Alice enter your move: 6A

Alice (6,A) hit
Congratulations Alice! You sunk a Battleship
Enter CPU emulation move: 3H

CPU (3,H) hit
Congratulations CPU! You sunk a Battleship
You received an attack at (3,H)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   O   O   O

2   -   -   -   -   -   -   -   -

3   *   -   -   -   O   O   O   O

4   *   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   O

7   *   -   -   -   -   -   -   O

8   -   O   O   -   -   -   -   O

CPU's grid

    A   B   C   D   E   F   G   H

1   O   O   O   -   O   O   O   -

2   -   -   -   -   -   -   -   -

3   O   -   -   -   -   O   O   -

4   O   -   -   -   -   -   -   -

5   O   -   -   -   -   -   -   -

6   O   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   -   -   -   -   -

Alice enter your move: 8D

Alice (8,D) hit
Enter CPU emulation move: 3A

CPU (3,A) hit
You received an attack at (3,A)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   O   O   O

2   -   -   -   -   -   -   -   -

3   O   -   -   -   O   O   O   O

4   *   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   O

7   *   -   -   -   -   -   -   O

8   -   O   O   -   -   -   -   O

CPU's grid

    A   B   C   D   E   F   G   H

1   O   O   O   -   O   O   O   -

2   -   -   -   -   -   -   -   -

3   O   -   -   -   -   O   O   -

4   O   -   -   -   -   -   -   -

5   O   -   -   -   -   -   -   -

6   O   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   O   -   -   -   -

Alice enter your move: 8E

Alice (8,E) hit
Enter CPU emulation move: 4A

CPU (4,A) hit
You received an attack at (4,A)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   O   O   O

2   -   -   -   -   -   -   -   -

3   O   -   -   -   O   O   O   O

4   O   -   -   -   -   -   -   -

5   *   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   O

7   *   -   -   -   -   -   -   O

8   -   O   O   -   -   -   -   O

CPU's grid

    A   B   C   D   E   F   G   H

1   O   O   O   -   O   O   O   -

2   -   -   -   -   -   -   -   -

3   O   -   -   -   -   O   O   -

4   O   -   -   -   -   -   -   -

5   O   -   -   -   -   -   -   -

6   O   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   O   O   -   -   -

Alice enter your move: 8F

Alice (8,F) hit
Enter CPU emulation move: 5A

CPU (5,A) hit
You received an attack at (5,A)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   O   O   O

2   -   -   -   -   -   -   -   -

3   O   -   -   -   O   O   O   O

4   O   -   -   -   -   -   -   -

5   O   -   -   -   -   -   -   -

6   *   -   -   -   -   -   -   O

7   *   -   -   -   -   -   -   O

8   -   O   O   -   -   -   -   O

CPU's grid

    A   B   C   D   E   F   G   H

1   O   O   O   -   O   O   O   -

2   -   -   -   -   -   -   -   -

3   O   -   -   -   -   O   O   -

4   O   -   -   -   -   -   -   -

5   O   -   -   -   -   -   -   -

6   O   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   O   O   O   -   -

Alice enter your move: 8G

Alice (8,G) hit
Enter CPU emulation move: 6A

CPU (6,A) hit
You received an attack at (6,A)


Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   O   O   O

2   -   -   -   -   -   -   -   -

3   O   -   -   -   O   O   O   O

4   O   -   -   -   -   -   -   -

5   O   -   -   -   -   -   -   -

6   O   -   -   -   -   -   -   O

7   *   -   -   -   -   -   -   O

8   -   O   O   -   -   -   -   O

CPU's grid

    A   B   C   D   E   F   G   H

1   O   O   O   -   O   O   O   -

2   -   -   -   -   -   -   -   -

3   O   -   -   -   -   O   O   -

4   O   -   -   -   -   -   -   -

5   O   -   -   -   -   -   -   -

6   O   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   O   O   O   O   -

Alice enter your move: 8H

Alice (8,H) hit
Congratulations Alice! You sunk a Carrier

Your grid

    A   B   C   D   E   F   G   H

1   -   -   -   -   -   O   O   O

2   -   -   -   -   -   -   -   -

3   O   -   -   -   O   O   O   O

4   O   -   -   -   -   -   -   -

5   O   -   -   -   -   -   -   -

6   O   -   -   -   -   -   -   O

7   *   -   -   -   -   -   -   O

8   -   O   O   -   -   -   -   O

CPU's grid

    A   B   C   D   E   F   G   H

1   O   O   O   -   O   O   O   -

2   -   -   -   -   -   -   -   -

3   O   -   -   -   -   O   O   -

4   O   -   -   -   -   -   -   -

5   O   -   -   -   -   -   -   -

6   O   -   -   -   -   -   -   -

7   -   -   -   -   -   -   -   -

8   -   -   -   O   O   O   O   O


Game over, winner is Alice in 17 rounds

----------------------------------------
           Thanks for playing
              Battleship
----------------------------------------

Function Table

Below are functions that make use of other functions. Other functions marked with a * represent another approach to the implementation. Library functions are not included here, although you may find some helpful when implementing the projects.

     
File Function Other functions it should call
Position.cpp Position() (1st non-default) Position::check_range()
Position.cpp Position() (2nd non-default) Position::check_range()
Position.cpp set_row() Position::check_range()
Position.cpp set_col() Position::check_range()
Position.cpp read() Position::check_range()
Ship.cpp Ship() (1st non-default) Position::get_row(),Position::get_col(),Ship::is_horizontal()
Ship.cpp is_horizontal() Position::get_row()
Ship.cpp has_position() Position::get_row(), Position::get_col(), Ship::is_horizontal()
Player.cpp Player() (default) Player::init_grid()
Player.cpp Player() (1st non-default) Player::init_grid()
Player.cpp add_ship() Ship::get_start(), Ship::get_end(), Position::get_row(), Position::get_col(), Ship::is_horizontal(), Ship::has_position()*
Player.cpp attack() Ship::has_position(), Ship::hit(), Ship::has_sunk(), Player::announce_ship_sunk(), Position::get_row(), Position::get_col()
Player.cpp load_grid_file() Position::Position() (default), Ship::Ship() (1st non-default), Player::add_ship()
Game.cpp Game() (default) Player::Player() (default)
Game.cpp Game() (non-default) Game::generate_random_grid(), Player::load_grid_file(), Player::get_name()
Game.cpp start() Position::Position() (2nd non-default), Game::get_move(), Game::check_valid_move(), Player::get_name(), Player::destroyed(), Player::attack(), Player::print_grid(), Player::print_guess_grid(), Game::opponent_make_move()

NOTE: There are two non-default constructors for Position. One that accepts row and col in int form and a second constructor that expects row and col as char.

Testing

Bugs To Expose

There are a total of 19 unique bugs to find in our implementations. Your tests do not need to expose all of the bugs to receive full points. The autograder will tell you the names of the bugs that you have exposed, from the following set:

The autograder test suite will not be exhaustive of all the possible bugs in your program. Therefore, you should prepare more robust suites that include a larger number of test cases.

How to submit

Battleship

Remember, a computer does not interpret. If you misspell a word, you will fail all autograder test cases. If you omit punctuation, you will fail all autograder test cases. We strongly suggest you test your code. An easy way is to use diffchecker.com, quickdiff.com, or diffnow.com or your favorite diff program.

To submit function implementations, head to https://autograder.io/web/project/995. You must submit all of Position.cpp, Ship.cpp, Player.cpp, and Game.cpp, with correct names. We will use your highest scoring submit to determine your final score.

Make sure that you’ve included your (and your partner’s) name, your (and your partner’s) uniqname and a small description of the program in the header comments.

You have 4 submits per day with feedback, and one additional “bonus” submission. This “bonus” submission allows you to submit 5 times in a single day, but only once during the project. Each submit is shared and applied to both students if you’re in a partnership, so you have 4 collective submits (not 8).

Test Suite

You will submit test.cpp to the autograder, together with your implementation of the project. The autograder will list the bugs you have exposed, but nothing else. If your test suite does not expose enough bugs, you’ll need to write more rigorous test cases. You may also submit up to two extra text files for use in your test cases. These MUST be called grid1.txt and grid2.txt, and may prove useful in testing some of your functions.

Although both grid1.txt and grid2.txt that you submit to the autograder must contain valid positions for ships that form a valid grid, you may find it helpful to test locally with a smaller grid to expedite the game (to test locally, it may be useful to create files such as grid3.txt that is a smaller grid).

S’more

Have time for a quick challenge? As we mentioned earlier, the S’mores version of this project will have implement a medium-difficulty AI for the Battleship game.

You will be modifying the large if-statement inside of opponent_make_move() in Game.cpp. Specifically, the else if clause that checks whether difficulty is set to MEDIUM. The easy AI simply makes a random move, which is not very smart — no wonder the CPU is having hard time beating you! You can use existing heuristics you find online or come up with your own to implement a smarter AI that takes into account the current state of the CPU’s grid. For example, your AI can make a move that corresponds to the right, bottom, left or top of a previously hit position.

Here are a few tips:

IMPORTANT: You will submit your S’mores project to a separate autograder: Autograder not available. Don’t forget to complete and submit the regular version of the project first.