Hello there! My name is Ian and I am one of the developers for the Battleship game. The following document is a Project Portfolio Page of my contributions to the application.
1. Project Overview
Battleship is the product of a semester-long project, in which my team was tasked with adapting an existing phone addressbook application into an application of our choice. The project was part of a module on software engineering that I read at the National University of Singapore (NUS). The application, Battleship, is a revival of the classic retro game Battleships, where players try to destroy each other’s ships by guessing the positions of their opponent’s battleships.
In our Battleship application, however, players have the opportunity to use both a Command Line Interface (CLI) and a Graphical User Interface (GUI) to play the game. The GUI was created with JavaFX and the application code was rigorously tested to ensure a high quality of code.
My role in the team was to design and implement the Ship Management feature. The feature allows players to manage their ships during the game. The Ship Manager feature consists of the commands put
, list
and listTags
. Together, these three commands provide an intuitive way for players to interact with their own ships. The following sections illustrate the feature in more detail, as well as the relevant sections I have added to the user and developer guides in relation to this feature.
You can find out more about the Battleship application here.
2. Summary of contributions
-
Major enhancement: I added the Ship Management feature of the game.
-
What it does: The Ship Management feature consists of three commands (
put
,list
andlistTags
) and the classes representing the battleship, coordinates, orientation and player fleet.-
The
put
command allows the user to place a ship on the map grid. The user is also given the option of tagging the ships. The ship can be acruiser
of length 2, adestroyer
of length 3, or anaircraft carrier
of length 5. -
The
list
command allows the user to list down the ships that have been placed on the map grid. The user can filter the list by thename
of the ship or by specifictags
. -
The
listTags
command allows the user to list down all the tags that have been used on ships.
-
-
Justification: The Ship Manager feature is crucial to the game as it works together with the map grid to allow both the human player and the computer player to interact in a turn-taking game. Behind the scenes, the feature also implements the
Coordinates
,Orientation
andFleet
classes for other features to work. Furthermore, the feature implements boundary value checking that is used by the Battle Manager and Computerised Enemy feature. -
Highlights: The other features rely on the functionality provided by the Ship Management feature. It also makes ship management highly intuitive for the player.
-
-
Code contributed: Here are my code commits and my RepoSense statistics.
-
Other contributions:
-
Project management: Managed release
v1.3
on GitHub. -
Enhancements to existing features:
-
Community:
-
Contributed actively in issue tracking: issues created by me.
-
Contributed actively in forum discussions: discussions raised by me.
-
Reported bugs and suggestions for other teams: bugs found by me.
-
-
Tools: Integrated Travis CI Bot and Coveralls Checker with team repository.
-
3. Contributions to the User Guide
Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users. |
3.1. Introduction
Ships ahoy! Battleship is a simple computer-based remake of the classic Battleship game.
It is for people who want to experience the joy of playing Battleships without the hassle and fuss of dealing with physical game pieces.
Battleship is optimised for people who want to use a Command Line Interface (CLI), while still retaining the benefits of a Graphical User Interface (GUI).
It’s a single-player game, and provides a fully functional computerised enemy player for the player to play against, guaranteeing many hours of fun! Can’t wait to get started? Head over to [Quick Start] to fire away!
What is a Command Line Interface (CLI) and a Graphical User Interface (GUI)? A Command Line Interface (CLI) interacts with the user by accepting words that are typed in by the user. Conversely, a Graphical User Interface (GUI) interacts with the user visually. It uses icons and graphics to show the user what the program is doing. |
As you will see, Battleship is a hybrid application. It combines both a CLI and GUI, meaning that the user must type in commands but will see the changes caused by those commands graphically.
3.2. Features
3.2.1. Managing ships: put
, list
, listTags
Placing a ship on the map: put
Adds a ship onto your map. The coordinates specified is the position of the ship’s head.
Format: put n/NAME c/COORDINATES r/ORIENTATION [t/TAGS]
Examples:
-
put n/destroyer c/a1 r/vertical
-
put n/aircraft carrier c/b1 r/h t/tag1
The head of a ship is the top-most and left-most cell of the ship. When coordinates are specified in the put
command, it specifies the coordinates of the head of the ship, as shown in the figure below.
put
command refer to the coordinates of the ship head.The orientation of the ship can be horizontal
or vertical
. This may be shortened to h
or v
, respectively. The orientation of the ship must be specified.
When putting a ship on the map grid, you should specify the head coordinates such that:
-
The ship falls within the map grid.
-
The ship does not collide with another ship that is already on the map grid.
4. Contributions to the Developer Guide
Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project. |
4.1. Ship Management feature
The Ship Management feature is named as such to avoid confusion with the main title of the game, Battleship. In this section, the words "battleship" and "ship" are used interchangeably. The capitalised word |
4.1.1. Current Implementation
The ship management feature handles the following:
-
Putting ships on the map grid and ensuring that ships are placed in valid areas on the map grid.
-
Keeping track of the status of ships in the player.
We can see the use case scenarios in the diagram below.
Battleship
is a class representing a ship that can be placed on the map grid. A FleetEntry
class is internally used to store the Battleship
in a player’s Fleet
. FleetEntry
is a nested class within Fleet
that contains a Battleship
, its head Coordinates
and its Orientation
on the map grid.
The length of the ship varies depending on the type of ship. The user can tag a ship using a t/[TAG]
parameter in the put
command. Tagging a ship is optional.
There are three types of ships and the number of each ship depends on the size of the map. The relationship between map size and the number of each ship is illustrated in the table below.
Type of Ship | Length | Number |
---|---|---|
Cruiser |
2 |
|
Destroyer |
3 |
|
Aircraft carrier |
5 |
|
The management of ships can be carried out with three commands, namely put
, listTags
and list
.
Putting ships
The put
command puts a ship on the map grid, specified by the head coordinates.
The following operations are called when the put
command is called.
-
performChecks()
- Performs checks to ensure that the ship can be put on the map. -
putShip()
- Puts the ship into the cell.
The boundary checks are essential to the functionality of both the human and computer player. This is because BoundaryValueChecker
is used by the human player in the put
command and when the computer player deploying its own ships after the human player’s turn has ended. BoundaryValueChecker
relies on four separate methods to perform its checks. They are:
-
isHeadWithinBounds()
- Checks if the head coordinates falls within the map grid. -
isBodyWithinBounds()
- Checks if the body of the ship falls within the map grid. -
isBattleshipAbsent()
- Checks if there are no other ships that are situated on the head coordinates. -
isClear()
- Checks if there are no other ships that situated along the body of the ship.
These methods check the horizontal and vertical boundaries when a ship is being deployed. They distinguish between the head and body of a ship in order to provide more specific feedback for the user. For the methods isBattleshipAbsent()
and isClear()
, BoundaryValueChecker
calls the getCellStatus()
method of the mapGrid
object to obtain the status of Cell
for checks.
Once BoundaryValueChecker
has finished its checks and there are no exceptions thrown, the put
command proceeds to call the putShip()
method of the mapGrid
object to put the ship on the map grid. It then updates the Fleet
in the human player. The following sequence diagram shows what happens when the put
command is called.
Listing tags
Ships can be tagged. You can list all the tags used by ships that have been deployed on the map grid with the listTags
command. The command uses the getAllTags()
method of the Fleet
class. The code snippet below shows the operation of the getAllTags()
method. The method returns a list of all the unique tags present in the player’s fleet of deployed ships.
public List<FleetEntry> getByTags(Set<Tag> tagSet) {
return this.getDeployedFleet().stream()
.filter(fleetEntry -> fleetEntry.getBattleship()
.getTags()
.containsAll(tagSet))
.collect(Collectors.toList());
Listing ships
Ships that have been deployed can also be listed in four different ways:
-
List all ships:
list
-
List ships with certain tags:
list t/t1 t/t2
-
List certain ships:
list n/destroyer n/cruiser
-
List certain ships with certain tags:
list n/destroyer n/cruiser t/t1 t/t2
The set of unique tags and the set of unique names are presented to the ListCommand
as an Optional
class. This is because both sets may be empty. In such cases, instead of redudantly checking whether each fleetEntry
contains the ship and an empty set, ListCommand
simply returns the entire fleet.
The list
command can list certain ships with certain tags by filtering the list of deployed ships. The following sequence diagram shows how deployed ships are listed when the list
command is entered into the command line.
4.1.2. Activity Diagram
Ship management functions throughout the entirety of the game. As there are multiple states during the game, it is beneficial to visualise the operations of the put
, listTags
and list
commands with respect to the different game states. The activity diagram below illustrates these operations.
4.1.3. Design Considerations
Aspect: How a ship is placed on the map
-
Current choice:
The sameBattleship
object is put in multiple cells. Each cell contains a reference to the sameBattleship
object. When a ship on theCell
needs to be modified, theBattleship
attribute in theCell
is accessed.-
Pros: This allows any cell that is hit to access the same
Battleship
object without having to separately find theBattleship
object. -
Cons: Difficult to keep track of each
Battleship
position.
-
-
Alternative:
Two separateBattleship
andBattleshipPart
objects are used. TheBattleshipPart
object represents the body of theBattleship
and contains an attribute that points to theBattleship
. When a battleship on theCell
needs to be modified, theBattleshipPart
is accessed, which then accesses the mainBattleship
object.-
Pros: Clearer separation between the body of the ship and the ship itself.
-
Cons: Difficult to handle hits on the cell.
-
5. Instructions for Manual Testing
5.1. Putting a ship
-
Putting a ship on the map after initialising the map.
-
Prerequisites: There are ships in your fleet ready to be deployed. This means that the number of ship in the fleet is more than 0. The map is initialised to a size between 6 and 10.
-
Test case:
put n/destroyer r/horizontal c/b1
Expected: Destroyer ship of size 3 will be put horizontally on coordinatesb1
,b2
andb3
. The map is updated with 3 black cells on each of these coordinates representing the Destroyer ship. -
Test case:
put n/aircraft carrier r/horizontal c/c1 t/bluefleet
Expected: Aircraft Carrier ship of size 5 will be put horizontally on coordinatesc1
,c2
,c3
,c4
andc5
. The map is updated with 5 black cells on each of these coordinates representing the Aircraft Carrier ship. -
Test case:
put n/aircraft carrier r/horizontal c/e1 t/nomore
Expected: No ship is put down on the map. Error details shown in the status message. Map remains the same.
-
6. Use Cases
6.1. List all tags that ships have
MSS
-
User requests to list tags of ships that have already been deployed on map.
-
Game shows all of the tags of ships that have already been deployed on map.
Use case ends.
6.2. List ships by tag
MSS
-
User requests to list ships deployed on map that have certain tags.
-
Game shows all of the user’s ships deployed on map that have certain tags.
Use case ends.