Tetris
The game is a timer that pulls the current piece down one row, plus player input that moves it sideways or rotates it. Both use the same check: does the piece fit at this position?
The game loop
flowchart TD
A["Spawn the next piece at the top"] --> B{"Does it fit?"}
B -- no --> C["Game over"]
B -- yes --> D["Gravity timer fires"]
D --> E{"Can the piece move down one row?"}
E -- yes --> F["Move it down"]
F --> D
E -- no --> G["Lock the piece into the board"]
G --> H["Remove full rows"]
H --> I["Update score, lines, and level"]
I --> A
Player input
flowchart LR
A["Left, right, or rotate"] --> B{"Does the piece fit in the new position?"}
B -- yes --> C["Apply it"]
B -- no --> D["Rotation only: try a few sideways offsets, then give up"]
E["Hard drop"] --> F["Slide the piece down until it can't move"] --> G["Lock immediately"]
The ghost piece uses the same calculation as hard drop. It finds where the piece would land and draws it translucent, redrawn after every move.
Scoring and speed
| Rows cleared at once | Points |
|---|---|
| 1 | 100 × level |
| 2 | 300 × level |
| 3 | 500 × level |
| 4 | 800 × level |
The level rises by one for every 10 lines cleared. The gravity interval starts at 800 ms and shrinks by 60 ms per level, with a floor of 50 ms. Each row of soft drop (the down arrow) adds 1 point; hard drop adds none.
The board and the pieces
- The board is a grid of cells that are either empty or filled with a color. A locked piece becomes ordinary filled cells and loses its identity.
- A piece is a small matrix. Rotating it 90° clockwise is a matrix rotation, checked against the board before it is accepted.
- Removing a full row deletes it from the grid and inserts an empty row at the top, so everything above falls one row.