Editor

Dice Rolling Simulator in Python

Beginner · Games · about 40 minutes to build · 91 lines

It rolls up to five dice and draws their faces, or rolls thousands of times and shows how often each total comes up.

The program

Press Run and answer its questions in the box that appears under the code.

dice_rolling_simulator.py
"""Dice rolling simulator: roll up to five dice, or roll many times and chart the totals."""
import random
SIDES = 6
MAX_DICE = 5
MAX_ROLLS = 100_000
BAR_WIDTH = 40
# The three rows of pips inside each face, from 1 to 6.
FACES = {
1: (" ", " o ", " "),
2: (" o ", " ", " o "),
3: (" o ", " o ", " o "),
4: (" o o ", " ", " o o "),
5: (" o o ", " o ", " o o "),
6: (" o o ", " o o ", " o o "),
}
def ask_number(prompt, low, high):
"""Ask until the user types a whole number from low to high."""
while True:
text = input(prompt).strip().replace(",", "")
if text.isdecimal() and low <= int(text) <= high:
return int(text)
print(f" Please type a whole number from {low} to {high}.")
def roll_dice(count):
"""Roll count dice and return the values as a list."""
return [random.randint(1, SIDES) for _ in range(count)]
def draw_dice(values):
"""Print the dice side by side, one face per die."""
edge = " ".join("+-------+" for _ in values)
print(edge)
for row in range(3):
print(" ".join(f"|{FACES[value][row]}|" for value in values))
print(edge)
def roll_and_show():
"""Roll the number of dice the user asks for and draw them."""
count = ask_number(f"How many dice? (1-{MAX_DICE}): ", 1, MAX_DICE)
values = roll_dice(count)
draw_dice(values)
print(f"You rolled {', '.join(map(str, values))}. Total: {sum(values)}")
def chart_totals():
"""Roll many times, count each total and print a bar chart."""
count = ask_number(f"How many dice? (1-{MAX_DICE}): ", 1, MAX_DICE)
rolls = ask_number(f"How many rolls? (1-{MAX_ROLLS:,}): ", 1, MAX_ROLLS)
# Start every possible total at zero so totals never rolled still show.
totals = {total: 0 for total in range(count, count * SIDES + 1)}
for _ in range(rolls):
totals[sum(roll_dice(count))] += 1
biggest = max(totals.values())
print(f"\n{'Total':>5} {'Count':>6} {'Share':>6}")
for total, times in totals.items():
bar = "#" * round(times / biggest * BAR_WIDTH)
print(f"{total:>5} {times:>6} {times / rolls:>6.1%} {bar}")
most_common = max(totals, key=totals.get)
print(f"Most common total: {most_common}")
def main():
"""Show the menu until the user chooses to quit."""
print("=== Dice Rolling Simulator ===")
while True:
print("\n1. Roll the dice")
print("2. Roll many times and chart the totals")
print("3. Quit")
choice = input("Choose 1, 2 or 3: ").strip()
if choice == "1":
roll_and_show()
elif choice == "2":
chart_totals()
elif choice == "3":
print("Goodbye.")
break
else:
print(" Please type 1, 2 or 3.")
if __name__ == "__main__":
main()

Open it in the full editor to save it, share it and keep building.

Sample run

What the program printed, and what was typed (in yellow).

=== Dice Rolling Simulator ===

1. Roll the dice
2. Roll many times and chart the totals
3. Quit
Choose 1, 2 or 3: 1
How many dice? (1-5): 2
+-------+  +-------+
| o     |  | o     |
|   o   |  |       |
|     o |  |     o |
+-------+  +-------+
You rolled 3, 2. Total: 5

1. Roll the dice
2. Roll many times and chart the totals
3. Quit
Choose 1, 2 or 3: 1
How many dice? (1-5): three
  Please type a whole number from 1 to 5.
How many dice? (1-5): 3
+-------+  +-------+  +-------+
| o   o |  | o   o |  |       |
|       |  | o   o |  |   o   |
| o   o |  | o   o |  |       |
+-------+  +-------+  +-------+
You rolled 4, 6, 1. Total: 11

1. Roll the dice
2. Roll many times and chart the totals
3. Quit
Choose 1, 2 or 3: 2
How many dice? (1-5): 2
How many rolls? (1-100,000): 10,000

Total   Count   Share
    2     299    3.0%  #######
    3     559    5.6%  #############
    4     818    8.2%  ###################
    5    1110   11.1%  ##########################
    6    1411   14.1%  #################################
    7    1703   17.0%  ########################################
    8    1330   13.3%  ###############################
    9    1169   11.7%  ###########################
   10     783    7.8%  ##################
   11     532    5.3%  ############
   12     286    2.9%  #######
Most common total: 7

1. Roll the dice
2. Roll many times and chart the totals
3. Quit
Choose 1, 2 or 3: 3
Goodbye.

How it is built

1. Dice faces as text

Each face is three rows of seven characters, with o for a pip. Drawing a die means printing its three rows between two edges.

FACES = {
    1: ("       ", "   o   ", "       "),
    2: (" o     ", "       ", "     o "),
    3: (" o     ", "   o   ", "     o "),
    4: (" o   o ", "       ", " o   o "),
    5: (" o   o ", "   o   ", " o   o "),
    6: (" o   o ", " o   o ", " o   o "),
}

2. Reading a number

Commas are removed first, so 10,000 works. isdecimal() checks that what is left is all digits before int() converts it, so letters and negative numbers are asked again instead of crashing the program.

def ask_number(prompt, low, high):
    """Ask until the user types a whole number from low to high."""
    while True:
        text = input(prompt).strip().replace(",", "")
        if text.isdecimal() and low <= int(text) <= high:
            return int(text)
        print(f"  Please type a whole number from {low} to {high}.")

3. Drawing dice side by side

To put dice next to each other, the program prints the top row of every die on one line, then the middle rows, then the bottom rows. " ".join(...) puts two spaces between the dice.

def draw_dice(values):
    """Print the dice side by side, one face per die."""
    edge = "  ".join("+-------+" for _ in values)
    print(edge)
    for row in range(3):
        print("  ".join(f"|{FACES[value][row]}|" for value in values))
    print(edge)

4. Counting thousands of rolls

The dictionary starts every possible total at zero, so a total that never comes up still gets a row. Each bar is scaled against the most common total, and {times / rolls:>6.1%} prints the share as a percentage.

def chart_totals():
    """Roll many times, count each total and print a bar chart."""
    count = ask_number(f"How many dice? (1-{MAX_DICE}): ", 1, MAX_DICE)
    rolls = ask_number(f"How many rolls? (1-{MAX_ROLLS:,}): ", 1, MAX_ROLLS)

    # Start every possible total at zero so totals never rolled still show.
    totals = {total: 0 for total in range(count, count * SIDES + 1)}
    for _ in range(rolls):
        totals[sum(roll_dice(count))] += 1

    biggest = max(totals.values())
    print(f"\n{'Total':>5}  {'Count':>6}  {'Share':>6}")
    for total, times in totals.items():
        bar = "#" * round(times / biggest * BAR_WIDTH)
        print(f"{total:>5}  {times:>6}  {times / rolls:>6.1%}  {bar}")
    most_common = max(totals, key=totals.get)
    print(f"Most common total: {most_common}")

5. The menu

The menu repeats until the user picks 3. Each choice calls one function, which keeps main() short.

def main():
    """Show the menu until the user chooses to quit."""
    print("=== Dice Rolling Simulator ===")
    while True:
        print("\n1. Roll the dice")
        print("2. Roll many times and chart the totals")
        print("3. Quit")
        choice = input("Choose 1, 2 or 3: ").strip()
        if choice == "1":
            roll_and_show()
        elif choice == "2":
            chart_totals()
        elif choice == "3":
            print("Goodbye.")
            break
        else:
            print("  Please type 1, 2 or 3.")

Make it bigger

  • Ask how many sides the dice have, and print the values as numbers when there is no picture for them.
  • Roll two dice until you get a double and count how many rolls it took.
  • Print the exact chance of each total next to the chart: with two dice, 6 of the 36 combinations make 7.
  • Add a scoring game: roll five dice and score points for pairs, three of a kind and a full house.

What it practises