build-a-qr-code-encoder / lesson-23.md
Lesson 23 · The module matrix

The empty grid

A QR symbol is a square grid of modules, each dark or light. Before placing anything you need the grid itself and a way to tell an unset module from a decided one. Today you build that grid for Version 1.

The goal

Create the Version 1 module grid with every module initially unset.

Start here - the target
TO DO
Scenario: A fresh grid of the right size
Givena Version 1 symbol, whose side length is 4*version + 17 modules
Whena new grid is created for Version 1
Thenit is 21 by 21 modules
Andevery module starts unset - distinct from both dark and light - so later steps can tell which modules still need a value
Background

A QR symbol is a grid of square modules, each either dark or light, and the grid is always square with an odd side length. The side length is 4 * version + 17, so Version 1 is 21 by 21. Every larger version adds four modules per side. This grid is the canvas the rest of the chapter draws on.

The subtlety is that you need three states, not two. As you place finder patterns, timing lines, and data, you must know which modules are still empty so you do not overwrite a function pattern with data or place data twice. So each module is unset, dark, or light, and a fresh grid is entirely unset. Represent that however you like - a sentinel value, a pointer, a parallel “reserved” mask - as long as “not yet decided” is distinct from “decided light”. Everything from here writes into this grid.

Make it work
// Three states per module: unset, dark, light. Use a pointer
// or a -1 / 0 / 1 sentinel so "unset" is distinguishable.
type Grid struct {
size int
modules [][]int8 // -1 unset, 0 light, 1 dark
}
func NewGrid(version int) *Grid {
n := 4*version + 17
// ... fill with -1
}
CheckpointDONE
You have an empty Version 1 grid. Commit and stop here.