# Exercise Sheet C

## Exercise

Your work for this exercise sheet will be automatically collected in (if you put it in the right place) at 5 p.m. on Friday 6th December.

Put your work into a subdirectory of your `cs2000` directory called `sheetC`.

In this exercise, you will write a program for playing the Hindu board game of Moksha-Patamu. In this game, players move around a board according to the throw of a dice. Players are occasionally rewarded (for virtue, faith, reliability, generosity, knowledge and asceticism) by being allowed to directly ascend to later squares on the board. Other times, they are punished (for disobedience, vanity, vulgarity, theft, lying, drunkenness, debt, rage, greed, pride, murder and lust) by being required to directly descend to earlier squares on the board. The first to reach the final square wins.

In case you haven't guessed, Moksha-Patamu is the original form of Snakes and Ladders. These days the ladders and snakes are no longer labeled with rights and wrongs. Some might say that this reflects the moral vacuum at the heart of modern society.

### Part 1

Write a class definition `Dice`. For generality, we will allow our dice to be n-sided dice, where n is supplied as a parameter to the constructor.

The interface is as follows:

• Constructors

There are two constructors. The first constructor is told how many sides the dice is to have. The second constructs a standard 6-sided dice.

```public Dice(int theNumOfSides)

public Dice()```
• Getters
`public int roll()`

The getter uses Java's random number facilities (covered in lectures) to roll this dice. The return value is an integer between 1 and the number of sides inclusive.

### Part 2

The next class definition we need will represent squares on the board. This has quite a lot of methods, but first here are some hints about its instance variables.

• Each square will have a unique number. Look at the way we gave unique numbers to borrowers in lecture 11.
• Each square will need to know what square comes next. Many of you will be tempted to store this as an `int`: the number of the next square. Don't do it that way. Instead, use an instance variable of type `Square`. (If this variable contains `null`, then this square has no next square, and it must be the final square on the board.)
• If a square contains the head of a snake, we need to store the square that this snake takes us to. (Again, don't do this using `int`s. And again if this variable is `null`, then there is no snake head in this square.)
• Similarly for the foot of a ladder.
• We need to know which players, if any, are currently in this square of the board. Several players may be in this square at the same time, so we need some sort of data structure (list or array or...). To make this easier for you, I've written a class definition called `ListOfPlayers`. It provides a zero-argument constructor to create an empty list of players, and it provides two methods, `add` and `remove`, for inserting and removing players from the list, respectively. Obtain your copy of this class definition here.

Now here's the interface for your `Square` class definition:

• Constructor
`public Square()`

In your constructor, assign a unique number to the square being created. The first square that ever gets created should be square 1; the next should be square 2; and so on.

Think about all the other instance variables. Are Java's default initialisations appropriate?

• Getters
`public int getSquareNumber()`

- returns this square's unique number.

`public boolean hasNext()`

- tells you whether this square has a next square or not (hence we can use this to tell whether this is the final square on the board).

`public Square getNext()`

- gets the next square (but null if there is no next square).

`public boolean containsSnakeHead()`

- returns true if this square contains a snake head.

`public boolean containsLadderFoot()`

- returns true if this square contains a ladder foot.

`public Square getSnakeDestination()`

- returns the square at the very end of the tail of the snake (but null if this square contains no snake head).

`public Square getLadderDestination()`

- returns the square at the very top of the ladder (but null if this square contains no ladder).

`public ListOfPlayers getPlayers()`

- returns the list of players who are currently resident in this square.

• Setters

These all make simple changes to the instance variables that you defined earlier.

`public void linkTo(Square theNextSquare)`

- links this square to the next square.

`public void addSnake(Square theTail)`

- adds a snake to this square. The snake's head is in this square. The location of its tail is given as a parameter.

`public void addLadder(Square theTop)`

- adds a ladder to this square. The foot of the ladder is in this square. The location of the top of the ladder is given as a parameter.

`public void addPlayer(Player thePlayer)`

- adds a player to this square. This updates the contents of the list of players.

`public void removePlayer(Player thePlayer)`

- removes a player from this square. Again this updates the contents of the list of players.

### Part 3

Now it's time to write `Player`. There are three instance variables: the player's name (use a `String` for this; don't bother with `PersonName` on this occasion); the player's dice; and the player's current square.

• Constructor
```public Player(String theName, Dice theDice)
```
• Getters
`public String getName()`

- returns the player's name.

`public int roll()`

- rolls the player's dice and returns the result.

`public Square getSquare()`

- returns the square that this player is currently on.

• Setters

The setters are quite tricky, so think hard about them.

`public void setSquare(Square theSquare)`

This puts the player onto whatever square is supplied as a parameter. Obviously, this method will update one of `Player`'s instance variables.

But it has to do more than that! This setter must also send messages to two squares: to remove the player from one of the squares and to add him/her to another square.

`public void moveBy(int theDisplacement)`

We use this method to move the player after s/he has rolled a certain number on his/her dice. The amount by which s/he should move is the parameter of this method.

Think about how you used to do this when you played the game for real. You lifted up your counter, and you counted off an appropriate number of next squares. E.g. if `theDisplacement` is three, you count off three next squares.

If during this, you were moved to or beyond the final square, you could stop counting and you could place your counter triumphantly on the final square (you have won).

Once you have stopped counting, you looked at the square your counter ended up on. Did it contain a snake head? If so, your counter slithered to the square at the tail of the snake. Or did it contain the foot of a ladder? If so, your counter climbed to the top of the ladder.

But things didn't stop there! On arriving at the tail of a snake or top of a ladder, you then looked to see whether you had arrived at the head of another snake or foot of another ladder. This process would repeat until your counter was resting in a square that contained no more snake heads or ladder feet.

Your `moveBy` method should be a faithful implementation of what you used to do when playing the game for real. Don't forget to update the instance variables in `Player` and in the two `Squares` that are affected by this move.

Note that if the board contains a cyclic structure of snakes and ladders, then some moves will be infinite. If this happens when you run the program, you will have to kill off the program (using CTRL-C). If this seems unsatisfactory to you, then see the Challenge Exercise.

### Part 4

There's just one class definition remaining. It's called `SnakesAndLadders`. I've made a start on it for you, which you can obtain here.

I've already defined its instance variables, written its constructor, some getters and a `main` method. The parts I've written create the Snakes & Ladders board, i.e. the parts I've written create an appropriate number of `Square` objects, and link them together in sequence, using your `Square` class definition. My code also generates a random number of snakes and ladders and places them into the squares.

So there is only one thing left for you to do, and that is to write the `play()` method.

Assume that the players (in the array called `players`) take turns in the same order as they appear in the array.

Place each player onto the starting square of the board. Then each takes a turn to throw their dice and move to a new square. If anyone reaches the final square, the game is immediately over.

Include some print statements in your `play` method and add some extra print statements to your `moveBy` method in `Player` so that when you run the game, the user gets some idea of what is going on.

Here's some example output for three players:

```All 3 players are at the start.
Ann rolls 1
After moving 1 place, s/he is now at square 2
But this contains a ladder! S/he clambers to square 16
Bob rolls 4
After moving 4 places, s/he is now at square 5
But this contains a ladder! S/he clambers to square 26
Col rolls 5
After moving 5 places, s/he is now at square 6
Ann rolls 6
After moving 6 places, s/he is now at square 22
Bob rolls 5```

etc.

### Part 5

You've finished. This part is just for fun.

I've written some other class definitions to provide a GUI for your Snakes and Ladders game. My class definitions use your class definitions. So if yours are wrong, my stuff may not compile or may not run correctly.

You need to obtain copies of the following files: MokshaPatamu.java, SLController.java, SLGUI.java and SLSquareGUI.java.

Compile using

`javac MokshaPatamu.java`

and run using

`java MokshaPatamu`

The GUI doesn't use lovely pictures of snakes and ladders. Sorry - I've no time to make it look better.

## Challenge Exercise

This Challenge Exercise does not involve programming. It only involves thinking!

As mentioned above, my code for randomly generating the snakes and ladders sometimes generates cyclic structures, e.g. a snake head in square i might have its tail in square j; but j might be the foot of a ladder that takes you back up to i!

The challenge is to write down a precise set of rules for the legal placement of snakes and ladders on a m by n board.

If you think this is easy, then you haven't thought about it at all!

Discuss your ideas with me and/or put them into a text file in `sheetC/challenge`.