This page contains exercise answers and teaching guidance for
Step 6 — Functions.
Not linked from the student pages.
Students: please go back and try the activities first.
def and a parameter listdef draw_snake(surface, snake):
"""Draw every body segment; head is darker green."""
for i, (col, row) in enumerate(snake):
colour = DKGREEN if i == 0 else GREEN
rect = (col * CELL_SIZE, row * CELL_SIZE, CELL_SIZE - 1, CELL_SIZE - 1)
pygame.draw.rect(surface, colour, rect)
def draw_food(surface, food_x, food_y):
"""Draw the food square."""
rect = (food_x * CELL_SIZE, food_y * CELL_SIZE, CELL_SIZE - 1, CELL_SIZE - 1)
pygame.draw.rect(surface, RED, rect)
def check_wall_collision(hx, hy):
"""Return True if the head is outside grid boundaries."""
return hx < 0 or hx >= GRID_COLS or hy < 0 or hy >= GRID_ROWS
# ── Main loop — clean and readable ──
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill(BG)
draw_snake(screen, snake)
draw_food(screen, food_x, food_y)
pygame.display.flip()
clock.tick(8)
hx, hy = snake[0]
if check_wall_collision(hx, hy) or snake[0] in snake[1:]:
running = False
def function_name(params):Defines the function. The body is indented below.
surface and snake are parameters (placeholders in the definition); screen and snake (the actual list) are arguments passed at the call.
Drawing code was scattered through the loop. Functions give it a name — draw_snake() tells you WHAT it does without reading HOW.
enumerate(snake)Yields (index, value) pairs — lets us colour the head (index 0) differently.
"""..."""The string immediately after def is Python’s built-in documentation mechanism.
return valuecheck_wall_collision returns True or False so the caller can decide what to do.
| Question | Model Answer |
|---|---|
| What keyword defines a function in Python? | def |
| What is the DRY principle? | Don’t Repeat Yourself — if you write the same code more than once, put it in a function. |
| Difference between parameter and argument? | Parameter = name in the definition (placeholder); argument = actual value passed at the call. |
What does enumerate(snake) return? |
Pairs of (index, value) for each item — e.g. (0, (10, 7)), (1, (9, 7)). |
def draw_snake(snake): (missing surface parameter), then draw_snake(screen, snake) at call site.
Error: TypeError: draw_snake() takes 1 positional argument but 2 were given
Fix: def draw_snake(surface, snake):
Add draw_score(surface, score) that renders the score as text.
def draw_score(surface, score):
font = pygame.font.SysFont("monospace", 20)
text = font.render(f"Score: {score}", True, WHITE)
surface.blit(text, (8, 8))
# In main loop after screen.fill():
draw_score(screen, score)
Create game_over(surface) that displays “GAME OVER” centred and waits 2 seconds.
def game_over(surface):
font = pygame.font.SysFont("monospace", 36, bold=True)
msg = font.render("GAME OVER", True, RED)
rect = msg.get_rect(center=(WINDOW_W // 2, WINDOW_H // 2))
surface.blit(msg, rect)
pygame.display.flip()
pygame.time.wait(2000)
# After running = False:
game_over(screen)
| Prompt | Key ideas a strong answer contains |
|---|---|
| 1. Why use functions? | Avoids repeated code; gives it a readable name; makes main loop shorter; allows reuse. |
| 2. What is scope? | The region where a variable exists. Local = inside the function. Global = outside all functions. |
| 3. When would a function return a value? | When the caller needs a result — e.g. check_wall_collision() returns True/False for the caller to act on. |
| 4. What is a docstring? | A triple-quoted string immediately after def — Python’s built-in documentation. |
| 5. Explain DRY | “If you write the same code twice, you have to fix bugs twice. Functions mean you fix it once.” |
| What they did | What they see | What to say |
|---|---|---|
| Forgot to call the function | Code in function never runs | “Defining creates it; calling runs it. Check you have draw_snake(screen, snake) in the loop.” |
Modified global variable inside function without global |
Change doesn’t persist after function returns | “Variables inside a function are local. To modify a global, add global variable_name at the top of the function.” |
| Called function before defining it | NameError: name 'draw_snake' is not defined |
“Python reads top to bottom. Define functions before the loop that calls them.” |
| Wrong argument order | Wrong positions / crash | “Arguments match parameter order. draw_snake(screen, snake) matches def draw_snake(surface, snake).” |
Used print() thinking it returns the value |
Function returns None |
“print() shows output; return gives a value back to the caller. They’re different.” |
Display the Step 5 loop (messy, long) next to the Step 6 loop (short, readable). Ask: “Which is easier to read and debug?” The visual difference makes DRY concrete without explanation.
A function is a recipe. Write it once; follow it as many times as needed. The ingredient list = parameters; making the dish = calling the function.
Demonstrate: define x = 5 inside a function, then try to print x outside it → NameError. Local variables exist only while the function runs.
Functions hide complexity behind a name. Ask: “Now that we have draw_snake(), do you need to know HOW it draws to use it in the loop?” This is abstraction.
This step is mostly refactoring — no new visual features. Students who expect to see something change may feel disappointed. Help them see the value in code organisation: “Clean code is a gift to your future self.”
These 5 questions appear in the activity page after Tier 4 (post-calibration gate). Pass mark is 4 of 5 (80%). Students who fail may retry; the system records attempts and final score in Google Sheets.
| Question (displayed to student) | Correct Answer |
|---|---|
| Q1: def draw_snake(body): — what is body in this line? | ✓ A parameter — a value passed in when the function is called |
| Q2: What does a function return when it has no return statement? | ✓ None |
| Q3: Why call draw_snake(body) instead of pasting drawing code everywhere? | ✓ To keep the code DRY — reuse logic without repeating it |
| Q4: What is variable scope? | ✓ The region of code where a variable can be read or written |
| Q5: def is_collision(head, body): return head in body — return type? | ✓ True or False (bool) |
Recorded in Google Sheet (Act_6 tab):
concept_q1–concept_q5 (student’s 0-based answer index),
concept_score_pct, concept_passed (1 = pass, 0 = fail),
concept_attempts (retry count).
Every submission to this step writes one row to the Act_6 tab in the research spreadsheet. All 13 tabs (Student_Reg, Pre_Test, Post_Test, Act_1–Act_10) share the same student identity columns.
| Column | Description |
|---|---|
| STUDENT IDENTITY (10 fields) | |
matric | Matric / student ID |
name | Full name |
gender | Gender (Female / Male / Other) |
age | Age in years |
mykid | MyKid / IC number |
home_state | Home state in Malaysia |
class | Class or cohort code |
school_code | School or programme code |
phone | Phone number |
email | Email address |
| SUBMISSION | |
step | Step number (6) |
submitted_iso | KL timestamp (UTC+8, ISO 8601) |
| PRE-CALIBRATION | |
cal_confidence | Self-confidence before activity (1–5 scale) |
cal_predicted | Predicted score before activity (%) |
cal_reflection | Free-text: what will be hard? |
| ACTIVITY TIERS | |
t1_score_pct | Tier 1 Fill-in-Blanks score (%) |
t2_attempts | Tier 2 Debug — number of attempts |
refl2_text | Tier 2 reflection free text |
t3_attempts | Tier 3 Complete-Code attempts |
t4_attempts | Tier 4 New Task attempts |
| CONCEPT CHECK | |
concept_q1–concept_q5 | Student answer index (0-based) per question |
concept_score_pct | Percentage correct (0–100) |
concept_passed | 1 = passed (≥80%), 0 = failed |
concept_attempts | Total retries |
| REFLECTIVE JOURNAL | |
jr1–jr5 | Journal prompts 1–5 free-text responses |
| POST-CALIBRATION | |
post_confidence | Confidence rating after activity (1–5) |
post_actual | Self-reported actual score (%) |
post_r1 | Reflection: how accurate was the prediction? |
post_r2 | Reflection: what would you do differently? |
calibration_index | post_actual − cal_predicted (negative = overconfident) |