Lab 2: Exceptions
Overview
This lab will focus on handling and using Exception
objects in a program with a Driver and a custom class.
Additionally, we will be creating our own custom Exception
class to handle an issue specific to our custom class.
The program will be performing an experiment to verify the frequency of values generated by rolling a certain collection of dice.
Pre-Lab (DUE BEFORE LAB - see due date in Canvas)
As part of the pre-lab activity you must ensure that you have accepted the assignment in GitHub Classroom and cloned your repository to a new project in IntelliJ on your computer.
Assignment
Driver class
The provided Driver
class will call the run()
method of the DiceApp
class to begin the program execution.
DiceApp class
The run()
method for this program will perform the following tasks:
- Print an introductory message to the user explaining the experiment.
- Get input from the user regarding how many dice will be rolled, how many sides the dice will have, and how many times the dice will be rolled.
- Store the results of the user input in an array
- Create the dice described in the user input
- Roll all the dice and store the result as many times as the user has requested
- Find the result that appeared most frequently during all the rolls
- Print the results of the experiment
The run()
method will do this by calling the following helper methods:
intro()
This method will print out instructions for the user.getInput()
This method will ask the user for three numbers, entered on a single line and separated by spaces and store these values in the appropriate instance variables. These numbers will be:- The number of dice to roll in the experiment
- The number of sides these dice will have
- How many times the dice will be rolled
createDice()
This method will create the correct number of dice with the correct number of sides the dice will have, storing it in the appropriate instance variable.rollDice()
This method will roll all the dice, total up the values, and add to that value's total. It will do this as many times as the user specifies.findMaxIndex()
This method will find and return the index inrolls
of the largest count.report()
This method will print the results as a horizontal bar chart using asterisks. See below for more details.
If at any time during the execution of the program an exception halts the program, an appropriate message will be printed to the console and the program will return to step 1 (getting input from the user) and ask the user for input. Once the program successfully completes, it will end.
Die class
The Die
class will keep track of the number of sides on the Die
, which should be between 2-100 inclusive, and whatever the current value of the top side of the Die
is. It will also use a Random
object called random
to determine the next value when the Die
is
"rolled". It will have three methods:
- A constructor with a single parameter
numSides
that will set the number of sides for thatDie
. If the number of sides is out of range, anIllegalArgumentException
will be thrown. You should not setcurrentValue
to anything in the constructor. getCurrentValue()
which will return the last value generated by rolling theDie
. It will also reset the current value to 0, so that theDie
must be rolled again before a value can be gotten. IfcurrentValue
is not in the expected range of theDie
, a customDieNotRolledException
will be thrown.roll()
will use theRandom
object to generate a new random value for theDie
and assign it tocurrentValue
Storing the frequencies
To keep track of how many times each value has been rolled, we will create an int[] rolls
where each index in the array will correspond to a value in the possible range for the number of sides and the number of dice.
For example, two 6-sided dice will have the value range 2-12, inclusive. This means you would create an int[]
of length 11 (the total possible number of distinct values) and initialize all the indexes to 0. You would then use the indexes to hold a count for each of possible values, so index 0 would hold the number of times a 2 was rolled, index 1 would hold the number of times a 3 was rolled, etc. Below is an illustration of how it would look.
Index | Value |
---|---|
0 | 2 |
1 | 3 |
2 | 4 |
3 | 5 |
4 | 6 |
5 | 7 |
6 | 8 |
7 | 9 |
8 | 10 |
9 | 11 |
10 | 12 |
Whenever you roll a new value, increment the index that corresponds to that value. For example, if you were to roll a 6, you would increment the value at index 4. When the rolling is finished, each index should contain the number of times the corresponding value was rolled.
Exception Handling
There will be various places where an Exception
may be thrown by the Virtual Machine while executing as well as a few spots where you will need to throw an Exception
manually. Specifically
- If there is ever a time you will need to enforce a specific range of values, you will likely need to validate the given value and throw an
Exception
if the current value is not in range - When getting input from a user, if the wrong type of data is entered, an
Exception
is possible
Bear in mind you do not need to throw every Exception
yourself. Some will be thrown by Java. When and how you handle the Exception
will be for you to determine. Also, please note that if an Exception
is not something that can be handled or fixed while the program is running, it should not be caught and allowed to crash the program.
Some Exceptions
you may end up using would be IllegalStateException
, IllegalArgumentException
, InputMismatchException
, and NumberFormatException
, along with your custom DieNotRolledException
Your program will be expected to generated output that matches the sample output shown below. Note your actual values will differ, but the formatting and error messages should be identical.
Report Formatting
Your report format should match the sample output format exactly, though the values themselves will be different. The spacing and justifying should be handled by formatting the output String
either through the printf()
command or the String.format()
command. You should not attempt to hard-code spacing.
You will use the findMaxIndex()
method to determine what the scale of the report will be. Each asterisk will represent roughly 10% of the max value, so the value with the highest count will have 10 asterisks and the rest will scale down based on the max value, using the following equation to calculate how many asterisks to print for each value:
// scale is how many rolls is 10% of the max
scale = maxNumRolls / 10
// Number of asterisks for a value is the number of rolls divided by the scale
numStars = numRolls / scale
Sample Output
Please enter the number of dice to roll, how many sides the dice have,
and how many rolls to complete, separating the values by a space.
Example: "2 6 1000"
Enter configuration:2 6
Invalid input: Expected 3 values but only received 2
Please enter the number of dice to roll, how many sides the dice have,
and how many rolls to complete, separating the values by a space.
Example: "2 6 1000"
Enter configuration:2 101 10000
Bad die creation: Illegal number of sides: 101
Please enter the number of dice to roll, how many sides the dice have,
and how many rolls to complete, separating the values by a space.
Example: "2 6 1000"
Enter configuration:2 6 fff
Invalid input: All values must be whole numbers.
Please enter the number of dice to roll, how many sides the dice have,
and how many rolls to complete, separating the values by a space.
Example: "2 6 1000"
Enter configuration:3 6 100000
3 :454
4 :1368 *
5 :2757 **
6 :4714 ***
7 :6922 *****
8 :9821 *******
9 :11601 *********
10:12413 *********
11:12555 **********
12:11521 *********
13:9697 *******
14:6856 *****
15:4661 ***
16:2770 **
17:1396 *
18:494
Acknowledgment
This laboratory assignment was developed by Prof. Sean Jones.