Schedule‎ > ‎

### 08A: Random Numbers and Designing with Functions

• Questions from last class?
• How many people brought their dice setup from the lab?
• What is a long data type?

^ top

## Random Numbers

 Learner Outcomes At the end of the lesson the student will be able to: Write code that generates random numbers Write code to seed the random number generator Write code to simulate dice

^ top

### Generating Random Numbers

• Randomness is an important part of many computer and electronics projects, like:
• Cryptography in many areas including generating passwords
• Simulation of unpredictable real phenomena
• Random numbers in games of chance like dice rolling
• Random shuffling of the audio files in an audio player
• To create randomness in computers, we use random numbers
• Random numbers are a series of numbers whose future values cannot be predicted
• The Arduino library, like most C/C++ libraries, has a random number generator named `random()`
• The syntax for calling the function is:
```random(max)
random(min, max)
```
• Where:
• min: lower bound of the random value, inclusive (optional)
• max: upper bound of the random value, exclusive
• For example:
```int randNumber = random(10, 20); // returns number between 10 and 19
```

#### Pseudorandom

• The numbers produced by the library appear to be random but are not
• We call these types of random numbers pseudorandom
• Pseudorandom means that given an initial starting condition, the procedure always produces the same result
• The following program uses `random()` to produce the same output every time it runs
• The reason that the numbers are the same is because the numbers are generated with the same computer commands every time it is called
• When running the following program, remember the first few numbers and then start the program again by reopening the Serial Monitor
• Notice that the same sequence of numbers is produced

#### Example Program Using `random()`

 ```1 2 3 4 5 6 7 8 9 ``` ```#include using namespace std;void setup() { Serial.begin(9600); cout << "0-9 10-19" << endl;}void loop() { long randNumber = random(10); // 0-9 long randNumber2 = random(10, 20); // 10-19 cout << randNumber << " and " << randNumber2 << endl; delay(1500);} ```

#### Check Yourself

1. A number whose value cannot be predicted ahead of time is known as a ________ number.
2. The problem with this random number generator from xkcd is that ________.
1. dice rolling is not a fair way to get random numbers
2. it was not selected randomly
3. you can predict the number ahead of time
4. nothing is wrong
3. The function `random(10)` returns a number between ________ and ________.

^ top

### Seeding the Random Generator

• When running programs we do not always want the same sequence of numbers every time
• For instance, if we run a dice simulation for a game we want different numbers every time the program runs
• To get a different number, we must "seed" the random number generator
• We set the seed with the `randomSeed()` function with the syntax:
```randomSeed(seed)
```
• Where:
• seed: the initial number for the random sequence
• For example:
```randomSeed(seed);
```
• If we change the `seed` value, we will get different numbers every time

#### Changing the Starting Value

• One common strategy for changing the seed value is to read the current value of an unused analog pin
• If the pin is unused, the value on the pin is noise and is different every time it is read:
`randomSeed(analogRead(0));`
• The expression `analogRead(0)` returns a "random" number between 0 and 1023, assuming pin 0 is not connected to any circuit
• We only need to call `randomSeed()` once in a program

#### Example Program Using `randomSeed()`

 ```1 2 3 4 5 6 7 8 9 10 ``` ```#include using namespace std;void setup() { Serial.begin(9600); cout << "0-9 10-19" << endl; randomSeed(analogRead(0));}void loop() { long randNumber = random(10); // 0-9 long randNumber2 = random(10, 20); // 10-19 cout << randNumber << " and " << randNumber2 << endl; delay(1500);} ```

#### Check Yourself

1. The function that sets the starting location, or seed, for `random()` is ________.
2. To produce a new random seed for a program starts use the code: ________.
3. True or false: you must reseed the random number generator every time before calling `random()`.

^ top

### Simulating Dice

• A simulation is an imitation of some real thing or process
• We create a simulation of randomness in a computer program by generating random numbers
• One simple random simulation we can do is a pair of dice

#### Setting the Range

• We need a number between 1 and 6, so we call the `random()` function like:
```long die = random(1, 7);
```
• The reason for the number 7 is that the `max` parameter is exclusive
• Another way to accomplish the same result is:
```long die = random(6) + 1;
```
• In this second version, `random(6)` returns a value between 0 and 5
• We add one to shift the value returned up by one, producing 1 through 6
• We explore simulating the rolling of dice in the next exercise

#### Check Yourself

What code do you write to get the following integer random numbers, including the end points?

1. A random number between 0 and 5. ________
2. A random number between 1 and 6. ________
3. A random number between 1 and 10. ________
4. A random number between -10 and 10. ________

^ top

### Exercise 1: Getting Random (5m)

In this exercise we explore how to generate random numbers by simulating dice.

#### Parts

• Arduino board
• USB cable

#### Specifications

1. Start the Arduino IDE with a new sketch and save the program as `twodice`.
2. Random numbers are generated by using the `random()` function. In the `loop()` function, declare two long integer variables, `die1` and `die2`, and assign them values returned by the `random()` function using code like the following:
```  long die1 = random(1, 7);  long die2 = random(6) + 1;  cout << "You rolled a " << die1 << " and a " << die2 << endl;  delay(1500);
```

For more information, see section the section above on Generating Random Numbers.

Notice that every time you run the program you get the same numbers.

5. Ask the user how many dice they want to roll (from 1 to 10).  Using a loop roll that many dice and print out the results.
6. Your results should look like this:
7. How many dice do you want to roll (1-10)?:
Dice  1 is a 5
Dice  2 is a 1
Dice  3 is a 5
Dice  4 is a 1
Dice  5 is a 2
Dice  6 is a 4
Dice  7 is a 2
Dice  8 is a 1
Dice  9 is a 1
Dice  10 is a 4

8. Verify your code and view it in the Serial Monitor to make sure it works correctly.

If you have problems, ask a classmate or the instructor for help.

9. Save your `twodice.ino` file to submit to Canvas.

^ top

### Summary

• In this section we explored the use of random numbers
• Random numbers are a series of numbers whose future values cannot be predicted
• We computed random numbers by calling the Arduino function named `random()`
• Calling random() will produce the same numbers every time the program runs unless we seed the random number generator
• We set the seed with the `randomSeed()` function
• We used these functions to simulate the rolling of a die as shown below

#### Example Program Simulating Rolling Dice

 ```1 2 3 4 5 6 7 8 9 10 11 ``` ```void setup() { Serial.begin(9600); randomSeed(analogRead(0));}void loop() { long die1 = random(1, 7); long die2 = random(6) + 1; cout << "You rolled a " << die1 << " and a " << die2 << endl; delay(1500);} ```

^ top

## Designing with Functions

 Learner Outcomes At the end of the lesson the student will be able to: Describe the activity of programming Develop algorithms to solve simple computational problems Use stepwise refinement to create algorithms Write functions following the black-box analogy

^ top

### Computational Problem Solving

• Programming is about developing a list of instructions for a computer to follow in solving a problem
• We could try to enter our instructions to the computer first thing
• However, software engineers have learned from experience that it is often better to do some preparatory work first
• In general, we should develop programs in two phases as shown below

#### Algorithms

• The output of the problem-solving phase is an algorithm
• An algorithm is a sequence of precise set of instructions on how to accomplish a task
• We use algorithms in our daily lives like:
• Shampooing hair: lather, rinse, repeat
• Calling someone on the phone
• The easiest or most efficient way to get to school
• Recipes for cooking
• Many math operations such as adding numbers with digits in multiple columns
• A large part of this course is developing algorithms for computers
• Algorithms are the instructions or steps to get from the inputs to the output
• We can use functions to help us develop algorithms
• Functions provide a way to group the steps of a complex algorithm
• Functions take input data like numbers, words, etc. and return an output
• Since functions follow the same input, computation, output sequence as programs, we use algorithms at multiple levels
• Algorithms at a high level may call a series of functions
• Algorithms at a lower level may be stated within a function

#### Check Yourself

1. A sequence of precise instructions to accomplish a task is called a(n) ________.
2. The two phases of program design are the problem solving phase followed by the ________ phase.
3. The output of the problem solving phase is a(n) ________.
4. Why is the problem-solving phase important?

^ top

### Stepwise Refinement

• As programs get larger, they become harder to design
• In this course, we are starting to develop more complex programs
• If we look at a particular problem, it may seem impossible to solve because of the complexity
• For example, the design of the following programs are not immediately obvious:
• a program to do your taxes
• a program to print numbers on a check as words
```One thousand two hundred thirty four dollars
```
• a program to produce a barcode
• a video game like 2048
• an electronic device to replace dice
• Before we start working on a program like these, we need a plan
• One commonly used and powerful technique to develop a plan is called stepwise refinement (also called top-down design or functional decomposition )
• We use stepwise refinement by first describing the general functions of a program
• When a task is complex or difficult, we break it down into simpler subtasks
• We keep breaking down the subtasks until we are left with tasks we know how to solve
• Here is a diagram of the process:

• In algorithmic form:
1. From a high level view, list the steps for solving the problem
2. For each step that is too complex to implement, break it down into subtasks
3. Repeat step 2 until all tasks are simple enough to solve easily
4. Review, simplify and test the design
• We will look at an example of top-down design in the following sections

#### Check Yourself

1. True or false: every computer program is easy to develop.
2. Breaking down a large problem into smaller problems is known as top-down design, functional decomposition, or ________.
3. You should stop decomposing a problem when ________.
1. you are tired
2. you know how to solve each task
3. you are about three levels down from the top
4. you feel ready to write some code

^ top

## Exercise 2:  Electronic Dice

In this lab you develop a breadboarded circuit for an electronic die (singular of dice) that you will use later.

#### Specifications:

1. Gather the parts listed in the Parts List below.
3. Start with a new sketch and save the program as `dice_test`.
4. Copy the Test Code code below and paste it into the `dice_test` sketch.
5. Compile the sketch to verify you copied the starter code correctly.
6. Upload the sketch and verify that all the LEDs are blinking, correcting any problems you find.
7. Check the button circuit by pressing the pushbutton and verifying the LEDS stop blinking while the button is pressed.
8. Submit your `dice_test.ino` file as part of this lab.

#### Parts List

• Arduino board
• USB cable
• 7x LEDs
• 7x 560 Ohm resistors
• 1x pushbutton
• Jumper Wires

2. First layout the LEDs as shown in the image to the right.
3. Add 560 Ohm resistors connecting each of the shorter pins (negative) to GND on the breadboard.
4. Connect a pushbutton up to another part of the breadboard (look at the LED pushbutton project to see how to do that). Use pin 8.
5. Connect up the 5V and GND rails of the breadboard to the correct pins on the LED.
6. Connect the LEDs to Arduino pins 1 - 7 using the following order:
 4 1 5 7 2 6 3
7. Check your circuit breadboard against the image below or against the Fritzing project: dice.fzz.

#### Dice Test Code

 ```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ``` ```const int BUTTON_PIN = 8; const int LED_PINS[] = {1, 2, 3, 4, 5, 6, 7}; void setup() { pinMode(BUTTON_PIN, INPUT_PULLUP); for (int i = 0; i < 7; i++) { pinMode(LED_PINS[i], OUTPUT); } } void loop() { int buttonState = digitalRead(BUTTON_PIN); if (buttonState == HIGH) { for (int i = 0; i < 7; i++) { digitalWrite(LED_PINS[i], HIGH); } delay(500); for (int i = 0; i < 7; i++) { digitalWrite(LED_PINS[i], LOW); } delay(500); } } ```

#### Why Seven LEDs?

• One question that might arise is why we need seven LEDs
• Look at the layout of all six dice patterns shown to the right
• Notice that three of the dice patterns have a center spot (pip): one, three, five
• Five of the dice patterns have pips on the outer edges
• The minimal number of pips to cover all six patterns is seven
• Thus we will need to position seven LEDs

#### Lab Self-Test

Be prepared to answer the following questions after completing this lab:

1. The number of LEDs in the dice project is ________.
2. Why would you want this number of LEDs?
3. The code that checks the state of the button is ________.
1. `digitalRead(BUTTON_PIN)`
2. `digitalWrite(LED_PINS[i], HIGH)`
3. `digitalWrite(LED_PINS[i], LOW)`
4. `pinMode(BUTTON_PIN, INPUT_PULLUP)`
4. True or false: the Arduino digital pin 3 is connected to the LED of that same number.
5. True or false: other digital pins could be connected to the LEDs and be made to work just as well with changes to the code.

^ top

### Pseudocode

• Oftentimes when we work on a problem we want to think with a broad overall view or perspective
• We do not want to be bogged down with details
• However, we still need to record our thinking about the algorithm we are developing
• One way to avoid trivial details until needed is using pseudocode
• pseudocode is an informal high-level description of an algorithm
• With pseudocode we explain our algorithm in English, or whatever language in which we normally like to think
• We can get detailed when necessary with our descriptions in pseudocode
• At the same time, we do not need to worry about matching braces or missing semicolons

#### Electronic Dice Psuedocode

```if the button is pressed then roll dice

roll dice
get random number
show the die face
```

#### Working with Psuedocode

• Once we have worked out the basic psuedocode we enter it into our editor as comments
• We notice that "roll dice" is a separate part of the code so we create a function for that code
• We look at each step so far and continue to breakdown the steps that are too complex to easily implement
• Are there any steps that need more breakdown?
• If the breakdown is complicated, we might assign that to a function

#### Sketch with Pseudocode

```void setup() {

}

void loop() {
//if the button is pressed then roll dice

}

//roll dice
//  get random number
//  show die face of random number

//show die face of random number
//  Turn off all the LEDs
//  for any number turn on the correct LEDs (more detail when actually coded)
```

#### Testing the Algorithm

• The last step of the problem-solving phase is to test the algorithm
• To test the algorithm we draw up a table of variables and outputs from the algorithm
• Then we work through the algorithm and compare the output with what we expected
• As an example in our pseudocoded algorithm, we have variables for a random number and LED pips
• If we choose the random number as 3 then we would expect the LEDs 1, 6 and 7 to be lit from the following layout:  4 1 5 7 2 6 3

#### Check Yourself

1. To informally describe an algorithm we use ________.
2. True or false: pseudocode requires very precise descriptions.
3. For a dice roll of 5, the LEDs lit would be ________.
1. 1, 3, 4, 6, 7
2. 1, 3, 4, 6
3. 1, 2, 3, 4, 5, 6
4. 1, 3, 5, 6, 7

#### Try It: Refine and Test the Algorithm (5m)

1. Start the Arduino IDE, copy the starter code above and paste it into the main IDE window.
2. Save the project using the name dice (`File > Save As...`) to a convenient location like the Desktop or the Arduino projects folder.
3. Compile the sketch to verify you copied the starter code correctly.

When compiling is successful, you will see a message at the bottom of the source code window saying, "Done compiling."

4. Take a few minutes to manually test the design by tracing variables and type in any more psuedocode that seems appropriate.
5. If you have problems, ask a classmate or the instructor for help.

^ top

### Designing Functions

• After testing our pseudocode algorithm, it is time to implement the basic program structure
• We start by writing function stubs

Function stub: a minimal set of code to act as a placeholder for a function

• Thus we write the function signature and add curly braces
• If a return value is needed, we return a dummy value
• As a hypothetical example, consider if we decided to have a function to return the sum of random dice
• For the function, we would write a stub like:
```int getDiceSum(int numDice) {
return 1; // dummy value
}
```
• Stubs allows us to design and code a high-level structure without worrying about the implementation details

#### Functions as Black Boxes

• Whenever we develop a function, it is important to design it as a black box

Black box: a technical term for a device, system or object viewed in terms of its input and output without knowledge of its internal workings.

• Here is a diagram of the concept:

• A black box is something that we know how to use but not how it operates
• An example might be a cell phone or an iPod
• These devices have controls that we know how to operate
• However, we really do not know their internal workings
• A function has a specific job to do and should be designed like a black box
• We know what inputs to give it and the outputs it will produce, but do not have to know about its internal workings

#### Function Comment Blocks

• An important technique for providing information about the inputs and outputs of a function is the comment block
• A function comment block is a description of:
• What the function does
• The purpose of each parameter
• What the function returns
• For example, here is a possible comment block for our hypothetical function:
```/**
Returns the sum of a number of dice rolled.

@param numDice The number of dice to roll.
@return The sum of all the dice rolled.
*/
int getDiceSum(int numDice);
```
• A function signature with a comment block should tell the programmer all the information needed to use the function
• However, the function comment block should not describe how the function does its task
• The format of the function comment block is shown in How To Document and Organize Your Arduino Code
• The comments, along with the signature, allow a programmer to use the function
• With this information, there is no need to study the statements inside the function
• This allows the programmer to keep fewer details in mind while solving a problem

#### Check Yourself

1. A function with just enough code to allow the function to compile is known as a ________.
2. True or false: we add function stubs to our code as a placeholder until we complete the function.
3. When we look at a device in terms of input and output, but do not know its internal workings, we call the device a ________.
4. True or false: function comment blocks are an important part of the function design.

^ top

### Exercise 3: Create Function Stubs and Comment Blocks (5m)

#### Specifications

2. A Function Stub is a function that doesn't do anything yet.  Like this:

int rollDice(int numRolls)  {
//do nothing for now
return 0;
}

3. Write function stubs and comment blocks for at least the two functions that:
• roll dice
• show die face
4. In the comment block for both functions, state the purpose of the function, but not how it operates.
5. Clearly specify any parameters of the functions and describe them in the comment block.
6. Clearly identify any value a function returns in the comment block.
7. Compile the sketch to verify the syntax is correct.
8. Save your dice.ino and turn it into Canvas.

### Exercise 4:  Finish programming the dice program (dice_complete.ino)

1. Save your dice.ino from 08A Exercise 3 as dice_complete.ino
2. Add code to your roll dice function and your show dice face functions so they will run and light up the proper LEDs.
3. Add the calls to your roll dice function and your show dice face functions when the user presses the button.
5. Submit your dice_complete.ino to Canvas.

^ top

### Summary

• Programs are best developed in two phases:
1. Problem-solving phase
2. Implementation phase
• The output of the first phase is an algorithm
• An algorithm is a sequence of precise set of instructions on how to accomplish a task
• Stepwise refinement, A.K.A. top-down design, is a technique for creating algorithms
• Then you break down each subtask into smaller subtasks as needed
• Eventually, the tasks are so trivial that they are easy to code
• We applied stepwise refinement to the problem of electronic dice
• Remember that we write functions for these reasons:
1. To organize our code into modules
2. To reduce repeated code
3. To allow for code reuse in another program
• To help us reach these goals we design our functions as black boxes
• A black box refers to something that we know how to use, but not how it operates
• A programmer who uses a function needs to know what the function does, not how it does it
• We want to write functions so that the function declaration and block comments are all a programmer needs to use the function

^ top

## Wrap Up and Reminders

• For the next homework, see the schedule