The class Random. The Java class library provides a class called Random that implements a random number generator. You will use it to help shuffle the deck. To use Random, you must put the following line at the start of your program.
Note that java and util are in lower case, Random begins with an upper case letter, and the line ends with a semicolon. The import statement obtains something from the Java library. The library is divided into packages and subpackages. The package java contains things that are generally useful when writing Java programs. Its subpackage util contains various utilities, one of which is Random.
You need only Random's constructor and its method nextInt. The constructor call new Random() returns a new instance of the class Random. If r is an instance of Random, then r.nextInt()returns a randomly generated int. It may be negative, and it may have a large absolute value.
For this program, you will need small positive random int's. You can get these by using the Java expression Math.abs(r.nextInt()) % m, where m returns a positive int greater than 0. The expression will return a random int greater than equal to 0, but less than m.
The class Card. Each instance of the class Card represents a playing card. Source code for this class is available on Moodle. To make your program easier to grade, you must use this source code; you must not modify or extend Card in any way. Here is a short description of Card's public methods, and what they do.
public Card(int rank)
Constructor. Make a new instance of Card with a given rank, which must be between 1 and 13.
public int getRank()
Return the rank of this Card.
public String toString()
Return a String that describes this Card. It must be used only for printing. For example, it might return "ace", "two", "queen", "king", etc.
Note that Card's are immutable objects, so no part of them can be changed after they are created by their constructor.
The class Deck. An instance of the class Deck represents a deck of Card's. You must write Deck yourself. It must have the following methods, and they must work as described here.
(5 points.) Constructor. Make an array containing 52 different Card's. You must use one or more loops: you will receive no points if you just write 52 assignment statements. The order of Card's within the array does not matter.
public Card deal()
(5 points.) Return the next Card from the array made by the constructor. You need not pick a Card at random, because the Card's in the array will already be shuffled into random order by the time you call deal. Throw an IllegalStateException if no Card's remain to be dealt from the array. This method must work in O(1) time.
public void shuffle()
(10 points.) Shuffle the deck of Card's that is represented by the array you made in the constructor. The easiest way is the Durstenfeld-Fisher-Yates algorithm, named after its inventors. It exchanges randomly chosen pairs of array elements, and works in O(n) time for an array of size n. You must use the following pseudocode for this algorithm.
- Do steps 2 and 3 for integer values of i, starting from the length of the array minus 1, and ending with 1.
- Let j be a random integer between 0 and i, inclusive.
- Exchange the array elements at indexes i and j.
If shuffle is called after any Card's have been dealt (by the method deal), then it must throw an IllegalStateException. You are not allowed to shuffle the deck after dealing has started.
To implement Deck, you can use ideas from the array stack class that was discussed in the lectures.
The class Pile. Each instance of the class Pile represents a pile of Card's. You must write Pile yourself. It must have the following nested classes and methods, which must work as described here.
private class Layer
(5 points.) An instance of this class represents a layer in the Pile. It must have two slots. One must be called card, and it must point to an instance of the class Card. The other must be called next, and it must point to the next Layer in this Pile. The class Layer must also have a constructor that takes two arguments, called card and next, which determine the values of the two slots.
(2 points.) Constructor. Initialize a new empty Pile of Card's.
public void add(Card card)
(3 points.) Add card on top of this Pile.
public Card turn()
(3 points.) Turn over a Card from the top of this Pile. Return the Card. Throw an IllegalStateException if there are no cards in the Pile.
public boolean isEmpty()
(2 points.) Test if this Pile has no Card's left in it.
To implement Pile, you can use ideas from the linked stack class that was discussed in the lectures.
The class Tableau. Each instance of the class Tableau represents thirteen Pile's of Card's, as described previously. You must write Tableau yourself. It must have the following methods, which must work as described here.
(5 points.) Constructor. Make an array with thirteen empty Piles in it (see below). Also make a new instance of Deck. Shuffle the Deck. Deal four cards from the shuffled Deck into each Pile.
private boolean hasWon()
(5 points.) Test if all thirteen Pile's are empty.
public void play()
(10 points.) Play a game of Perditio Tempus. Each time you get a Card from a Pile, write:
Got c from pile p.
where c is the name of the Card and p is the number of the Pile. At the end of the game, if the program won, then write:
If the program lost, then write:
Pile p is empty. You lost!
where p is the number of the empty Pile that you tried to get a card from. See the examples for details.
In Java, array indexes are numbered starting from 0, but in Perditio Tempus, piles are numbered starting from 1. The easiest way to handle this is to make an array with indexes 0 through 13, and then never use index 0.
The class Perditio. (0 points.) This class must contain only the main method. It starts the program running. You must write Perditio yourself.
Got jack from pile 1.
Got jack from pile 11.
Got three from pile 11.
Got six from pile 3.
Got two from pile 6.
Got ace from pile 2.
Got nine from pile 1.
Got king from pile 9.
Got two from pile 13.
Got king from pile 2.
Got ace from pile 13.
Got three from pile 1.
Got four from pile 3.
Got nine from pile 4.
Got four from pile 9.
Got four from pile 4.
Got king from pile 4.
Got eight from pile 13.
Got three from pile 8.
Got ten from pile 3.
Got queen from pile 10.
Got jack from pile 12.
Got four from pile 11.
Got five from pile 4.
Got seven from pile 5.
Got two from pile 7.
Got queen from pile 2.
Got ace from pile 12.
Got five from pile 1.
Got six from pile 5.
Got king from pile 6.
Got seven from pile 13.
Got queen from pile 7.
Got ten from pile 12.
Got nine from pile 10.
Got six from pile 9.
Got five from pile 6.
Got eight from pile 5.
Got ace from pile 8.
Pile 1 is empty. You lost!