Board games need dice, and dice get lost. In this lesson you build an electronic one on the 4-digit 7-segment display from your kit. Press the roll button and the numbers spin faster than your eye can follow, then slow down and stop, just like a real dice tumbling across the table. The second button switches between one dice and two, and the display shows both results and their total.
What you'll learn
- How a 7-segment display draws numbers from seven small LEDs
- How multiplexing shows four digits with only twelve pins
- How to make random numbers with
random()andrandomSeed() - How to slow an animation down step by step
What you need
- UNO R3 board and USB cable (UNO R3 Starter Kit)
- 4-digit 7-segment display, common cathode (UNO R3 Starter Kit)
- 4 resistors, 220 Ω (UNO R3 Starter Kit)
- 2 push buttons (UNO R3 Starter Kit)
- Breadboard and jumper wires (UNO R3 Starter Kit)
Make it real: glue the breadboard into a small box lid and cut a window for the display, so the dice sits on the games table like a real gadget.
Wiring

| From | To |
|---|---|
| Display segments a, b, c, d, e, f, g, dp | UNO pins 2, 3, 4, 5, 6, 7, 8, 9 |
| Display digits D1, D2, D3, D4 | 220 Ω resistor each, then UNO pins 10, 11, 12, 13 |
| Roll button, one leg | UNO pin A0 |
| Mode button, one leg | UNO pin A1 |
| Both buttons, the diagonally opposite leg | GND |
This is the same wiring as the 4-digit stopwatch project, so if you built that, only the sketch changes. Check your display's pin order in its datasheet: most 12-pin displays have digit 1 at the top left.
The sketch
const int SEG_PINS[8] = {2, 3, 4, 5, 6, 7, 8, 9}; // a, b, c, d, e, f, g, dp
const int DIGIT_PINS[4] = {10, 11, 12, 13}; // digits 1 to 4
const int ROLL_PIN = A0;
const int MODE_PIN = A1;
// Segment patterns for 0-9 (bit 0 = a ... bit 6 = g)
const byte NUMBERS[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
const byte BLANK = 0x00, DASH = 0x40;
byte shown[4] = {DASH, DASH, DASH, DASH};
bool twoDice = false;
int dice1 = 0, dice2 = 0;
// Show the four patterns for a few milliseconds each, again and again (multiplexing)
void refresh(unsigned long ms) {
unsigned long start = millis();
while (millis() - start < ms) {
for (int d = 0; d < 4; d++) {
for (int s = 0; s < 8; s++) digitalWrite(SEG_PINS[s], bitRead(shown[d], s));
digitalWrite(DIGIT_PINS[d], LOW); // common cathode: LOW turns the digit on
delay(2);
digitalWrite(DIGIT_PINS[d], HIGH);
}
}
}
void showDice() {
if (twoDice) {
shown[0] = NUMBERS[dice1];
shown[1] = NUMBERS[dice2];
int total = dice1 + dice2;
shown[2] = total >= 10 ? NUMBERS[1] : BLANK;
shown[3] = NUMBERS[total % 10];
} else {
shown[0] = BLANK; shown[1] = BLANK; shown[2] = BLANK;
shown[3] = NUMBERS[dice1];
}
}
void roll() {
int wait = 20;
while (wait < 260) { // spin, slowing down a little each time
dice1 = random(1, 7);
dice2 = random(1, 7);
showDice();
refresh(wait);
wait += wait / 6 + 2;
}
}
void setup() {
for (int s = 0; s < 8; s++) pinMode(SEG_PINS[s], OUTPUT);
for (int d = 0; d < 4; d++) {
pinMode(DIGIT_PINS[d], OUTPUT);
digitalWrite(DIGIT_PINS[d], HIGH); // all digits off
}
pinMode(ROLL_PIN, INPUT_PULLUP);
pinMode(MODE_PIN, INPUT_PULLUP);
randomSeed(analogRead(A5)); // a floating pin gives a different start each time
}
void loop() {
if (digitalRead(ROLL_PIN) == LOW) {
randomSeed(micros()); // the moment you press adds more randomness
roll();
}
if (digitalRead(MODE_PIN) == LOW) {
twoDice = !twoDice;
if (dice1 > 0) showDice();
else for (int d = 0; d < 4; d++) shown[d] = (twoDice || d == 3) ? DASH : BLANK;
while (digitalRead(MODE_PIN) == LOW) refresh(10);
}
refresh(10);
}
How it works
Each digit is eight LEDs: seven segments, called a to g, plus the decimal point. A number is a pattern of segments, stored as one byte: in 0x06, for example, only bits 1 and 2 are set, so only segments b and c light up, which makes a 1.
All four digits share the same eight segment wires, so the sketch switches on one digit at a time, shows its pattern for 2 ms, and moves to the next. That happens 125 times a second, too fast for your eye, so you see all four digits at once. This trick is called multiplexing, and it is why the display has to be refreshed all the time in loop().
random(1, 7) gives a number from 1 to 6. Computers can't really make random numbers, so randomSeed() starts the sequence from something unpredictable: the noise on an unused pin, and the exact microsecond you press the button.
Try this next
- Add a "cheat" mode that only rolls sixes when you hold both buttons. Then remove it again!
- Count how often each number comes up in 600 rolls and print the results. Is your dice fair?
- Make a 1–20 dice for role-playing games.
Troubleshooting
- Some segments never light: check the eight segment wires against your display's pinout.
- Numbers look like strange shapes: two segment wires are swapped. Light one segment at a time to find which.
-
The display flickers: something in
loop()is waiting too long; keep callingrefresh(). -
Nothing lights at all: your display may be common anode. Swap HIGH and LOW for the digit pins and use
!bitRead(...)for the segments.