Tutorial 1.1 - Step 4

Learn to code with step-by-step lessons. A place for students to work through programming fundamentals and build skills.

Step 4 - Rotating pieces

← Step 3 · Tutorial 1.1 · Step 5 →


Goal

Add rotation: when the player presses a key (e.g. W or Up), the current piece should rotate 90° clockwise. We already have the right data structure: each piece has several lists of offsets (one per rotation state). Rotating means switching to the next list and wrapping (e.g. 0 → 1 → 2 → 3 → 0).

By the end of this step you should have:

We are not yet preventing rotation when it would overlap a wall or the board - that’s Step 5. Here we only add the rotation logic and more offset lists.


Why offset lists?

Each rotation of a piece is a different set of cells relative to the origin. For example, an L can have four rotations; each is a list of four (dx, dy) pairs. Storing them as offsets[0], offsets[1], … means rotating is just changing the index - no need to compute new coordinates with math.


Your task

  1. For your piece type(s), add all rotation states to self.offsets. For L you need 4 lists; for O you need 1 (or 4 identical); for T, S, Z you need 2 or 4 depending on symmetry.
  2. Implement rotate(self, n=1): set self.offset_num = (self.offset_num + n) % len(self.offsets).
  3. In the game’s key handling, when the player presses the rotate key, call self.pieces[0].rotate(1).

Hints

Hint 1 - How many offset lists per piece? L, T, J have 4 rotations; S and Z have 2 (the other two are the same). O has 1 (or 4 copies of the same). So `len(self.offsets)` can be 1, 2, or 4. Use modulo so after the last rotation you wrap: `(offset_num + 1) % len(offsets)`.
Hint 2 - Figuring out coordinates for each rotation Draw the shape on paper. The origin is often the “pivot” (e.g. top-left of the 3×3 box). For each 90° clockwise turn, write the (dx, dy) of each of the four cells. Example L: first state [(0,0),(0,1),(0,2),(1,2)]; second state [(0,1),(1,1),(2,1),(0,0)]; etc.
Hint 3 - Don’t forget render and check_collision They already use `self.offsets[self.offset_num]`, so once you add more lists and update `offset_num` in `rotate()`, the piece will render and collide with the new shape. No changes needed there.

Check your work

Pressing the rotate key should cycle the piece through its rotations. (It may still rotate into walls or the board - we fix that in Step 5.) Compare with the solution when ready.

→ See the solution for Step 4

Then go to Step 5 - Preventing rotation into walls and other pieces.