A lot of the classic video games are very good at providing flow because of their linearly increasing difficulty and the inevitability of losing. Consider Tetris. Tetris has all the basics: good controls, simple and concise rules, and constant feedback in the form of your score. You can tell when you're doing well, because the lines disappear and your score increases. You can tell when you're doing very well because the screen also flashes when you line up a Tetris.
"[The] only video game I can think of that left cultural marks for
decades & will last 100 [years] is Tetris" - Raph Koster
The key to Tetris (and many classics like it, such as Missile Command and Breakout) is that the difficulty steadily increases over time. The player may start the difficulty at any level. Then, after every regular interval (10 lines) the game becomes more difficult as the pieces begin to fall faster. The difficulty, then, will inevitably reach optimal challenge. Sooner or later, the player will be optimally challenged, just barely slotting the pieces where they're needed, or making small mistakes and having to be clever and quick to correct them. After a while longer, the pieces will fall too quickly, the player will become too challenged, and soon after, the game will end.
Tetris is very good at spending the player's time optimally challenged. The player doesn't have to spend any time bored, because he/she can set the starting difficulty at any level. The particularly brilliant part is that the player spends very little time frustrated, because the game ends shortly after the game becomes too difficult. When the difficulty has gone too high, the player loses and starts a fresh game, beginning again at a lower difficulty. The player never has to play through extended periods which are too easy or try to drag him/herself through an exceedingly difficult part of the game.
You can almost think of Tetris as searching for the player's skill level. The player punches in the best guess, since starting at a higher level means earning more points before losing. Tetris then ratchets up the difficulty until the player can no longer play, assuming that someplace in between it has to run into the perfect challenge. I have to wonder - if we could stop Tetris from growing more difficult when it hit that perfect balance, would we be happy to continue playing for half an hour at a time? I suspect that the game around the experience of flow is still important - chasing after that high score means you can also track your skill as a player.
Games which are intended to be beaten or finished don't have the luxury of this particular search strategy. If a game like Halo or Mass Effect 2 steadily ratcheted up the difficulty until the player died, the player would probably become pretty annoyed at the inevitability of having to die and lose progress before the game made it easier again. Developers of these games have to try to make the whole game optimally challenging, meeting the player's skill and then growing in difficulty as the player grows in skill. It's almost an impossible task, which is why probably a better design decision for these games is finely-grained difficulty settings.
The best difficulty system in a long, long time.
I'm not talking about "easy, normal, hard", where the difference between settings is enemies having +/- 50% health and the player taking +/- 50% damage - that's not nearly granular enough. Instead, I'm thinking of something like Bastion's "idols" system, where the player can change particular parameters about enemies, making them a little tougher for a little extra reward (ie enemies move faster; enemies recover health over time; enemies drop a grenade when they die; enemies drop fewer power-ups).
Helping your players to optimal challenge is easy when they're destined to lose - just keep cranking it up and they're bound to hit it eventually! Keeping them there for hours of a game that takes away their progress when they die, though, that's the really tricky part.