lab12 : Battleship

num ready? description assigned due
lab12 true Battleship Tue 01/15 04:00PM Fri 03/01 05:00PM

Note: this is not an auto-graded assignment. We may still put it on Gradescope so that you can submit it there, but there won't be any automated feedback.

Battleship!


Assignment Summary: Battleship is a children’s game where players guess (x,y) coordinate positions of the opposing player’s ship pieces in a 10x10 grid. For the official Hasbro rules and additional game context, read http://www.hasbro.com/common/instruct/Battleship.PDF . You will implement a version of this game in Python.

* It is highly recommended that you read the entire assignment first to get an idea of what the end-goals are, which will help in designing your code.

This assignment is divided into five required stages and optional sixth stage. Each succeeding stage is built upon what you have already written for the previous stage. We expect you to design, write, and test this program according to these stages—first get the first-stage program working, then modify it to satisfy the second stage, and so on. As always, be sure to keep a copy of each completed stage. That way, if you decide you've gotten off on the wrong track for a stage, you can start again easily from the end of the previous stage, without the painstaking task of removing each addition. You should make sure that each stage is entirely correct and working perfectly before you go on to the next. As you complete each stage, you should demonstrate briefly to your TA or tutor that it works correctly before you go on to the following stage.

Development by stages is good software engineering practice. It is far better to have a program that is correct but incomplete (i.e., it doesn't implement all the features but what it does implement is correct) than one that contains bugs. Grading for this assignment will reflect this, too; it will hurt your score much more to turn in buggy code than not to reach some of the later stages. Let's say that again: Your score will be higher if you do the first few stages correctly than if you do all of them with bugs in them.

What to turn in: On Checkmate, a single Python file (battleship.py) containing your last-stage code. Do not turn in code from the optional Stage VI section.

Grading: Your grade depends on organized development (did you design and debug each stage in sequence), completeness (does your program do everything the specification requires), correctness (does it produce the correct results), quality and clarity of your output, good modularity, good data organization (using data structures appropriately), and good programming style (are your identifier names descriptive, is your organization clear). You will receive appropriate partial credit for each stage you complete correctly. You will receive no credit for work on a later stage if the previous stages are incomplete or incorrect. The whole point of incremental development (i.e., stages) is to keep a programmer from biting off more than he or she can chew.


Rules

The rules to implement will be largely based on the rules described here: http://www.hasbro.com/common/instruct/Battleship.PDF

To summarize, the game consists of two players, Player 1 and Player 2. Each player will have 5 ship pieces of varying lengths (i.e. number of coordinates that it will occupy). Their names, identifying keys, and length are:



Carrier (CAR)    – 5 coordinates

Battleship (BAT) – 4 coordinates
Cruiser (CRU)    – 3 coordinates
Submarine (SUB)  – 3 coordinates
Destroyer (DES)  – 2 coordinates


Each player will place their ships on a 10x10 grid where the columns are labeled 0 – 9 and the rows are labeled A – J (note, the column values are different than the ones listed in Hasbro’s official rules). The players will have their own space (i.e. player 1 and player 2 ships do not occupy the same grid - each player will have their own grid space). This grid organization is shown below:


   0  1  2  3  4  5  6  7  8  9
A  _  _  _  _  _  _  _  _  _  _
B  _  _  _  _  _  _  _  _  _  _
C  _  _  _  _  _  _  _  _  _  _
D  _  _  _  _  _  _  _  _  _  _
E  _  _  _  _  _  _  _  _  _  _
F  _  _  _  _  _  _  _  _  _  _
G  _  _  _  _  _  _  _  _  _  _
H  _  _  _  _  _  _  _  _  _  _
I  _  _  _  _  _  _  _  _  _  _
J  _  _  _  _  _  _  _  _  _  _


When a player places their ship pieces on the board, the entire piece must be within the board and each piece cannot overlap (you cannot have two ships occupying the same position). The player must place each ship vertically or horizontally on the grid (not diagonally).

Each player will be unaware of the opposing player’s ship placement, and the objective of the game is to try and guess the ship positions the opposing player’s ships. Each player takes turns guessing the coordinates (Player 1 starts the game), and the first player to guess all of the opposing player’s ship coordinates wins the game.

When a player guesses the coordinate that an opposing player's ship occupies, then this counts as a “hit.” When a player guesses a coordinate that an opposing player's ship does not occupy, then this counts as a "miss." When a player guesses all coordinates of an opposing player's ship, then the ship is “sunk.” The game is over when a player sinks all of the opposing player’s ships.

The players will need to maintain two views: an ocean view representing the player’s current ship placement and a target view representing the current player’s knowledge of the opposing player’s ship placement.

 In addition to the views, each player must keep track of certain statistics and game state. These are:



Statistics (for each player):

    - Number of moves made.

    - Number of “hits” (correct guesses of the opposing player’s ship positions).

    - Number of “misses” (incorrect guesses of the opposing player’s ship positions).



Game State (for each player):

    - Both target and ocean view for each player.
    - Each player's ship information (for each ship) including:
        - A list of coordinate positions it occupies on its player's ocean view.
        - The ships "health" (i.e. the number of coordinates that have not been hit).

Stage I – Setup

For the first stage, it’s important that we lay out all the components that will be used throughout the game. The first thing that we will need to do is create the game board and lay out the ship pieces for each player before the game starts.

When designing an application, it’s important to think of what data structures should be used to represent the information of the program. Making decisions like this becomes easier with practice, but there are two things to keep in mind. First, start with the simplest data structure that does the job. (For example, you can consider creating a namedtuple representing a Ship that contains a list of coordinates that it occupies. Or perhaps you can consider using a set of coordinates instead of a list of coordinates). Second, accept that your first choice may not be your final choice; as the specifications become clearer or as circumstances change (or as you get to later stages in a problem like this one), you may decide that something else would work better. This kind of revision is a normal part of programming. It's no tragedy to rewrite or refactor some code in a better way, just as you should expect to revise written documents.

Remember, one of the challenges (and most interesting thing) about coding is there are many ways to solve a problem. Most of the decisions should be made by you and your partner. However, some design guidance you can consider:
  • Representing a 10x10 Grid can easily be done using 2D lists. Also, recall that lists (and 2D lists) are mutable, so assigning and replacing values in a 2D list is time / memory efficient.
  • Each player will need to keep track of their views (both target and ocean) and Ship information.
    • For the views, there are many ways to organize this. Following the examples in lecture, you can create a separate 2D list for each view for each player (four 2D lists total).
    • For the ships, the most important pieces of information are the ships name (displayed when the ship gets hit or sunk), the ship's current health (there are other ways to derive this information, but it would be nice to keep track of and instantly access this), the list of coordinates that the ship occupies in its respective player's ocean view (which can be a set of strings representing specific coordinates).
    • Each player will need to create ships, which will be updated throughout the game. Since each player only has one ship of each type (and each have a unique identifying key), you can organize these ships in a dictionary for each player: The key in the dictionary will be the three-character ship string (stated in the rules), and the value in the dictionary will be the corresponding Ship namedtuple.
    • Throughout gameplay, you will need to reference both views (to see if moves are valid and what ship information / statistics needs to be updated), and the Ship's state (checking if a ship occupies a coordinate and updating the Ship's state accordingly).
  • Each player will also need to keep track of game statistics.
    • The requirements are to keep track of three pieces of information for each player: number of moves made, number of hits, and number of misses. Similar to a ship's state, a dictionary can be used to map these three statistics (perhaps using keys like "moves", 'hits", "misses") and their corresponding int values.
    • This information will be used to display a summary of statistics when the game ends.
For now, users can interact with our game via the Python shell (though a user would probably prefer to interact with a graphical interface). Each player will need to define their ships’ positions, and though one approach to do so can be interactive, we will require each player to store their ship configurations in a text file (“p1.txt” for Player 1’s ship placement and “p2.txt” for Player 2’s ship placement). An example input file for p1.txt can look like this:


CAR,A1,A2,A3,A4,A5
BAT,B1,B2,B3,B4
CRU,C1,C2,C3
SUB,D1,D2,D3
DES,E1,E2


An example input file for p2.txt can look like this:

CRU,A3,B3,C3
BAT,A2,B2,C2,D2
DES,A5,B5
CAR,A1,B1,C1,D1,E1
SUB,A4,B4,C4


Each line in the file represents a specific ship with a three-character key (for example, Carrier is represented as “CAR”) as shown in the previous Rules section.  A line will also contain a list of coordinates it occupies. Each piece of information is separated by ‘,’ and the number of coordinates is dependent on the type of ship. There are certain things your program should check for when loading the files:
  • The user can input their ships in any order and your program will need to check and make sure the file is correct including:
    • Each distinct ship has the correct length.
    • Each ship is laid out horizontally or vertically.
    • Ship coordinates do not overlap with each other.
    • The coordinates themselves are valid positions (there shouldn't be invalid coordinates like “Z3”).
    • The ship keys are valid (it will either be ‘CAR’, ‘BAT’, ‘CRU’, ‘SUB’, ‘DES’.)
    • There are no duplicate ships in the file (a particular ship’s configuration cannot appear more than once).
If any of these conditions are not met, the program will print out a short statement stating there was a problem with reading the file and then the program will terminate.

As you are parsing through the player ship configuration files, it’s important to organize your information into the appropriate data structures. For example, in addition to modifying the player’s ocean view, you will need probably need to store the coordinates and initial ship state such as current health (or number of coordinates that have not been hit), the name of the ship, the ships coordinates, etc. Again, this is largely dependent on the decisions of what data type you want to use in order to represent / organize data to solve problems effectively.

You will need to print out the board showing the current state of the game. A few notes about displaying the board:
  • The board should be populated with underscores “_” for each position by default (an empty board example is shown in the previous Rules section).
  • For the ocean view, if a ship occupies a certain coordinate, then an asterisk “*” is displayed.
  • Throughout the game, the ocean view will change since when a player guesses a coordinate that a ship occupies, this asterisk should change to “X”. This is for the player whose ship was just hit. The target view for the player making the guess will need to be changed (as described below).
    • At the end of the game, a losing player’s ocean view will have all “*” replaced by “X”.
    • The ocean view does not change for misses (i.e. only coordinates occupied by a ship should be replaced with an "X" if a hit occurs. The "_" characters remain unchanged if a miss happens.
  • Initially, for the target view, since a player has not fired yet, the board should be populated with only underscore characters.
    • Throughout the game, the player's target view will change since when a player guesses a coordinate that the opposing player ship occupies, then the “_” will be replaced with a “H”, which represents a hit for that position.
    • When a player guesses a coordinate that the opposing player ship does not occupy, then the “_” will be replaced with an “M”, which represents a miss for that position.
At this stage, we shouldn’t worry about changing the target view and we should only worry about populating the player’s ocean view based on the input file. However, you should create functions that can print out any player’s ocean or target view in a nice tabular format as shown above.

Using the sample p1.txt file above, Player 1’s initial ocean view (when printed out nicely) will look like:



   0  1  2  3  4  5  6  7  8  9
A  _  *  *  *  *  *  _  _  _  _
B  _  *  *  *  *  _  _  _  _  _
C  _  *  *  *  _  _  _  _  _  _
D  _  *  *  *  _  _  _  _  _  _
E  _  *  *  _  _  _  _  _  _  _
F  _  _  _  _  _  _  _  _  _  _
G  _  _  _  _  _  _  _  _  _  _
H  _  _  _  _  _  _  _  _  _  _
I  _  _  _  _  _  _  _  _  _  _
J  _  _  _  _  _  _  _  _  _  _


Stage II – User Input and the Game Loop

For this stage, the main goal is to have the program interact with the user. Since we want to make this game somewhat user-friendly, we will accept both lower-case and upper-case commands from the user. Before the game starts, prompt the user if they would like to start a new game or quit the program. A sample title menu will look like this:

--------- BATTLESHIP! ---------

N:    New Game
Q:    Quit
Enter command:



When the user enters “Q” (or “q”), then the application will terminate. If the user enters “N”, then the program will read both “p1.txt” and “p2.txt” (both of these files will be placed in your program’s working directory) and populate each ocean view as discussed in Stage I.

If all is well, then the game can officially start where Player 1 makes the first guess. At the start of each turn, the output should indicate which player’s turn it is, the current player’s target view, the current health for each players’ ships (each player will need to display their health in a tabular two-column format), and a player turn menu prompting the player to enter their next move. The options for the user that the user can choose from are printing out their current ocean view or firing at a specific opposing player’s coordinate.

A few notes about printing out a player’s ocean view:
  • During gameplay, the opposing player will need to be honorable and look away if the opposing player is looking at the screen while their ocean view is displayed - this knowledge will clearly be unfair.
  • Printing out the ocean view isn’t really necessary for gameplay since a player won’t need to refer to their ocean view for anything besides book keeping (and we're implementing our program to take care of this for us).
  • We present the option to the user to print their ocean view and it will also be useful for testing your code.
If the player chooses to fire at the opposing player’s position, then the program will prompt the player to enter the coordinates. This will need to be in the form of [A-J][0-9]. Your program must check if the coordinate is valid, and if it is, that the player has not already fired at that specific position. If the player has already guessed a specific coordinate (which should already appear as either an “M” or “H” on the player’s target view), then the program should allow the user to continue entering a coordinate until one is valid.



One thing you will need to solve is 2D list indexing will not recognize the characters A through J as a valid position. You can write a helper function that takes in a character A – J and returns the appropriate index to access the 2D list (for example, A = 0, B = 1, C = 2, etc.). You probably have not seen the function ord (short for “ordinal”) yet that takes in a single character and returns the numeric representation of that character (recall, in class we talked about how each character has a value associated with it and that’s how we can sort strings). Also recall that characters have incremental values associated with it, so B = A + 1, C = A + 2, D = A + 3, etc. Consider having a function that takes in a character and subtracts the ordinal value from ‘A’ to get the 0-based index for the 2D list. For example print(ord('B') – ord('A')) should print 1.

With all that said, here is a sample output of what the user interaction will look like at this stage (note, the bold text indicates user input):

--------- BATTLESHIP! ---------

N:    New Game
Q:    Quit
Enter command: N

Player 1's Turn
   0  1  2  3  4  5  6  7  8  9
A  _  _  _  _  _  _  _  _  _  _
B  _  _  _  _  _  _  _  _  _  _
C  _  _  _  _  _  _  _  _  _  _
D  _  _  _  _  _  _  _  _  _  _
E  _  _  _  _  _  _  _  _  _  _
F  _  _  _  _  _  _  _  _  _  _
G  _  _  _  _  _  _  _  _  _  _
H  _  _  _  _  _  _  _  _  _  _
I  _  _  _  _  _  _  _  _  _  _
J  _  _  _  _  _  _  _  _  _  _

Player 1 Ships HP   Player 2 Ships HP
CAR - 5             CAR - 5
BAT - 4             BAT - 4
CRU - 3             CRU - 3
SUB - 3             SUB - 3
DES - 2             DES - 2

O: Print Ocean View
F: Fire at player
Enter command: I
Invalid command: Please re-enter command. O
   0  1  2  3  4  5  6  7  8  9
A  _  *  *  *  *  *  _  _  _  _
B  _  *  *  *  *  _  _  _  _  _
C  _  *  *  *  _  _  _  _  _  _
D  _  *  *  *  _  _  _  _  _  _
E  _  *  *  _  _  _  _  _  _  _
F  _  _  _  _  _  _  _  _  _  _
G  _  _  _  _  _  _  _  _  _  _
H  _  _  _  _  _  _  _  _  _  _
I  _  _  _  _  _  _  _  _  _  _
J  _  _  _  _  _  _  _  _  _  _

O: Print Ocean View
F: Fire at player
Enter command: F
Enter target's coordinate [A-J][0-9] to fire at: fjksal
Invalid coordinate. Please enter coordinate [A-J][0-9]: Z1
Invalid coordinate: Please enter coordinate [A-J][0-9]: A2
Battleship hit!

Player 2's Turn
   0  1  2  3  4  5  6  7  8  9
A  _  _  _  _  _  _  _  _  _  _
B  _  _  _  _  _  _  _  _  _  _
C  _  _  _  _  _  _  _  _  _  _
D  _  _  _  _  _  _  _  _  _  _
E  _  _  _  _  _  _  _  _  _  _
F  _  _  _  _  _  _  _  _  _  _
G  _  _  _  _  _  _  _  _  _  _
H  _  _  _  _  _  _  _  _  _  _
I  _  _  _  _  _  _  _  _  _  _
J  _  _  _  _  _  _  _  _  _  _

Player 1 Ships HP   Player 2 Ships HP
CAR - 5             CAR - 5
BAT - 4             BAT - 3
CRU - 3             CRU - 3
SUB - 3             SUB - 3
DES - 2             DES - 2

O: Print Ocean View
F: Fire at player
Enter command: O
   0  1  2  3  4  5  6  7  8  9
A  _  *  X  *  *  *  _  _  _  _
B  _  *  *  *  *  *  _  _  _  _
C  _  *  *  *  *  _  _  _  _  _
D  _  *  *  _  _  _  _  _  _  _
E  _  *  _  _  _  _  _  _  _  _
F  _  _  _  _  _  _  _  _  _  _
G  _  _  _  _  _  _  _  _  _  _
H  _  _  _  _  _  _  _  _  _  _
I  _  _  _  _  _  _  _  _  _  _
J  _  _  _  _  _  _  _  _  _  _

O: Print Ocean View
F: Fire at player
Enter command: F
Enter target's coordinate [A-J][0-9] to fire at: A1
Carrier hit!

Player 1's Turn
   0  1  2  3  4  5  6  7  8  9
A  _  _  H  _  _  _  _  _  _  _
B  _  _  _  _  _  _  _  _  _  _
C  _  _  _  _  _  _  _  _  _  _
D  _  _  _  _  _  _  _  _  _  _
E  _  _  _  _  _  _  _  _  _  _
F  _  _  _  _  _  _  _  _  _  _
G  _  _  _  _  _  _  _  _  _  _
H  _  _  _  _  _  _  _  _  _  _
I  _  _  _  _  _  _  _  _  _  _
J  _  _  _  _  _  _  _  _  _  _

Player 1 Ships HP   Player 2 Ships HP
CAR - 4             CAR - 5
BAT - 4             BAT - 3
CRU - 3             CRU - 3
SUB - 3             SUB - 3
DES - 2             DES - 2

O: Print Ocean View
F: Fire at player
Enter command: F
Enter target's coordinate [A-J][0-9] to fire at: A2
Please enter another coordinate [A-J][0-9]: A3
Cruiser hit!

Player 2's Turn
   0  1  2  3  4  5  6  7  8  9
A  _  H  _  _  _  _  _  _  _  _
B  _  _  _  _  _  _  _  _  _  _
C  _  _  _  _  _  _  _  _  _  _
D  _  _  _  _  _  _  _  _  _  _
E  _  _  _  _  _  _  _  _  _  _
F  _  _  _  _  _  _  _  _  _  _
G  _  _  _  _  _  _  _  _  _  _
H  _  _  _  _  _  _  _  _  _  _
I  _  _  _  _  _  _  _  _  _  _
J  _  _  _  _  _  _  _  _  _  _

Player 1 Ships HP   Player 2 Ships HP
CAR - 4             CAR - 5
BAT - 4             BAT - 3
CRU - 3             CRU - 2
SUB - 3             SUB - 3
DES - 2             DES - 2

O: Print Ocean View
F: Fire at player
Enter command: O
   0  1  2  3  4  5  6  7  8  9
A  _  *  X  X  *  *  _  _  _  _
B  _  *  *  *  *  *  _  _  _  _
C  _  *  *  *  *  _  _  _  _  _
D  _  *  *  _  _  _  _  _  _  _
E  _  *  _  _  _  _  _  _  _  _
F  _  _  _  _  _  _  _  _  _  _
G  _  _  _  _  _  _  _  _  _  _
H  _  _  _  _  _  _  _  _  _  _
I  _  _  _  _  _  _  _  _  _  _
J  _  _  _  _  _  _  _  _  _  _

O: Print Ocean View
F: Fire at player
Enter command:


Stage III – Saving State


At this point, your program should be able to load players’ ship configuration files, run the game loop (including prompting the user for input, interpreting that input, modifying the application data, can display the players’ Target and Ocean views, and displays the current health for each player’s ships for every turn).

It’s not unreasonable to have the players play an entire game of Battleship, but it would be nice to allow the players to save their game and resume it at a later point. In this stage, you will need to implement functionality to write game data to a file (known as “serializing” the data), read game data from a file into the program and resume gameplay.

Note, there are many ways one can serialize data. However, for this assignment, your file will need to write and read game state data to a file named “game.txt” with the following format:

----- # start of file (not actually part of file content) ----
A1

B2
A1,A2,A3,A4,A5,B1,B3,B4,C1,C2,C3,D1,D2,D3,E1,E2
CRU,3,C1,C2,C3
BAT,4,B1,B2,B3,B4
SUB,3,D1,D2,D3
DES,2,E1,E2
CAR,5,A1,A2,A3,A4,A5
1,1,0
B2

A1
A2,A3,A4,A5,B1,B2,B3,B4,B5,C1,C2,C3,C4,D1,D2,E1
CRU,3,A3,B3,C3
BAT,4,A2,B2,C2,D2
SUB,3,A4,B4,C4
DES,2,A5,B5
CAR,4,A1,B1,C1,D1,E1
1,1,0
P1

---- # end of file (not actually part of file content) ----

Each line is described as:
  • Line1: Coordinates that were “hits” in Player 1’s target view separated by ‘,’
  • Line2: Coordinates that were “misses” in Player 1’s target view separated by ‘,’
  • Line3: Coordinates that were “hits” in Player 1’s ocean view separated by ‘,’
  • Line4: Ship coordinates that were not hit yet in Player 1’s ocean view separated by ‘,’
  • Line5 – 9: Player 1’s Ship information. Each line represents a single ship. There are several important pieces of information that we need to save for each ship. The format that is used is:
    [three-character key for ship],[ship health], [coordinates of ship separated by ‘,’]. Note, the order of the ships do not matter (i.e. BAT can be listed before DES and DES can be listed before BAT).
  • Line10: Player 1 statistics in the following format: [moves],[hits],[misses]
  • Line11 – 20: The same information as described for Lines 1 – 10, but this information is specific to Player 2.
  • Line21: A string that’s either “P1” or “P2” representing if it’s Player 1’s or Player 2’s turn respectively.
Besides the functionality for writing, reading, and loading game state, we will need to provide the Player an option to load a game when the program starts (in the Title Menu) and an option to save a game during a player’s turn. For example, you will need to change and support a Title Menu with the following options:

--------- BATTLESHIP! ---------

L:    Load Game (game.txt)
N:    New Game
Q:    Quit


and a Turn Menu with the following options:

O: Print Ocean View
F: Fire at player
S: Save Game


Note that the game should continue resuming if the player chooses to save the game. All this does is write the game state to a file called “game.txt” and resumes the game.

Stage IV - End Game: Displaying Game Statistics

At this point, most of the heavy lifting is done and we have a fairly complete game. The last thing to worry about is displaying the game statistics. Throughout Stage II, you should be keeping track of each players’ statistics (moves made, hits made, misses made).

When a player wins the game, the program should state so and player statistics throughout the game should be displayed in a two-column fashion (similar to displaying each player’s ships’ health for each turn). After the statistics are displayed, the application should terminate. The statistics that need to be displayed for each player are:

  • Number of moves made throughout the game.
  • Number of misses the player made.
  • Number of hits the player made.
  • The hit percentage (with 3 decimal precision)
  • The miss percentage (with 3 decimal precision)
An example of Player 1 making the last move to win the game and displaying the statistics:

Player 1's Turn
   0  1  2  3  4  5  6  7  8  9
A  _  H  H  H  H  H  M  _  _  _
B  _  H  H  H  H  H  _  _  _  _
C  _  H  H  H  H  _  _  _  _  _
D  _  H  H  M  _  _  _  _  _  _
E  _  _  _  _  _  _  _  _  _  _
F  _  _  _  _  _  _  _  _  _  _
G  M  _  _  _  _  _  _  _  _  _
H  _  _  _  _  _  _  _  _  _  _
I  _  _  _  _  _  _  _  _  _  _
J  _  _  _  _  _  _  _  _  _  _

Player 1 Ships HP   Player 2 Ships HP
CAR - 0             CAR - 1
BAT - 0             BAT - 0
CRU - 0             CRU - 0
SUB - 0             SUB - 0
DES - 2             DES - 0

O: Print Ocean View
F: Fire at player
S: Save Game
Enter command: F
Enter target's coordinate [A-J][0-9] to fire at: E1
Carrier hit!
You have sunk the enemey's Carrier
Player 1 wins!
        Player 1 Stats      Player 2 Stats
Moves:  20                  19
Misses: 3                   4
Hits:   17                  15
Hit%:   85.000              78.947             
Miss%:  15.000              21.053 

Stage V – Cleaning Up Your Code

At this point, all of the functional requirements should be satisfied, but maybe the code you wrote is disorganized, inefficient, duplicate code exists in various places, information you included that isn’t necessary to have, etc. That doesn't mean you shouldn't test your code until this stage, each stage should be tested in tandem to implementation. However, at this point, the entire game functionality is done and there may be design decisions that made sense for a particular stage, but now that your code is working end-to-end, there is always room for cleanup. For example, reading ship information from the player ship configuration file and reading ship information from game.txt have similar functionality. Check and see if you're re-writing the same code for this and think if you can reduce duplicate code and generalize this functionality such that the same code can be used for both parts of the program. Part of what we grade you on is quality of your code. This stage should be dedicated to reviewing your current version and see if there are ways to make it more organized, elegant, and efficient.


Stage VI (optional) – Improvements and Extensions

For those of you who have finished early, feel free to use the remaining time to improve your program. This is completely optional and you will not receive extra credit for completing it. I encourage everyone to attempt some of this just for practice. It’s completely up to you, so feel free to be as creative as you like. Some things you can consider working on:

Improving the User Experience – There are several improvements that you can make in your application.
  • We required the player’s to provide a text file with the initial ship’s coordinates. You can attempt to make this process more interactive by prompting the players to manually enter the coordinates for each of their ships. Or maybe you want to write the functionality for ships to be placed randomly instead of the user providing ship configuration files.
  • The flow of commands can be more robust. For example, once the player enters the command to fire, there isn’t an option for the player to return back to the Turn Menu (and the player’s only choice is to enter a coordinate to fire at). Though this is minor, improving the flow of user interaction can be worked on.
Modifying the Game – We’ve implemented the traditional version of battleship, however there can be many different ways you can modify this game (for better or worse). Some ideas that may spark your imagination:
  • The ships are set on the game board and do not move throughout the game. What if the ships can move one space after every player’s turn (or every other turn)? There are some mechanics you will need to take into account. For example, if two ships are moving and are about to collide, then who gets priority? Also, will the ships only move in one direction, and if so, will they circle around to the other end of the board? The concepts of hits / misses on the board may not apply for these modified rules.
  • Perhaps having a player make one move every turn gets boring after some time. What if each ship has a certain speed attribute and a player can fire multiple times at the opposing player before they can fire back?
Adding Additional Statistics – We needed to do some bookkeeping for simple statistics throughout the game. However, there are many other things that could be important to keep track of (dedicated business teams are always trying to gather information to make the best possible decisions for the future of a product). For example, maybe keeping track of a hit / miss streak for each player is something that might be of interest.

... or anything else you think would be good to work on. Again, this part is totally optional and students can be really creative here. What you work on is up to you, so go nuts!

Tips and Advice

  • Take time to draw out and design your code! Don't start coding immediately until you know the overall organization and structure of the components you want to implement. This will significantly help you during implementation.
  • Get started early! There are a lot of parts to this lab and additions to make for each stage. You will need ample time to complete this assignment and will most likely require you to get started early (including finding a partner on Monday and utilizing all lab sections).
  • Save multiple versions of your project! Since each stage builds upon each other, you may make changes that can break your current functionality. In the worst-case scenario, you made modifications in your file, broke the code, and now nothing works. By saving several versions of your progress, you can always start from a later point rather than trying to start all over.
  • Create game.txt versions (or be sure to save versions for specific scenarios) that allow you to test various cases. For example, if you’re working on confirming the functionality for the end-of-game (printing stats, checking logic, etc.), it will be extremely annoying to replay an entire game just to get to that point. Imagine trying to debug an edge case at the end of the game and having to start a new game, hit all player ships just to reproduce the condition, realize the bug is still not fixed, and then replaying the game again… it will be wise to play with the game once, load a game.txt file as discussed in Stage III that has a near-complete game, and then testing the end-game conditions.

Written by Richert Wang in Spring 2016. Based on David G. Kay's Anteater Bed and Breakfast assignment in Winter 2016.