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 and listTags) 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 a cruiser of length 2, a destroyer of length 3, or an aircraft 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 the name of the ship or by specific tags.

      • 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 and Fleet 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:

      • Morph from AddCommand and EditCommand to create PutShipCommand: #383

      • Morph ListCommand to list and filter ships: #384

      • Add ListTagsCommand: #385

    • 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)?
An interface is how a user interacts with the computer. For example, you can use a mouse to click on a file to open it in Windows or MacOS. This is part of the interface for these operating systems.

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.

BattleshipHeadExample2
Figure 1. The coordinates of the 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.

ModelClassDiagram
Figure 2. Model diagram that I co-authored with team member Erjill Sison.

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 Battleship in monospace font is used to refer to the Java class.

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

mapSize - 5

Destroyer

3

(mapSize + 2) / 5

Aircraft carrier

5

1

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.

ShipManagementUseCaseDiagram
Figure 3. Use case diagram for Ship Management

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:

  1. isHeadWithinBounds() - Checks if the head coordinates falls within the map grid.

  2. isBodyWithinBounds() - Checks if the body of the ship falls within the map grid.

  3. isBattleshipAbsent() - Checks if there are no other ships that are situated on the head coordinates.

  4. 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.

PutShipSequenceDiagram
Figure 4. Sequence diagram of putting a ship on the map.
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:

  1. List all ships: list

  2. List ships with certain tags: list t/t1 t/t2

  3. List certain ships: list n/destroyer n/cruiser

  4. 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.

ListShipSequenceDiagram
Figure 5. Sequence diagram of listing ships deployed on the map.

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.

ShipManagementActivityDiagram
Figure 6. Activity diagram of ship management throughout the game.

4.1.3. Design Considerations

Aspect: How a ship is placed on the map
  • Current choice:
    The same Battleship object is put in multiple cells. Each cell contains a reference to the same Battleship object. When a ship on the Cell needs to be modified, the Battleship attribute in the Cell is accessed.

    • Pros: This allows any cell that is hit to access the same Battleship object without having to separately find the Battleship object.

    • Cons: Difficult to keep track of each Battleship position.

  • Alternative:
    Two separate Battleship and BattleshipPart objects are used. The BattleshipPart object represents the body of the Battleship and contains an attribute that points to the Battleship. When a battleship on the Cell needs to be modified, the BattleshipPart is accessed, which then accesses the main Battleship 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

  1. Putting a ship on the map after initialising the map.

    1. 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.

    2. Test case: put n/destroyer r/horizontal c/b1
      Expected: Destroyer ship of size 3 will be put horizontally on coordinates b1, b2 and b3. The map is updated with 3 black cells on each of these coordinates representing the Destroyer ship.

    3. Test case: put n/aircraft carrier r/horizontal c/c1 t/bluefleet
      Expected: Aircraft Carrier ship of size 5 will be put horizontally on coordinates c1, c2, c3, c4 and c5. The map is updated with 5 black cells on each of these coordinates representing the Aircraft Carrier ship.

    4. 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

  1. User requests to list tags of ships that have already been deployed on map.

  2. 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

  1. User requests to list ships deployed on map that have certain tags.

  2. Game shows all of the user’s ships deployed on map that have certain tags.

    Use case ends.