Build Tetris using React Native and Expo

Lesson 2 of 8

Tetromino Shapes and Rotation

There are exactly 7 tetromino shapes (I, O, T, S, Z, J, L), each made of 4 connected squares. This lesson defines them as data, and writes the rotation logic every one of them shares.

Defining the shapes

Each shape is a small matrix, 1 for a filled cell, 0 for empty:

type Matrix = number[][];

const SHAPES: Record<string, Matrix> = {
  I: [[1, 1, 1, 1]],
  O: [
    [1, 1],
    [1, 1],
  ],
  T: [
    [0, 1, 0],
    [1, 1, 1],
  ],
  S: [
    [0, 1, 1],
    [1, 1, 0],
  ],
  Z: [
    [1, 1, 0],
    [0, 1, 1],
  ],
  J: [
    [1, 0, 0],
    [1, 1, 1],
  ],
  L: [
    [0, 0, 1],
    [1, 1, 1],
  ],
};

const SHAPE_COLORS: Record<string, number> = { I: 1, O: 2, T: 3, S: 4, Z: 5, J: 6, L: 7 };

The SHAPE_COLORS map assigns each shape a number matching the board cell values from the last lesson, when a piece locks into the board, its cells get filled with this id, which the Board component's styling can later look up to pick a color per piece type.

Rotating a matrix 90°

function rotate(matrix: Matrix): Matrix {
  return matrix[0].map((_, col) => matrix.map((row) => row[col]).reverse());
}

console.log(rotate(SHAPES.L));
// [0,0,1] [1,1,1]  ->  [1,0] [1,0] [1,1]

This single line is the standard "rotate a matrix 90° clockwise" trick: matrix.map((row) => row[col]) reads down one column of the original matrix, turning it into a row, then .reverse() flips that row's order. Doing this for every column (matrix[0].map((_, col) => ...), using the first row just to get the right number of columns to iterate) builds an entirely new, rotated matrix, the original matrix is never mutated.

Why this works for every shape, unchanged

Because rotate only ever looks at a matrix's dimensions, not which shape it represents, the exact same function correctly rotates the I-piece (1x4), the O-piece (2x2, visually unchanged by rotation, but the code doesn't need to know that), and every other shape. Calling rotate four times returns you to (approximately) the original orientation.

TIP

The O-piece rotating "into itself" every time isn't a special case you need to write, it's just what naturally falls out of rotating a symmetric 2x2 matrix, one of the small satisfactions of representing shapes as plain data instead of hand-coding each shape's four rotations separately.

📝 Tetromino Shapes and Rotation Quiz

Passing score: 70%
  1. 1.How many distinct tetromino shapes does classic Tetris use?

  2. 2.The rotate() function needs a special case written for the O-piece so it rotates correctly.

  3. 3.The rotate() function reads down a column with map(), then calls .____() to flip that row's order.