Tetris
Northwestern CS 211, Spring 2023
View code on GitHub ↗︎- C++
- Object-Oriented Design
- Game Development

A from-scratch Tetris clone written in C++ using ge211, Northwestern's teaching game engine, built around a strict Model-View-Controller split with unit tests covering the core game logic.
Features
- All 7 tetromino shapes (I, J, L, O, S, Z, T), each with its own set of rotation states defined using block-by-block templates.
- Collision detection: pieces stop against the floor, the grid walls, and any previously settled tetromino.
- Line clearing: full rows are detected, deactivated, and everything above cascades down to fill the gap.
- Scoring and leveling: clearing lines increases the score, and every 10 cleared lines advances the level and speeds up future pieces' fall rate.
- Soft drop: holding down accelerates the active piece's descent.
- Game-over detection: the game ends when a newly spawned piece has nowhere to go.
Controls
- Left / Right arrow: move the active piece
- Up arrow: rotate the active piece
- Down arrow: soft-drop (increase fall speed)
- Q: quit
How it's built
The project follows the Model-View-Controller structure of the course's ge211 scaffolding.
Model — manages the grid, the falling tetromino, and the settled pieces. Each frame, it checks whether the active piece can move down. If not, it locks the piece in place and spawns the next one.
Rotation — swaps in a new block template for each shape's next rotation state. This keeps collision check simple because only the new blocks need to be checked.
Line clearing — checks for full rows, clears them, and shifts the blocks above down. Every 10 cleared lines increases the level and speeds up future tetrominoes.
View turns the model's state into sprites and text overlays for score, level, and lines cleared. Controller translates key presses into calls like move_tetromino_left() and rotate_tetromino() on the model. The whole project builds via CMake.
Verification
A Catch2 test suite covers five core behaviors:
- Tetromino rotation across both the 2-state and 4-state rotation systems
- Active-versus-settled piece movement
- Line clearing with score tracking
- Game-over detection
- Fall-speed scaling across levels
Rotation near walls and settled pieces needed separate manual testing beyond the automated suite. Since a rotation swaps in an entirely new block template rather than adjusting the existing one incrementally, the risk was a rotated piece clipping through a wall or overlapping a settled block at the boundary. Testing confirmed the rejection behaves cleanly instead: a rotation attempted too close to a wall or another piece just snaps back to its pre-rotation shape rather than glitching into an invalid position.
Result
View the gameplay demo below: