Functions and Games
Learning Objectives
- You can use a list to represent a roll of five dice.
- You can divide a game rule into small functions and use their returned results in other functions.
- You can test game logic without starting its graphical framework.
- You can distinguish the code you are responsible for from unfamiliar framework code.
A graphical game may react to keys, draw shapes, track rounds, and calculate scores. You can work on the scoring rule without changing the rest of the game. Here, you will write three functions for Dice Combos.
The same roll should always receive the same score. We can write and test that calculation before connecting it to the game.
Representing a Dice Roll
Each roll contains five ordinary six-sided dice, represented by a list:
dice = [2, 5, 2, 1, 2]Each item is an integer from 1 through 6. The scoring code can loop over these values without knowing about coordinates, colors, or keys. Their order does not affect the score; only the largest group of equal values matters. Above, 2 occurs three times, so the largest group has size 3.
Specify the Smallest Rule First
Begin with one focused question:
How many dice show a particular value?
The function boundary is:
Function:
count_value(dice, target)
Parameters: a list of five die values and a target from1through6.
Returns: the number of items indiceequal totarget.
Does not: print or changedice.
For example:
roll = [2, 5, 2, 1, 2]
assert count_value(roll, 2) == 3assert count_value(roll, 5) == 1assert count_value(roll, 6) == 0assert roll == [2, 5, 2, 1, 2]The last assertion checks that the roll is unchanged. Counting selected values is familiar from Part 2; here, a function receives the list and returns the count.
Build a Larger Rule from the Smaller One
The next function answers:
What is the largest number of matching dice in this roll?
Its contract is:
Function:
largest_group_size(dice)
Parameter: a list of five die values.
Returns: the size of the largest group of equal values. The result is from1through5.
Uses:count_valueto count each possible die value.
Does not: print or changedice.
For the roll [2, 5, 2, 1, 2], it should return 3.
This function can call count_value for each possible value and remember the largest answer. A loop through [1, 2, 3, 4, 5, 6] covers every face.
That is function composition:
dice and one target → count_value → one count
dice → largest_group_size → largest count uses count_valueThe loop remembers the largest count, while count_value does each count.
Turn the Group Size into Points
Dice Combos uses this scoring table:
| Largest equal group | Name | Points |
|---|---|---|
| 5 | five of a kind | 50 |
| 4 | four of a kind | 25 |
| 3 | three of a kind | 15 |
| 2 | one or more pairs | 5 |
| 1 | all values different | 0 |
The final function you will write has this contract:
Function:
score_roll(dice)
Parameter: a list of five die values.
Returns: the integer score from the table.
Uses:largest_group_sizerather than implementing the counting rule again.
Does not: print or changedice.
For example, both [3, 3, 3, 5, 5] and [3, 3, 3, 4, 5] score 15. The largest group has size 3 in both rolls. This game has no separate full-house rule.
Together the functions form this chain:
score_roll → largest_group_size → count_valueThe scoring table can change without changing the counting algorithm, while a counting fix benefits both larger functions.
Test One Function and Rule at a Time
Test the smallest function before depending on it in a larger one. Then test the larger functions separately:
assert count_value([2, 5, 2, 1, 2], 2) == 3assert count_value([2, 5, 2, 1, 2], 6) == 0
assert largest_group_size([1, 2, 3, 4, 5]) == 1assert largest_group_size([6, 6, 2, 6, 3]) == 3assert largest_group_size([4, 4, 4, 4, 4]) == 5
assert score_roll([1, 2, 3, 4, 5]) == 0assert score_roll([6, 6, 2, 2, 3]) == 5assert score_roll([3, 3, 3, 5, 5]) == 15assert score_roll([4, 4, 4, 4, 2]) == 25assert score_roll([5, 5, 5, 5, 5]) == 50These cases cover an absent target, all-distinct dice, and every scoring group. If score_roll fails, check largest_group_size, then individual counts. Testing each function and rule helps locate where the first wrong result appears.
Use the ordinary Python editor below to run these checks without opening the game. Copy only the three scoring functions from your exercise solution into it, then add assertions below the definitions. Leave the game framework in the exercise. When the checks pass, copy your finished functions back into the game starter.
How the Rules Connect to the Framework
The complete framework is in the exercise. These excerpts only show how the scoring functions connect to the game:
# Inside largest_group_size:count = count_value(dice, target)
# Inside score_roll:group_size = largest_group_size(dice)
# Inside the provided framework after a new roll:self.roll_score = score_roll(self.dice)The exercise framework also ends with this guarded launch:
if __name__ == "__main__": import random import pyxel
DiceCombosGame()Running the file executes this block and opens the game. Importing it for tests skips the block, so the ordinary functions can be tested without starting Pyxel.
The framework and its launch code are provided. Write the three marked functions; later parts of the course will explain the remaining code.
Suggested Workflow
Work from the smallest responsibility outward:
- implement and test
count_value; - implement and test
largest_group_sizeusing the first function; - implement and test
score_rollusing the second function; - run all of the function tests together;
- start the game and check several displayed rolls against the scoring table.
The function tests use rolls you choose, so you can repeat the same checks after each change.
The exercise provides the Pyxel starter and marks the three functions to complete. Follow the workflow above, then try the game.
Dice combos
0 / 35 points
Complete the scoring rules for Dice Combos. The provided Pyxel framework rolls five dice when the player presses Space, displays the current roll and score, and starts a new game when the player presses R.
Work in the three functions between YOUR CODE STARTS HERE and YOUR CODE ENDS HERE. The framework, random-number code, class, drawing code, and import guard are provided; you do not need to modify them. Keep the framework class and import guard in place so the game can run.
The framework always gives the functions a list of exactly five integers from 1 through 6. The functions do not need to validate that promise. None of the three functions should print anything or change the list it receives.
Implement these functions:
-
count_value(dice, target)returns how many items indiceequaltarget. The selected-count pattern from Part 2 is useful here. -
largest_group_size(dice)returns the size of the largest group of equal values. Callcount_valuefor each possible face and remember the largest count. You can loop through[1, 2, 3, 4, 5, 6]. -
score_roll(dice)callslargest_group_sizeand returns the score from this table:Largest group Points 5 50 4 25 3 15 2 5 1 0
A roll with two pairs still has a largest group of 2 and scores 5. A roll such as [3, 3, 3, 5, 5] has a largest group of 3 and scores 15; this game has no separate full-house rule.
Build the larger rules from the smaller functions. The loops, conditions, parameters, and return values taught so far are enough for all three functions.
Test the functions with the ordinary Python editor on this page before trying the game. Copy only your three functions into that editor and add assertions below them. Once the checks pass, copy the functions back into the game starter and run it.
Explain the Separation
After the game exercise, you should be able to explain this boundary:
- the three functions you wrote decide what a roll means and how many points it earns;
- the framework decides when a roll happens, which random values appear, how the dice are drawn, and how the running total is displayed.
The list holds the five die values that the scoring functions need.
Part 6 will return to framework code like this and explain classes and object state more formally.
Check Your Understanding
- Why is a list a natural representation for the five dice?
- What information enters and leaves
count_value? - Why should
largest_group_sizecallcount_valueinstead of copying its counting loop? - Why can the three scoring functions be tested without starting Pyxel?
- What does the import guard prevent when a test imports the file?
AI Study Aid
Create a chapter diagram
We're looking into to what extent AI-generated diagrams could help with studying.
Use this study aid to generate an AI-generated visual summary of the material you just studied.
Each diagram style emphasizes the content in a different way, so you can choose the focus
that feels most useful.
Using the diagram generator is voluntary and does not affect your course progress. We encourage
you to try it out and see if it helps, but it's totally up to you! Your answers help us understand
how to make better study aids in the future.