For your previous programming assignment, you were to have developed a class, SixSidedDie, each of whose instances represented a fair six-sided die, such as those often employed in games of chance (e.g., craps) and board games (e.g., Monopoly). Perhaps our motivation for developing this class was that we were interesed in building a computerized version of craps, or Monopoly. In that case, SixSidedDie would serve its purpose adequately.
On the other hand, when we are designing and building software components (such as Java classes), we should keep in mind that it is to our advantage to build components that serve not only our immediate purposes, but also unforeseen purposes that may arise in the future. That way, when those purposes arise, we will already have in our "library" components that we can use, rather than having to build new ones or enhance the functionality of old ones.
For this reason, we should seek to make our components as general-purpose as possible, within reason. (Of course, there is typically a tradeoff between generality and performance/simplicity, so it is not always best to design a component to be as general "as possible".)
Following this theme, for this assignment you are to complete the development of a class AnySidedDie that is more general than SixSidedDie in the sense that its instances include not only fair six-sided dice but also (not necessarily fair) dice with two sides, or five, or any other number.
The first constructor in the class is intended to be used when an unfair die is created. Its argument indicates not only how how many sides the die has but also the probability with which each side is to occur as the result of a toss. The second constructor, whose lone argument indicates the die's number of sides, is for initializing a fair die (i.e., one for which each side has the same chance of being thrown).
Let us examine the first constructor in more detail so as to provide you some hints as to how you might represent an n-sided die and perform a toss. The constructor's signature is this:
public AnySidedDie(double[] freq)
As an example, suppose that the array passed to the constructor is (4.0, 1.0, 3.0). Its length is three; hence, the die to be created has three sides. The sum of its values is 8.0. As the first element's value is 4.0, that means that the probability of tossing a 1 should be 4.0/8.0, or one-half. Similarly, the probability of tossing a 2 should be 1.0/8.0 (i.e., one-eighth) and the probability of tossing a 3 should be 3.0/8.0 (i.e., three-eighths).
How can we use an instance of the java.util.Random class to make the probabilities of tossing a 1, 2, and 3 be 1/2, 1/8, and 3/8, respectively? One answer is to partition the interval [0,1) into three sub-intervals whose lengths are 1/2, 1/8, and 3/8, respectively. The obvious choices are the sub-intervals [0,1/2), [1/2, 5/8), and [5/8, 1). Then, to perform a toss, we invoke the nextDouble() method upon the Random object to generate a pseudo-random number (of type double) in the interval [0,1). To ascertain the result of the toss (i.e., the number of dots showing), we determine in which of the three sub-intervals the pseudo-random number lies. If it lies in the first sub-interval, the result is 1; if it lies in the second sub-interval, the result is 2; and so on.
Also provided to you is the class AnySidedDieTester, whose purpose is suggested by its name.
Submit the source code of your AnySidedDie class via e-mail to your instructor at mccloske@cs.uofs.edu.