Game programming is probably the best way to learn to program many, many kinds of things ;-)
On the topic of state machines, I totally agree with the observation that games are a prime example of their usefulness. I've been working on and off on a relatively simple game that uses a Lua scripting backend to implement the game logic, and over time I've been refactoring this particular part many times, slowly converging to a solution resembling an event driven state machine implemented using reactive programming techniques. It's very interesting to see how even a very simple game already forces you to either apply concepts like state machines, events, etc, or end up with horrible crappy code that is hard to debug and not fun to work on.