Important Notice
INST2002 Programming 2: Description of Online Assessment
Set by: Luke Dickens
Available from 31st October, 2016 Due at 3pm on 4th November, 2016
This assessment forms part of your degree assessment. It must be done entirely on your own from start to finish:
• You must not collaborate or work with other students at any stage.
• You must not send or show other students your answers.
• You must not ask other students for help, or ask to see their answers. As well as being against regulations, this is unfair to the other student concerned, since it may lead to them being accused of plagiarism.
• You must not seek help from friends, relatives, online discussion groups other than the moodle forum for INST2002
• If you think any of the description of the task below is ambiguous or unclear, please post to the moodle forum, explaining what your concerns are, or raise it in person with your lecturer, Luke Dickens, or a INST2002 lab demonstrator.
• If you are unsure of any of the above points, please post your concern to the moodle forum.
Finally, if there is any reason you do not think you can complete this assessment in the alloted time, you should either make a formal request for an extension with your home department, or discuss your reasons with the INST2002 lecturer, Luke Dickens at l.dickens@ucl.ac.uk.
1 Outline
Your task in this assessment is to complete the implementation of a simplified computerised version of the board game Isolation, developed by Bernd Kienitz and published by Lakeside in the 1970s[1].
1.1 A Game of Isolation
The following instructions are adapted from the original rules [1] and its review on BoardGameGeek1. 1boardgamegeek.com.
1
Figure 1: The game of Isolation, published by Lakeside [1].
Isolation is a 2 player strategy game, played on a 6 ⇥ 8 grid of removable squares. An illustration of the board appears in Figure 1. On your turn, you move your pawn one space, then remove a board square (meaning that square can no longer be occupied). The object is to isolate your opponent so they cannot move. A more detailed description of the game is as follows:
The Board: You play the game on a board of 6 ⇥ 8 squares. The two starting squares have fixed platforms that cannot be removed from the board, all other squares have removable platforms. Each player is represented by a pawn (a moveable piece) that occupies exactly one platform at any one time.
The Object: To isolate your opponent’s pawn so that it is impossible for it to move.
To Start: Begin so that all the platforms are in place (i.e. all squares can be occupied). Place each pawn on it’s starting location.
To Play:
1.
On each turn,
Move your pawn one space in any direction (left, right, forward, back, or diagonally). You cannot occupy a location where the platform has been removed, or the same square as another pawn.
2.
The player who cannot legally move his/her pawn on his/her turn loses.
After moving your pawn, remove one platform from the board. You cannot choose a starting square or a square occupied by a pawn.
2 Your Task
You have been provided some code that partially implements the Isolation game described above. Your job is to complete it, by completing the implementation of two classes: Position and Board as described in the following sections. The code is provided in a single file, and contains three classes Problem, Position and Board. All three classes appear in the same file.
• Position must be a simple immutable class, and you are advised to implement this first.
• Board is a slightly more complex class that utilises Position objects, and you are advised to implement this second.
2
Position
-NODIRECTION: int
-NORTH: int
-NORTHEAST: int
-EAST: int
-SOUTHEAST: int
-SOUTH: int
-SOUTHWEST: int
-WEST: int
-NORTHWEST: int
…
Position(row: int, col: int)
+getRow() : int
+getCol() : int +isValidDirection(direction: int) : boolean
+getNeighbour(direction: int) : Position
? equals? ? ?
+stringToDirection(str: String) : int
+getAllDirections() : int[]
+getDirectionAbbreviations() : String
+toString() : String
Figure 2: A UML description of the Position class.
• You should not edit the Problem class. This has been provided so that when you have
finished you can play the isolation game, and test your implementation.
• The Problem class is public and the Position & Board classes are package visible. You
should not change the visibility of the classes.
• You should compile and test your changes regularly on your local machine.
• When you are satisfied that you have done as much as you can, you should go to the link in the TestDome email and submit the code there. A description of how to do so appears in Section 3.
2.1 Implementing Position
Your first task is to implement the Position class. This is a simple immutable class representing possible positions on a grid. Every Position object has a row and a column value which are accessed by the getRow and getCol methods respectively. For example, the position in row 1 and column 4 of the grid, would be represented by the Position (1, 4). Calling getRow and getCol on this position would give 1 and 4 respectively. However, Position objects need to be protected from changes of state.
A UML description of the Position class is shown in Figure 2. The attributes and methods that are provided for you are in grey text. The methods in blue text are not fully implemented; you will need to provide an implementation for these methods. For the equals method you will need to provide a signature and an implementation. Some static attributes have been provided for you, but you may also need to add attributes of your own to this class. The methods you need to provide are defined as follows:
• Position – A constructor for a Position, taking a row and column as input. In general, there are no restrictions on the values row and column can take.
3
• getRow – A straightforward getter method for the row
• getCol – A straightforward getter method for the column
• equals – A conventional equals method. This is an instance method that takes another Position as input and should return true if the other Position has the same row and column as this object, and false otherwise. You will need to provide the signature for this method.
• isValidDirection – This method should return true if the input is a valid direction and false otherwise. All valid directions are provided for you as static attributes: NORTH, NORTHEAST, EAST etc. Variable NODIRECTION represents an invalid direction.
• getNeighbour – If the input is a valid direction, this method returns the appropriate Position object; otherwise it should return null. For instance if the direction is NORTH the neighbour is the position one row up in the same column; if the direction is NORTHEAST the neighbour is the position one up & one right; and so on. Row number increases as we move down (SOUTH). Column number increases as we move right (EAST).
The positions extend in all directions without end; there will always be a position above, below, left and right of any other, even if the row or column numbers are negative.
The greyed out methods are already implemented and are described in the code. You can add any other helper methods you think appropriate.
[hint] You may find getAllDirections useful when implementing part of the Board class.
2.2 Implementing Board
Your second task is to implement the Board class. This is a more complex class representing a board state for the game of Isolation. We can refer to particular locations on the Board with a Position object; these are valid Positions, all other positions are invalid.
A UML description of the Board class is shown in Figure 3. You will see a number of attributes in red. These have been partially defined for you, but you will need to decide their visibility and whether they should be class or instance attributes. You do not need to add any other attributes, but you may choose to.
As before, the methods that are provided for you are in grey text. The methods in blue text are not fully implemented; you will need to provide an implementation for these methods. The methods provided for you are as follows:
• Board() – A constructor taking zero arguments has been provided, this creates a 2-dimensional array of ints one for each location on the board. Each location’s int gives the state of the platform at that location. A value of Board.FIXED represents a fixed platform that cannot be removed. A value of Board.PRESENT represents a non-fixed platform. And value of Board.REMOVED represents a platform that has been removed. Attributes p1Pawn and p2Pawn respectively hold player 1 and 2 pawn positions. The P1START and P2START attributes hold the initial pawn positions.
• Board(Position, Position) – A second constructor has been provided that allows the start- ing pawn positions to be specified. This constructor is for testing purposes, and must not be removed or edited.
4
Board
?NUMROWS: int ?NUMCOLS: int ?FIXED: int ?REMOVED: int ?PRESENT: int ?P1START: Position ?P2START: Position ?p1Pawn: Position ?p2Pawn: Position ?locations: Position[][]
+Board()
+getPlatformAt(pos: Position)
+toString() : String
+getPawnPosition(player: int) : Position +isValidLocation(pos: Position) : boolean +hasPlatform(testId: String) : boolean +isValidMove(player: int, move: int) : boolean +tryToMovePawn(player: int, move: int) : boolean +playerCanMove(player: int) : boolean +tryToRemovePlatform(row: int, col: int) : boolean
Figure 3: A UML description of the Board class.
|0|1|2|3|4|5|6|7|
—————–
0 |x| | | | |x|x|x|
1 | | |x|x|x|2|x| |
2 |#| | | |x| |x|x|
3 | |x|x|x|x| | |#|
4 | | |x|1|x| |x| |
5 |x| |x|x| |x| | |
Figure 4: Desired representation of a game state in Isolation.
• getPlatformAt – Gets the platform state at a given position. Input positions must be valid.
• toString – Gets a String representation of the board.
When implemented correctly, the board position shown in Figure 1 should output as seen in Figure 4.
The methods you need to provide are defined as follows:
• getPawnPosition – Takes a player id as input and returns the Position of that player’s pawn.
• isValidLocation – Takes any Position object and returns true if it is a location on the board, and false otherwise.
• tryToRemovePlatform – Takes a row and column as input and attempts to remove the plat- form at that location. If this is a valid choice, it should remove the platform and return true; otherwise it should return false.
• isValidMove – Takes a player id (int) and move (int) as input, and returns true if it is a 5
valid move for that player’s pawn. Remember: the move must be valid, and a player cannot move to a location outside of the board, onto a location with the platform removed or onto another player’s pawn. You can assume that the player id is okay.
• tryToMovePawn – Takes a player and move as input, and if these are valid update the state of the board to reflect this and return true. Otherwise return false
• playerCanMove – Required to test whether the game is finished. This takes a player’s id as input, and checks whether any move is possible for the pawn; it returns true if so, and false otherwise.
Some of these methods build on the functionality of earlier methods, so you are advised to implement them in order. When you have finished implementing all methods in Position and Board, you should be able compile and play the Problem class.
3 Submission
This section contains detailed instructions on how to submit your assessment, as well as some guidance.
3.1 Some Rules and Advice
You have been provided with signatures for all the necessary methods described above in the code. You should not change any of these signatures. In particular, for the methods provided in the code:
• Do not change the return type.
• Do not change the visibility, e.g. public.
• Do not change the input arguments.
• Do not change whether a method is static or not.
You may write your own additional methods in any way you see fit. You may also add attributes to the Position and Board classes. In some cases, it may be easier to solve the problem if you define helper methods, and you will be given credit if these are used appropriately.
3.2 A Local Copy of the Code
If you go to moodle, you can access a local copy of the code. This is the same code that will appear in the text box when you finally log in to TestDome (see Section 3.3). You can experiment with the code on moodle to test your ideas on your local machine, before you log in to TestDome.
Try compiling this local code to start with, then running it to see what happens. At this point, try to make changes in line with the description above, and recompile and run regularly to test your changes.
6
3.3 When you are ready
When you are ready, follow the link in the TestDome email and start the test. This will involve making changes to the programme in the text box, and then clicking the Run button. If the programme fails to compile, then you will get a compiler error, that will help you to locate the problem. If the programme compiles, then TestDome will run a series of tests, that will tell you what parts of the programme now work. To begin, you may choose to copy and paste the code that you have been working on locally. However, you may need to then modify the code in the text box, if some of the tests fail.
You should try to make as many tests pass as you are able. There is more than one way to solve this problem, and so long as you follow the instructions and pass all the tests on TestDome you will be given a minimum of 80% on this assessment. Additional marks will be given for coding style, up to a maximum of 20%. This includes, but is not limited to: good variable names, appropriate use of control flow (e.g. for loops and if statements), meaningful and appropriate comments, minimising duplication & unnecessary code, appropriate helper methods, and consistent formatting.
References
[1] Bernd Kienitz. Isolation (the don’t get stranded strategy game), 1972. Published by: Lakeside.
7