Rolling

From CompSciWiki
Jump to: navigation, search

Back to the Case Studies homepage

Problem

Write a program that uses an array to store the results of a simulation with two n-sided dice. At each step in the simulation, “roll” the pair of the dice and use the array to keep track of the number times each of the possible sums has been rolled so far. To store the results of the simulation, you will need an array of length 2n - 1, where n is the number of sides to each die. The following is an example of what an array for two 6-sided dice could look like after a 24-step simulation.

      
    
  0   1   2   3   4   5   6   7   8   9   10  <-- index
 ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___
|   |   |   |   |   |   |   |   |   |   |   |
| 1 | 3 | 0 | 2 | 3 | 5 | 3 | 4 | 2 | 1 | 0 | <-- value
|___|___|___|___|___|___|___|___|___|___|___|

Element 0 in our array represents a sum of 2, element 1 represents a sum of 3 and so on. The above array indicates that during the simulation, a sum of 2 (element 0) was rolled once, while a sum of 7 (element 5) was rolled 5 times.
Your program should ask the user for two values:

  • The number of sides to the dice. Both dice will have the same number of sides.
  • The number of steps in the simulation.

After reading in the input using Scanner, simulate rolling the die by generating two random numbers between 1 and the number of sides (inclusive). After the simulation is complete, print out a histogram displaying the percentage of simulation steps that generated each possible sum.


The following is an example histogram for the simulation illustrated above, with percentages rounded to nearest integer:

Sum of 2: ==== (4%)
Sum of 3: ============= (13%)
Sum of 4: (0%)
Sum of 5: ======== (8%)
Sum of 6: ============= (13%)
Sum of 7: ===================== (21%)
Sum of 8: ============= (13%)
Sum of 9: ================= (17%)
Sum of 10: ======== (8%)
Sum of 11: ==== (4%)
Sum of 12: (0%)

In addition to re-using the printBar method from Nucleotides, your program should consist of the following four methods:

public static void initializeArray(int initValue, int[] array)

The method initializeArray should set all values in the array to initValue.

public static int generateRandomNumber(int maximum)

The method generateRandomNumber should use Math.random to generate a random number between 1 and maximum (inclusive). For example, generateRandomNumber(4) should return one of 1, 2, 3, or 4.

public static void performSimulation(int numSides, int[] counts, int numSteps)

The method performSimulation should call initializeArray to set all values of the counts array to 0 and then execute the simulation. Executing the simulation should consist of repeated calling generateRandomNumber twice (to simulate rolling both dice). numSides is the number of sides to the dice.

public static void printRollHistogram(int numSides, int[] counts, int numSteps)

The printRollHistogram method should print a header line listing the parameters of the simulation (number of sides to the dice and the number of simulation steps) and then print the entire histogram for the given simulation.


Here is a sample run of the program

Enter the number of sides to the dice
8
Enter the number of simulation steps
50
Results of a 50-step simulation with two 8-sided dice:
Sum of 2: == (2%)
Sum of 3: (0%)
Sum of 4: == (2%)
Sum of 5: ====== (6%)
Sum of 6: ================ (16%)
Sum of 7: ======== (8%)
Sum of 8: ==== (4%)
Sum of 9: ==================== (20%)
Sum of 10: ======== (8%)
Sum of 11: ======== (8%)
Sum of 12: ======== (8%)
Sum of 13: ========== (10%)
Sum of 14: == (2%)
Sum of 15: ==== (4%)
Sum of 16: == (2%)
Enter the number of simulation steps
600
Results of a 600-step simulation with two 8-sided dice:
Sum of 2: == (2%)
Sum of 3: ==== (4%)
Sum of 4: ======= (7%)
Sum of 5: ======= (7%)
Sum of 6: ====== (6%)
Sum of 7: ========== (10%)
Sum of 8: ============ (12%)
Sum of 9: ============= (13%)
Sum of 10: ========== (10%)
Sum of 11: ========== (10%)
Sum of 12: ======== (8%)
Sum of 13: ===== (5%)
Sum of 14: === (3%)
Sum of 15: === (3%)
Sum of 16: == (2%)
Enter the number of simulation steps
-1
Programmed by [your name here].
End of Processing.
 

Rolling

Dice casestudy.jpg

Solution

Required knowledge

Understanding an array

What is an array?

Before we start writing our program we must first understand an array. An array in java, as well as other programming languages, will become one of your most important tools.

An array is used to keep a list of data in a way that we can manipulate them more efficiently. An array will be able to store multiple data items of the same data type (int, string, double, etc.) divided into a fixed number of slots. Here is an example of an array of size 10 (the size we will be using in our program):

  0   1   2   3   4   5   6   7   8   9   <-- index
 ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ 
|   |   |   |   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |   |   |   | <-- value
|___|___|___|___|___|___|___|___|___|___|

Each item in the array is called an element, and each element is accessed by a numerical index.

Note: The above array has a numerical index from 0 – 9

This is true for all arrays. The first element in the array will always be at index [0] and the last element of the array will always be at index [size_of_array – 1].

Declaring an array:

Now that we understand what an array is the next part is to understand how to use one. We must start out by declaring the array. This can be done by first determining which type of data we would like to store in our array (our current program stores values of type “int”). We can then declare our array by writing the type, followed by two brackets [] and finish off with the name of the array. Here is an example of this:

int[] arrayName;

Initializing an array:

Java now knows that arrayName is a variable array of int's. The next step is to initialize the array. By initializing the array we are giving the array a fixed size. This can be done at the same time as the declaration or, as we will see in the program we are writing, later in our code. Here is an example of initializing an array of size 10 at the same time as declaration and later in our code:

Initializing at the same time as declaration:
int[] arrayName = new int[10]; 


Initializing later in our program:
arrayName = new int[10];

We have now initialized an array of size 10. At this point every element of the array will be initialized to NULL. We are able to use this array as it is. In most cases we will want to initialize every element in the array to a set number or piece of data. To do this we will use a for loop. Java, unlike some other programming languages, has a very useful command: .length. This command will give us the size of any array we are dealing with. In this case our array will be of size 10. Here is an example of how we would put the number ‘0’ into every index of the array using a for loop:

for(int i = 0; i < arrayName.length; i++)
{
	arrayName[i] = 0;
}

We now have all the information we need to declare, initiate, and assign values to an array.


Start Programming

Organize your code

Remember to abide by the COMP 1010 coding standards while writing the code.


To create a solution for this problem we must first start out by by working on each section individually. These sections in java are called "methods". By separating our program into separate parts we can then worry about each section individually. This will make our code much easier to understand and debug. For more on methods please see User-Defined Methods. The methods that we are going to want to separate our program into are the following:

Create Initialize Array Method

public static void initializeArray(int initValue, int[] array)

This method will be used to initialize the array. To do this you will use a for loop that counts from 0 to the size of the array. We will initialize each index of the array to 'initValue'. An example of how we might approach this is provided above in Understanding an array.

Create Generate Random Number Method

public static int generateRandomNumber(int maximum)

This method will generate an int between 1 and 'maximum'. This value can be found using Math.random(). You will finish off this method by returning the random value.

Write Perform Simulation Method

public static void performSimulation(int numSides, int[] counts, int numSteps)

This method is going to perform our roll simulation. To do this we must remember three things:

1) We are rolling two dice so we must have variables 'roll1' and 'roll2'
2) To perform the rolling of the dice we are going to be using the method generateRandomNumber using our variable 'numSides' as a parameter.
3) When placing the sum of the rolls into our 'counts' array we must remember to subtract 2 from the position of the array. For example, if we were to get 1 and 1 which equals 2 we would want to raise the index 0 by 1 as explained in the problem. This is how it should look:

counts[roll1 + roll2 -2]++;

Write Print Roll Histogram Method

public static void printRollHistogram(int numSides, int[] counts, int numSteps)

This method can be done in four steps:
1)In this method we are going to be using the printBar() method. This method will require a percentage parameter so we must first declare a percentage variable:

int percentage;

2)Every time we use this method it will print out the following statement:

System.out.println("Results of a "+ numSteps + "-step simulation with two " + numSides + "-sided dice: ");

3)We are now going to run the printBar() for every index of our array counts. Any time we have to pass through an array it is a good indication that we will be using a for loop. This for loop should count from 0 to count.length.
4)In our for loop we are going to need to calculate the percentage of every index and use this percentage as a parameter with our printBar() method. Finding the percentage is a little tricky so I am going to give you the algorithm:

percentage = (int)Math.round(counts[i] / ((double) numSteps) * 100);


Print Bar Method

This method was previously used in Nucleotides. As a programmer, it is very common that you will use methods that you have previously used or created yourself. Not all previously created methods will work well in your current program the way you might predict. You may need to slightly modify either the parameters or the contents of the method. Here is the print bar method you have been given:

public static void printBar(String label, int percent, char barSymbol) {
	// works well when all labels are the same width, but not so well otherwise.
	System.out.print(label + ": ");

	for (int i = 0; i < percent; i++) {
		System.out.print(barSymbol);
	}

	System.out.println(" (" + percent + "%)");
}


Main

Now that we have all of our methods we can the begin the process of creating our main method. This should be your last step in programming a program with many different methods. The main method is where you will use all of your methods that you have created to create your final output. Since we are working with arrays our main program will have to follow the following steps:

Declare Variables

Like any program we must first start off by declaring our variables. Here is a list of the variables we will need to declare:

int[] rollArray;
Scanner myScanner = new Scanner(System.in);
int numSides;
int numSteps;

Retrieving Number of Sides

Next, we must retrieve the number of sides. We will do this by first prompting the user to write the number of sides of the dice. Then using a Scanner we will place the number of sides into the variable numSides.

Initializing Array

As discussed earlier in the description of an array it is a good idea to initialize our array to a specified size. Now that we know how many sides are on our dice we can then determine how many values we will need to keep track of. The size of our array will be [size*2 - 1].

Retrieving the Number of Steps

Again, just like in retrieving number of sides, we will prompt the user to enter the number of steps. Using a Scanner we will then place the number of steps into the variable numSteps.

Rolling

And now it is time to make our program do something. This program will do as many simulations as we would like. To do this we will need to make use of a while loop. The while loop will allow the program to continually ask the user until he/she decides that they would like to stop by typing in the value '0' for the number of simulations they would like. Our for loop is going to look as followed:

while(numSteps != 0)


In this loop we will need to do four things:
1) Initialize all elements of the array to 0. This can be done by using the method initializeArray()
2) Perform the simulation. This can be done by using the method performSimulation()
3) Print the histogram. This can be done by using the method printRollHistogram()
4) Get the next number of simulation steps. This is the same as we did earlier in the main method. Using a Scanner we will place the number of steps into a variable numSteps. When we prompt the user to enter the number of steps, remember to also allow for the user to quit the simulation. In this case since our while loop ends when numSteps = 0 let the user know by typing in '0', it will end the simulation.


Test Your Program

Now it is time to test your program. Although we did not cover it in this case study, it is a good idea to continually test your code as you construct it. Waiting until the end to test may lead to bigger problems. It is much harder to find out where the problem is situated by testing it all at once.

Run your program. See if the output matches the output in the problem. Provided below is the solution code to the problem.

Code

Solution Code

Back to the Case Studies homepage