A game booth claims its die is fair, but a few rolls cannot prove it. Your challenge is to build repeatable chance experiments, count what happens, and use those counts to estimate answers. By Lesson 3, the same random choices will steer a turtle on a walk that is different from an ordinary polygon.
-
Use
random.randintto roll a whole number andrandom.choiceto pick from a range or string. -
Set a seed to repeat the same sequence of random choices.
-
Put random choices in functions that run many trials and count outcomes.
-
Use those counts to estimate a chance or a value such as π.
-
Lesson 1: Chance
A board game needs a six-sided die. We could type one fixed roll, but then the game would never surprise anyone. Python's
randommodule can choose an integer for us.A die we can test
First, bring in the
randommodule so its tools are available.import randomScroll the code for more ↓
import randommakes the module available; it has not chosen a value yet.Now fix the starting point of the random number recipe with seed 4.
random.seed(4)Scroll the code for more ↓
The same seed restarts the same sequence, which makes debugging and testing repeatable.
Choose one integer from 1 through 6. Both endpoints are possible.
print(random.randint(1, 6))Scroll the code for more ↓
Output
2randint(1, 6)makes one die roll. The next choice continues the seeded sequence.The function below restarts seed 4 and adds several rolls. Predict the total before running this cell.
import random def roll_total(rolls): random.seed(4) total = 0 for roll_number in range(rolls): roll = random.randint(1, 6) total = total + roll return total print(roll_total(6))Scroll the code for more ↓
Output
20The seed comes before the first random choice. Run the cell again: the total repeats because seed 4 restarts the same tested sequence. Change only the seed and the choices can change. During a real game we might not restart the seed inside the function, but seeded functions let this unit's tests compare exact results.
Try real input: number of rolls
This version reads a roll count and uses the function above.
Try it rolls = int(input("How many rolls? ")) print(roll_total(rolls))Scroll the code for more ↓
Choose from a range or a string
random.choice(range(2))chooses either 0 or 1. We can let 0 mean tails and 1 mean heads.random.randint(0, 1)is the everyday tool for choosing between those two integers, whilerandom.choice(range(...))can pick from any supplied run of values.random.choicecan also choose one character from a string.Try a two-character string to make a coin with
Hfor heads andTfor tails.random.seed(4) print(random.choice("HT"))Scroll the code for more ↓
Output
Hchoice("HT")returns one character, eitherHorT. Seed 4 makes this example repeat the same way every time.Now flip with
random.choice(range(2))many times and count how often 1 (heads) appears.import random def count_heads(flips): random.seed(4) heads = 0 for flip_number in range(flips): coin = random.choice(range(2)) if coin == 1: heads = heads + 1 return heads print(count_heads(12))Scroll the code for more ↓
Output
5Use module style: write
import random, then names such asrandom.randintandrandom.choice. In this unit, choose withrandintor withchoiceon a range or string.Dice-and-coin score
Now the game has rounds. Each round rolls a die and flips a coin. Heads adds the roll; tails subtracts the roll. The score must survive from one round to the next, so it is a running total.
import random def chance_score(rounds): random.seed(4) score = 0 for round_number in range(rounds): roll = random.randint(1, 6) coin = random.randint(0, 1) if coin == 1: score = score + roll else: score = score - roll return score print(chance_score(8))Scroll the code for more ↓
Output
8Trace it:
scorestarts once, before the loop. Each round reads the old score and stores the new score. Ifscore = 0were inside the loop, every round would erase the earlier rounds instead of keeping a cumulative score.Lesson 2: Simulate & Estimate
The booth owner says, “Sixes happen about one-sixth of the time.” Instead of arguing from six rolls, we can simulate many trials and count every six.
Count an outcome
A trial is one repeat of an experiment. Here,
totalis an accumulator: it changes only when the condition is true.import random def count_sixes(trials): random.seed(4) total = 0 for trial in range(trials): roll = random.randint(1, 6) if roll == 6: total = total + 1 return total print(count_sixes(60)) print(count_sixes(600))Scroll the code for more ↓
Output
6 87This is count by condition. The loop performs every trial, but
total = total + 1runs only for a six. The larger experiment gives more evidence, although its count is not required to be exactly one-sixth of the trials.Try real input: number of trials
Read a trial count, then count the sixes.
Try it trials = int(input("How many trials? ")) print(count_sixes(trials))Scroll the code for more ↓
Report a percentage
A raw count is hard to compare across experiment sizes. This function turns it into a percentage.
max(trials, 1)keeps the divisor at least 1, andround(..., 1)reports one decimal place.import random def six_percent(trials): random.seed(4) total = 0 for trial in range(trials): roll = random.randint(1, 6) if roll == 6: total = total + 1 safe_trials = max(trials, 1) return round(100 * total / safe_trials, 1) print(six_percent(60)) print(six_percent(600))Scroll the code for more ↓
Output
10.0 14.5A quarter-circle picture for estimating π
Imagine a quarter-circle of radius 1000 inside a 1000-by-1000 square. The curved boundary runs from
(0, 1000)to(1000, 0).y 1000 *------. + outside corner | `. | ) quarter-circle edge | .' 0 +-------* x 0 1000The arc bulges outward, so the quarter-circle covers about 78.5% of the square — that fraction is
π / 4, so multiply by 4. The square's area is1000 * 1000, and the quarter-circle's area isπ * 1000 * 1000 / 4. Count the inside fraction and multiply by 4 to estimate π.First test one fixed point in a quarter-circle of radius 1:
(0.3, 0.4). Compare the sum of its squared coordinates with1 * 1.x = 0.3 y = 0.4 print(x * x + y * y <= 1 * 1)Scroll the code for more ↓
Output
True0.3 * 0.3 + 0.4 * 0.4is at most 1, so this point is inside. The same comparison works when the radius is 1000.For each point, choose
x = random.randint(0, 1000)andy = random.randint(0, 1000). Each axis has 1001 possible integer values, including both 0 and 1000, so do not call this a “1000×1000 grid.” A point is inside whenx*x + y*y <= 1000*1000.import random def estimate_pi(trials): random.seed(4) inside = 0 for trial in range(trials): x = random.randint(0, 1000) y = random.randint(0, 1000) if x * x + y * y <= 1000 * 1000: inside = inside + 1 safe_trials = max(trials, 1) return round(4 * inside / safe_trials, 2) print(estimate_pi(50)) print(estimate_pi(500)) print(estimate_pi(5000))Scroll the code for more ↓
Output
3.12 3.0 3.1The result is an estimate close to π, not exactly π. Expect a value around 3.1, not exactly 3.14159. More trials usually make the estimate steadier, but randomness does not promise that every larger experiment is closer. Seed 4 gives the same result every time.
Lesson 3: Random Turtle Walk
A rescue robot can move a fixed distance, but debris forces it to turn left or right after every step. A regular polygon knows its next turn. This robot must choose. Can we make the route surprising and still make the program testable?
Build the walk as a real program
The walk runs from
assets/l3_random_walk.py, just like the turtle programs in Unit 06. Its step length stays fixed.random.randint(0, 1)chooses a left or right turn. A random walk usually ends away from where it started.Program # Bring in the drawing and random-choice tools. import turtle import random random.seed(4) # Take a fixed step, then randomly choose a left or right turn. step = 28 move_count = 24 turtle.pencolor("darkviolet") turtle.pensize(3) for move_number in range(move_count): turtle.forward(step) turn = random.randint(0, 1) if turn == 0: turtle.left(90) else: turtle.right(90) turtle.done()Scroll the code for more ↓
The real program (
assets/l3_random_walk.py)# Bring in the drawing and random-choice tools. import turtle import random random.seed(4) # Take a fixed step, then randomly choose a left or right turn. step = 28 move_count = 24 turtle.pencolor("darkviolet") turtle.pensize(3) for move_number in range(move_count): turtle.forward(step) turn = random.randint(0, 1) if turn == 0: turtle.left(90) else: turtle.right(90) turtle.done()From this unit directory, run:
assets/l3_random_walk.pyClose the turtle window when you finish observing the route. Change only
move_count, save, and rerun to see how a longer walk extends the same seeded route.step,move_count, andturnhave clear jobs. The turtle always moves with its pen down, so 24 loop trips make 24 drawn segments. Seed 4 makes the left/right choices repeat for testing. The route is intentionally open, unlike Unit 06's closed polygons.Try real input: number of flips
Use the coin-counting function from Lesson 1 with a count entered by a reader.
Try it flips = int(input("How many flips? ")) print(count_heads(flips))Scroll the code for more ↓
Put the ideas together
Random programs still need structure. A function gives an experiment inputs and returns its result. A loop runs the trials. An accumulator remembers a score or count. A condition decides which outcomes count. A fixed seed makes the experiment reproducible while you test it.
-
import randomgives you the module's chance tools. -
random.randint(1, 6)can choose either endpoint;random.choice("HT")picks one character. -
random.seed(4)restarts a sequence so the same experiment repeats. -
A simulation counts many trials; its estimate can get steadier without matching the exact value every time.
You can now build a repeatable dice experiment and a wandering turtle route.
-