CSc 120: Battleship
Background
Battleship is a
guessing game where two players take turns trying to guess the
locations where their opponent has placed a set of "ships" on a
10x10 grid (video).
Restrictions
-
For the long problem, your code should follow the style guidelines
for the class. You must follow the updated guidelines for commenting classes.
-
You may not use concepts and/or short-hand syntax not yet covered in class. The restrictions include the following:
-
dictionary or list comprehensions, e.g., [n * 2 for i in range(10)]
-
with open (explicitly open and close the file instead)
-
the ternary operator (use an if instead)
-
nested functions (using def within a function to define another function)
-
exceptions (try/except)
-
type annotations
-
lambda expressions
-
generators and user defined iterators
-
default arguments
-
decorators
-
importing libraries (unless a library is explicitly mentioned in the specification)
Problem Description
This program involves writing a program to model half of the actual board
game, namely, Player 1's ship placements and Player 2's guesses.
The game setup.
For the purposes of this program, the game board is a 10x10 grid. We
use (x,y) coordinates to refer to the points of this grid: on
each axis, grid values range from 0 through 9; the
bottom-left corner has coordinates (0,0); and the top-right corner
has coordinates (9,9).
Each player has
five ships
(one of each kind):
Ship type
|
Abbreviation
|
Size
|
Aircraft carrier |
A |
5 |
Battleship |
B |
4 |
Submarine |
S |
3 |
Destroyer |
D |
3 |
Patrol boat |
P |
2 |
Expected Behavior
Write a Python program, in a file battleship.py,
that behaves as specified below.
-
Use input(), without any arguments, to read in the name
of a placement file describing Player 1's ship placements.
Read in the contents of the placement file and initialize the board accordingly.
The format of the placement file is described below under
Input Formats.
The rules for legal placement are given in the link battleship-rules.
An example placement file is shown in the file
example-placement.txt.
-
Use input(), without any arguments, to read in the name
of a guess file describing Player 2's guesses. Read in the contents and
for each guess, respond based on the effects of the guess as described below.
The format of a guess file is described below under Input Formats.
The rules for legal guesses are given in the link battleship-rules.
An example guess file is shown in the file example-guess.txt.
Process the guess file as follows. For each guess:
-
If the guess is not legal: give the error message
"illegal guess", discard the
guess, and continue processing.
-
If the guess (x, y) is legal:
-
If the grid point (x, y) is not occupied by
any of Player 1's ships, indicate this as follows.
If this is the first time this grid point has been guessed,
print out the message "miss";
if this grid point has been guessed previously,
print out the message "miss (again)".
-
If (x, y) is occupied by some ship S,
and at least one of the grid points occupied by S
has not been hit by any of Player 2's guesses up to and
including the current guess, indicate this using as follows.
If this is the first time this grid point has been guessed,
print out the message "hit";
if this grid point has been guessed previously,
print out the message "hit (again)".
-
If (x, y) is occupied by some ship S,
and all of the grid points occupied by S have been hit
by Player 2's guesses up to and including the current guess
(i.e., this guess hits the last grid point of S that was
not previously hit), indicate this using the statement
print("{} sunk".format(ship))
where ship is one of
{ 'A',
'B',
'S',
'D',
'P' } and refers to the ship occupying
the grid point (x, y).
-
If, after this guess, all of Player 1's ships have been sunk,
indicate this using the following statement and then exit
the program:
print("all ships sunk: game over").
-
The game ends (the program terminates) when either all of the ships have
been sunk, or there are no more guesses to respond to.
An example of the program's expected behavior is given
Battleship Input/Output Example. The input files corresponding to this
example are available as
example-placement.txt
(placement file) and
example-guess.txt
(guess file).
The rules for legal guesses are given in the link battleship-rules.
Input Formats
I. Player 1's ship placements
This is done by specifying the placement of each ship in turn. Each ship's
placement has the following form:
Abbreviation x1 y1
x2 y2
where Abbreviation is one of A, B, S,
D, and P (see table above);
(x1, y1) specifies the
grid coordinates of one end of the ship; and
(x2, y2) specifies the coordinates
of the other end. The rules for legal placement are given
here.
For example:
B 3 2 3 5
specifies that the battleship (B) occupies the four grid points
from (3,2) to (3,5). The input file should contain five such placements,
one for each of Player 1's ships.
II. Player 2's guesses
Each guess is a pair of integers on a single line specifying a grid point. The rules for
legal guesses are given in the link battleship-rules.
Programming Requirements
Your program must implement the following classes:
-
class GridPos
-
An instance of this class describes a grid position.
Attributes: These should include:
-
the x- and y-coordinates of the position;
-
the Ship object at that position, if any, and
None if the position is unoccupied; and
-
whether or not it has been previously guessed.
Methods: These should include
__init__() and __str__()
methods; and, optionally, a __repr__() method.
-
class Board
-
An instance of this class describes a board with a placement of ships.
Attributes: These should include:
-
a 10 × 10 grid of positions, where each position is a
GridPos object; and
-
a collection (e.g., list, set, or dictionary) of Ship
objects.
Methods: These should include:
-
a method to process guesses.
-
__init__() and __str__()
methods.
-
class Ship
-
An instance of this class represents a ship.
Attributes: These should include:
-
the kind of ship (see the table at the top of this page);
-
the size of the ship;
-
the grid positions occupied by the ship; and
-
the number of grid positions occupied by the ship that have
not yet been hit.
Methods:
__init__() and __str__()
methods.
Errors
There are several possible errors that relate to the contents
of the placement file (e.g.,
too many or too few ships,
not all of the ships are placed,
some ships are placed more than once,
one or more ships are placed off the board). Additionally, the position
of a guess might be off the board.
Use if statements to detect these errors (that is, don't use asserts
or try/except) and perform the actions specified below.
-
There should be 5 ships, one of each type; if not print the following error message and quit:
Error message: "ERROR: fleet composition incorrect"
-
If the ship is out of the grid area, print the following error message and quit:
Error message: "ERROR: ship out-of-bounds: " + line
-
If the ship is not horizontal or vertical, print the following error message and quit:
Error message: "ERROR: ship not horizontal or vertical: " + line
-
If the ship overlaps with another ship, print the following error message and quit:
Error message: "ERROR: overlapping ship: " + line
-
If the ship is an incorrect size for its type, print the following error message and quit:
Error message: "ERROR: incorrect ship size: " + line
-
If a guess is at a position not within the board,
print the following error message, discard the guess, and
continue processing:
Error message: "illegal guess"
Note: You must handle the errors in the order listed above so that your output
matches the output expected by the autograder.
To help simplify the logic of your code to terminate the program after the
errors in items 1-5 above are reported, you may use Python's system library.
First, include the following import statement at the top of your program:
import sys
After printing the appropriate error message, exit your program like so:
sys.exit(0)
Examples
An example of the program's expected behavior is given here
Battleship Input/Output Example.
The input files corresponding to this
example are available as
example-placement.txt
(placement file) and
example-guess.txt
(guess file).
The rules for legal guesses are given in the link battleship-rules.
`