A traffic light has three states (green, yellow, red), one rule for transitioning between them (next in order), and a duration for each state. That's the entire algorithm. When you write it out, you've written a finite-state machine — the foundational pattern for embedded control.

The pattern is an enum and a switch

Define the states: enum { GREEN, YELLOW, RED } state = GREEN;. In loop(), switch on the current state, set the right pins, wait for the duration, then advance to the next state. That's it. Adding pedestrian-crossing buttons or sensor inputs becomes "in this state, also check if X" — but the structure of the code doesn't change.

The seductive trap is to skip the enum and just write a sequence of digitalWrite + delay calls in order. That works for the simple case. The moment you need to react to anything mid-cycle — a pedestrian button, an emergency override, a sensor that says "early advance" — you discover you've made it impossible. The state machine pattern keeps every possible "what should I do next?" question answerable in one place.

State machines compose

Almost every device you've ever owned is a state machine. The dishwasher cycles through prewash → wash → rinse → dry. The microwave runs idle → counting-down → done-beep → idle. Your smartphone's lock screen is a four-state machine. Recognising the pattern is half the battle; writing one neatly is the other half.