Blame
|
1 | <!-- Generated from applied-computing-au vic/unit3-4/sat/C06-2026/C06-Reference-Godot — do not hand-edit; re-run the port. --> |
||||||
| 2 | # Control Structures — GDScript |
|||||||
| 3 | ||||||||
| 4 | ||||||||
| 5 | **Skill codes on this page** |
|||||||
| 6 | ||||||||
| 7 | | Code | Level | Skill | |
|||||||
| 8 | |---|---|---| |
|||||||
| 9 | | C625 | 3–4 | control structure — sequence | |
|||||||
| 10 | | C626 | 3–4 | control structure — selection | |
|||||||
| 11 | | C632 | 5–6 | control structure — iteration / repetition | |
|||||||
| 12 | ||||||||
| 13 | ## C625 — Sequence |
|||||||
| 14 | ||||||||
| 15 | **Definition.** A set of instructions that executes line by line in the order that it is written. |
|||||||
| 16 | ||||||||
| 17 | Minimum two lines whose order matters — label the start and end: |
|||||||
| 18 | ||||||||
| 19 | ```gdscript |
|||||||
| 20 | # C625 sequence: start |
|||||||
| 21 | var zone: int = int($ZoneInput.text) |
|||||||
| 22 | var fare: float = FARE_TABLE[zone] |
|||||||
| 23 | balance -= fare |
|||||||
| 24 | $BalanceLabel.text = "Balance: $%.2f" % balance |
|||||||
| 25 | # C625 sequence: end |
|||||||
| 26 | ``` |
|||||||
| 27 | ||||||||
| 28 | **Earns the tick:** a labelled block that breaks if you swap two lines. **Doesn't:** one isolated statement (that's C611). |
|||||||
| 29 | ||||||||
| 30 | **In connect-go-dots** (`grid.gd`) — store the choice first, then switch screens: |
|||||||
| 31 | ||||||||
| 32 | ```gdscript |
|||||||
| 33 | # connect-go-dots — grid.gd |
|||||||
| 34 | func _open(photo: Texture2D) -> void: |
|||||||
| 35 | Shared.photo = photo # C625 sequence: store the choice… |
|||||||
| 36 | get_tree().change_scene_to_file("res://detail.tscn") # …then change scene |
|||||||
| 37 | ``` |
|||||||
| 38 | ||||||||
| 39 | ## C626 — Selection |
|||||||
| 40 | ||||||||
| 41 | **Definition.** A control structure that allows a programmer to write lines of code that are only run when a particular requirement is met. |
|||||||
| 42 | ||||||||
| 43 | ### If |
|||||||
| 44 | ||||||||
| 45 | When condition is met, flow is directed to the alternative instruction. |
|||||||
| 46 | ||||||||
| 47 | ```gdscript |
|||||||
| 48 | if condition: # C626 — selection |
|||||||
| 49 | # code |
|||||||
| 50 | ``` |
|||||||
| 51 | ||||||||
| 52 | ### If … Then … Else (chained selection) |
|||||||
| 53 | ||||||||
| 54 | When condition is met, flow can be directed multiple times. *Chained selection:* more than one condition checked in sequence — each branch can test a different condition, and execution stops at the first branch whose condition is true. |
|||||||
| 55 | ||||||||
| 56 | ```gdscript |
|||||||
| 57 | if condition: # C626 — chained selection |
|||||||
| 58 | # code |
|||||||
| 59 | elif other_condition: |
|||||||
| 60 | # code |
|||||||
| 61 | else: |
|||||||
| 62 | # code |
|||||||
| 63 | ``` |
|||||||
| 64 | ||||||||
| 65 | ### Switch or Case (`match`) |
|||||||
| 66 | ||||||||
| 67 | Choose between listed alternatives. Unlike chained selection, every case tests the *same* expression for equality against a different value. |
|||||||
| 68 | ||||||||
| 69 | ```gdscript |
|||||||
| 70 | match value: # C626 — selection: match |
|||||||
| 71 | 1: |
|||||||
| 72 | # code |
|||||||
| 73 | 2: |
|||||||
| 74 | # code |
|||||||
| 75 | ``` |
|||||||
| 76 | ||||||||
| 77 | **In club-ladder** (`team.gd`) — a real `match`, with the wildcard `_` as the catch-all: |
|||||||
| 78 | ||||||||
| 79 | ```gdscript |
|||||||
| 80 | # club-ladder — team.gd |
|||||||
| 81 | func record(result: String) -> void: |
|||||||
| 82 | match result: # C626 — selection: match with a catch-all |
|||||||
| 83 | "win": |
|||||||
| 84 | wins += 1 |
|||||||
| 85 | "draw": |
|||||||
| 86 | draws += 1 |
|||||||
| 87 | _: |
|||||||
| 88 | losses += 1 # anything that is not a win or a draw |
|||||||
| 89 | ``` |
|||||||
| 90 | ||||||||
| 91 | ### Myki example |
|||||||
| 92 | ||||||||
| 93 | ```gdscript |
|||||||
| 94 | # C626 selection: pick the fare rule |
|||||||
| 95 | if is_concession: |
|||||||
| 96 | fare = FARE_TABLE[zone] * 0.5 |
|||||||
| 97 | elif is_weekend: |
|||||||
| 98 | fare = WEEKEND_CAP |
|||||||
| 99 | else: |
|||||||
| 100 | fare = FARE_TABLE[zone] |
|||||||
| 101 | ``` |
|||||||
| 102 | ||||||||
| 103 | *Nested selection* — a selection inside another selection's structure — is also C626 evidence; use the word "nested" in validation. |
|||||||
| 104 | ||||||||
| 105 | **Earns the tick:** a condition that changes what runs, demonstrated with both outcomes. An `if` whose `else` can never happen is weak evidence. |
|||||||
| 106 | ||||||||
| 107 | **In tile-matching-game** (`game.gd`) — both selection shapes: |
|||||||
| 108 | ||||||||
| 109 | ```gdscript |
|||||||
| 110 | # tile-matching-game — game.gd |
|||||||
| 111 | if is_busy or card.is_face_up or card.is_matched: # C626 — guard clause |
|||||||
| 112 | return # bail out early on any bad click |
|||||||
| 113 | ||||||||
| 114 | if first_card.pair_id == second_card.pair_id: # C626 — selection: two outcomes |
|||||||
| 115 | _handle_match() |
|||||||
| 116 | else: |
|||||||
| 117 | await _handle_mismatch() |
|||||||
| 118 | ``` |
|||||||
| 119 | ||||||||
| 120 | ## C632 — Iteration / repetition |
|||||||
| 121 | ||||||||
| 122 | **Definitions.** *WHILE:* an iteration repeated for as long as a condition is met. *FOR:* an iteration repeated a predefined number of times. *Infinite loop:* an iteration that will never reach the condition upon which it can terminate. |
|||||||
| 123 | ||||||||
| 124 | ### While … |
|||||||
| 125 | ||||||||
| 126 | May not execute to satisfy condition. |
|||||||
| 127 | ||||||||
| 128 | ```gdscript |
|||||||
| 129 | while condition: # C632 — iteration |
|||||||
| 130 | # code |
|||||||
| 131 | ``` |
|||||||
| 132 | ||||||||
| 133 | ### Do … While |
|||||||
| 134 | ||||||||
| 135 | May not execute if condition is not satisfied once. |
|||||||
| 136 | ||||||||
| 137 | No `do … while` construct in GDScript — a pre-test `while` loop covers this behaviour: |
|||||||
| 138 | ||||||||
| 139 | ```gdscript |
|||||||
| 140 | while condition: # C632 — iteration |
|||||||
| 141 | # code |
|||||||
| 142 | ``` |
|||||||
| 143 | ||||||||
| 144 | ### Repeat … Until |
|||||||
| 145 | ||||||||
| 146 | Executes at least once. If conditions are not met, there is a possibility of an **infinite loop**. |
|||||||
| 147 | ||||||||
| 148 | No `repeat … until` construct in GDScript — emulate a post-test loop with `while true:` and a `break` when the condition is met: |
|||||||
| 149 | ||||||||
| 150 | ```gdscript |
|||||||
| 151 | while true: # C632 — post-test iteration |
|||||||
| 152 | # code |
|||||||
| 153 | if condition: |
|||||||
| 154 | break |
|||||||
| 155 | ``` |
|||||||
| 156 | ||||||||
| 157 | ### For … Next |
|||||||
| 158 | ||||||||
| 159 | A counting loop to be executed a set number of times. |
|||||||
| 160 | ||||||||
| 161 | ```gdscript |
|||||||
| 162 | for i in range(10): # C632 — counting iteration |
|||||||
| 163 | # code |
|||||||
| 164 | ``` |
|||||||
| 165 | ||||||||
| 166 | ### For … In |
|||||||
| 167 | ||||||||
| 168 | A counting loop that iterates over items in an array or list. |
|||||||
| 169 | ||||||||
| 170 | ```gdscript |
|||||||
| 171 | var cats = ["Whiskers", "Fluffy"] |
|||||||
| 172 | for cat in cats: # C632 — iteration over an array |
|||||||
| 173 | print(cat) |
|||||||
| 174 | ``` |
|||||||
| 175 | ||||||||
| 176 | ### Myki example |
|||||||
| 177 | ||||||||
| 178 | ```gdscript |
|||||||
| 179 | # C632 iteration: total up today's journeys |
|||||||
| 180 | var total: float = 0.0 |
|||||||
| 181 | for journey in journeys: |
|||||||
| 182 | total += journey["fare"] |
|||||||
| 183 | ``` |
|||||||
| 184 | ||||||||
| 185 | **In connect-go-dots** (`grid.gd`) — one loop wires every photo button: |
|||||||
| 186 | ||||||||
| 187 | ```gdscript |
|||||||
| 188 | # connect-go-dots — grid.gd |
|||||||
| 189 | for button in %Photos.get_children(): # C632 — iteration |
|||||||
| 190 | button.pressed.connect(_open.bind(button.texture_normal)) |
|||||||
| 191 | ``` |
|||||||
| 192 | ||||||||
| 193 | `get_children()` returns an array of the six `TextureButton`s and the loop visits each in turn. (`%Photos` finds the node by its scene-unique name.) |
|||||||
| 194 | ||||||||
| 195 | **In tile-matching-game** (`deck.gd`) — a real `while` whose end is guaranteed: |
|||||||
| 196 | ||||||||
| 197 | ```gdscript |
|||||||
| 198 | # tile-matching-game — deck.gd |
|||||||
| 199 | while not file.eof_reached(): # C632 — ends when the file runs out of rows |
|||||||
| 200 | var row := file.get_csv_line() |
|||||||
| 201 | ``` |
|||||||
| 202 | ||||||||
| 203 | **Earns the tick:** a loop over real data — a `for` over your own array, or a `while` whose condition provably terminates. Be ready to explain *why the loop ends*: the infinite-loop question is a validation favourite. |
|||||||
| 204 | ||||||||
| 205 | ## Check Your Understanding |
|||||||
| 206 | ||||||||
| 207 | 1. In a `match`, what does every case compare? |
|||||||
| 208 | ||||||||
| 209 | >| ### Answer |
|||||||
| 210 | >| The *same* expression against a different value — unlike chained `elif`, where each branch can test something different. |
|||||||
| 211 | ||||||||
| 212 | 2. GDScript has no `repeat … until`. What is the accepted emulation? |
|||||||
| 213 | ||||||||
| 214 | >| ### Answer |
|||||||
| 215 | >| `while true:` with `if condition: break` at the end of the body — runs at least once, tests after. |
|||||||
| 216 | ||||||||
| 217 | 3. What two questions about any loop should you be ready to answer live? |
|||||||
| 218 | ||||||||
| 219 | >| ### Answer |
|||||||
| 220 | >| What it iterates over, and why it must end. |
|||||||
