Assignment
05: Battleship
Fall 2007,
David Matuszek |
Purposes of this assignment:
- To get you started with JUnit tests.
- To give you more practice with arrays, and with classes in general.
General idea of the assignment:
Once again, this assignment is based on a paper-and-pencil game, since those
are a good source of array problems.
|
The Fleet
| One battleship |
|
| Two cruisers |
|
| Three destroyers |
|
| Four submarines |
|
|
Battleship is usually a two-player game, where each player has a fleet and
an ocean (hidden from the other player), and tries to be the first to sink
the other player's fleet. We'll just do a solo version, where the computer
places the ships, and the human attempts to sink them.
How to play:
The computer places the ten ships on the ocean in such a way that
no ships are immediately adjacent to each other, either horizontally, vertically,
or diagonally. For example,
The human player does not know where the ships are. The initial display of
the ocean shows a 10 by 10 array of locations, all the same.
The human player tries to hit the ships, by calling out a row and column number.
The computer responds with one bit of information--hit" or "miss." After
each shot, the computer redisplays the ocean with the new information.
A ship is "sunk" when every square of the ship has been hit. Thus,
it takes four hits (in four different places) to sink a battleship, three to
sink a cruiser, two for a destroyer, and one for a submarine. The object is
to sink the fleet with as few shots as possible; the best possible score would
be 20. (Low scores are better.) When all ships have been sunk, the program
prints out a message that the game is over, and tells how many shots were required.
Details:
class Battleship
The Battleship class is the "main" class--that is,
it contains a main method. In this class you will set up the
game; accept "shots" from the user; display the results; print
final scores; and ask the user if he/she wants to play again. All input/output
is done here (although some of it is done by calling a print() method in the Ocean class.) All computation will be done
in the Ocean class.
To aid the user, row numbers should be displayed along the left edge of the
array, and column numbers should be displayed along the top. Numbers should
be 0 to 9, not 1 to 10.
The top left corner square should be 0, 0. Use different
characters to indicate locations that contain a hit, locations that contain
a miss, and locations that have never been fired upon.
Use methods. I won't tell you exactly what methods to write this time, but
you should have a pretty good idea by now of what kind of methods you will
need.
class OceanTest
This is a JUnit test class for Ocean. Test every required
method for Ocean, including the constructor, but not including
the print() method. If you create additonal methods in the Ocean class,
you must either make them private, or write tests for them. Test methods do
not need comments, unless they do something non-obvious.
Experience has shown that it is a bad idea for one partner to write the
tests and the other partner to write the code. It works much better if
you write tests for your own code.
class Ocean
Ship placement can be described by two integer variables, row and column,
and one boolean variable, isHorizontal. If isHorizontal is
true, then row and column indicate the
leftmost square of the ship, and remaining squares extend to the right. If isHorizontal is
false, then row and column indicate
the topmost square of the ship, and remaining squares extend below it.
Here's
what you should have (and what we will test for) in your Ocean class.
Ocean()
- The constructor. Creates and returns an "empty" ocean. Also initializes
any game variables, such as how many shots have been taken.
void placeAllShipsRandomly()
- Using the methods below, place all ten ships randomly on the (initially
empty) ocean. Place larger ships before smaller ones, or you may run into
a situation where it is impossible to continue. You will want to use the
Random class
in the java.util package,
so look that up in the Java API.
boolean okToPlaceBattleshipAt(int row, int column, boolean isHorizontal)
- Returns
true if and only if it is possible to place a battleship
in the indicated location on this Ocean. This method will return false if
any of the following conditions hold:
- Either row or column is not in the range 0 to 9.
- The ship would "stick out" beyond the edges of the array.
- The ship would overlap with an existing ship.
- The ship would be adjacent (horizontally, vertically, or diagonally) to an existing ship.
void placeBattleshipAt(int row, int column, boolean isHorizontal)
- Places a battleship in the indicated location on this Ocean. You can assume
that the indicated location is legal.
boolean okToPlaceCruiserAt(int row, int column, boolean isHorizontal)
- Similar to
okToPlaceBattleshipAt, but for cruisers.
void placeCruiserAt(int row, int column, boolean isHorizontal)
- Similar to
placeBattleshipAt, but for cruisers.
boolean okToPlaceDestroyerAt(int row, int column, boolean isHorizontal)
- Similar to
okToPlaceBattleshipAt, but for destroyers.
void placeDestroyerAt(int row, int column, boolean isHorizontal)
- Similar to
placeBattleshipAt, but for destroyers.
boolean okToPlaceSubmarineAt(int row, int column)
- Similar to
okToPlaceBattleshipAt, but for submarines. Submarines
occupy a single square, so "horizontal" or "vertical" orientation is meaningless.
void placeSubmarineAt(int row, int column)
- Similar to
placeBattleshipAt, but for submarines. Again, orientation
is meaningless.
boolean isOccupied(int row, int column)
- Returns
true if the given location contains a ship, false if it does not.
boolean shootAt(int row, int column)
- Returns
true if the given location contains a ship, false if
it does not. In addition, this method updates the number of shots that have
been fired, and the number of hits.
Important note: If a location
contains a ship, this method will return true every
time the user shoots
at that same location. The ship is never actually removed from the Ocean.
So don't assume the game is over when 20 hits have been recorded; every
square occupied by a ship must be hit.
int numberOfShotsFired()
- Returns the number of shots fired (in this game).
int numberOfHits()
- Returns the number of hits recorded (in this game). All hits are counted,
not just the first time a given square is hit.
boolean isGameOver()
- Returns
true if all ships have been sunk, otherwise false.
void print()
- Prints the ocean. To aid the user, row numbers should be displayed along
the left edge of the array, and column numbers should be displayed along
the top. Numbers should be
0 to 9, not 1 to 10.
The top left corner square should be 0, 0. Use
different characters to indicate locations that contain a hit, locations
that contain a miss, and locations that have never been fired upon.
This is the only method in the Ocean class that does any input/output,
and it is never called from within the Ocean class (except possibly during
debugging.)
You are welcome to write additional methods of your own. In fact, you probably
should, because otherwise there will be quite a lot of repeated code. Remember
the DRY principle: Don't Repeat Yourself.
Additional methods should either be tested (if you think they have some usefulness
outside this class), or private (if they don't).
Additional requirements:
- Every method, except your test methods, should have javadoc comments. Use
Eclipse's Source -> Generate Element Comment to get the correct
form.
- The program should be properly formatted. Use Eclipse's Source ->
Format to get it right.
- Every method should be short enough to see all at once on
the screen.
- All fields (instance variables and static variables) in the
Ocean class
must be marked private. You may not provide getter or setter
methods for those fields, other than those specified above.
Due date:
Thursday, October 18, before midnight.
Turn in your program electronically, using Blackboard.
(See my Instructions for Using
Zip Files and Blackboard). Only assignments submitted via Blackboard
will be accepted--do not send your program by
email. The usual late penalty of 5 points per day (out of 100 points) will apply.