JavaScript Simon Game: Separate Playback from the Response

You press a button while the sequence is still flashing, and the game counts it as your first answer. On the next attempt, a correct pair of presses advances the round even though the third symbol was wrong.

Both failures come from accepting input without checking the phase and response position.

A JavaScript Simon game is a useful state-machine exercise when the sequence, playback, and player response have separate jobs. This guide specifies an original four-symbol practice game with five rounds. Use its fixtures to inspect exactly when an activation should count, then verify playback and input in the intended host.

Five-round sequence practice
Five-round sequence practice
Open the full example ↗

Give each round an ordered prefix

Use four native buttons labeled 1 Circle, 2 Triangle, 3 Square, and 4 Star. Numbers and names identify the buttons even when a reader cannot distinguish their colors. For development, use the fixed sequence [1,3,1,4,2] and maximum length five.

Round one plays [1]. Round two plays [1,3]. Round three plays [1,3,1]; it does not choose an unrelated three-symbol sequence. Rice University's ELEC327 project describes this progressive-prefix structure, an ordered response, and completion of the full sequence. Its hardware version also has a response timeout. Our browser practice variant deliberately has no response deadline, and uses its own symbols and timing rather than the source's electronics or firmware.

For ordinary play, choose five IDs independently from 1 through 4 at Start. Repeats are allowed. Keep the deterministic sequence as a separate development mode, not a promise that the ordinary sequence always differs from the previous game.

Treat the phase as an input gate

Define six states: idle, playback, response, between, won, and lost. Start initializes round one and enters playback. Each symbol is highlighted for an illustrative 350 ms, followed by 150 ms off. After the last off interval, clear symbol feedback, set response index to zero, and enter response.

Phase Accepted action
Idle Start a fresh sequence; Reset clears the session
Playback Reset; symbol guesses and Replay are ignored
Response One symbol activation, Replay Round, or Reset
Between Next Round, Replay Round, or Reset
Won or lost Reset only

Disable unavailable controls and also check the phase inside the action handler. A disabled-looking button is not the rule itself. A pending callback must verify that its session and playback generation are still current before it changes highlights or enables responses.

Use native click activation for the four symbol buttons. Native keyboard activation and pointer activation should reach that same handler once. Adding a second guess handler to pointer-down or key-down can count one physical action twice.

Compare the next position, not a set of symbols

In round three, the expected response is 1,3,1. After the first 1, the response index becomes one. After 3, it becomes two. The round is still incomplete: the final expected ID is 1.

Third-round input Expected result
1, 3 Still responding; two of three positions matched
1, 3, 1 Round complete; completed rounds becomes 3
1, 3, 2 Lost at the third position

The two appearances of 1 are different positions, so they require separate activations. If a fixture expects [3,3], pressing Square once cannot satisfy both positions. Compare one activation to the current expected ID, then advance once.

After a complete response in rounds one through four, enter between. Next Round explicitly advances the round and starts its longer prefix. After all five positions in round five match, set completed rounds to five and enter won. Do not schedule a sixth round.

Replay without manufacturing completed rounds

Replay Round uses the same sequence and current prefix. Cancel old playback callbacks, clear response feedback, and reset the response index before replaying. Replay itself earns no completion credit.

Use completed rounds = max(existing completed rounds, current round) only when the full response is correct. Repeating an already completed third round keeps that value at three. If the replay succeeds, it returns to between; if the replay response contains a wrong symbol, it follows the ordinary loss rule. Replay is unavailable during playback or in a terminal state.

Show the round, completed-round count, response progress, and phase in text. An optional review mode may display the full development sequence, clearly labeled as an inspectable practice key. Ordinary play can name the currently highlighted symbol without claiming that the game has passed assistive-technology checks.

When the page becomes hidden or the window loses focus during playback, response, or between, abort the active session rather than resume halfway through a prefix. Cancel timers, clear feedback and progress, and return to interrupted idle. Start creates a fresh game. Reset additionally clears the sequence and interrupted message; callbacks from either abandoned session cannot re-enable response input. Won and lost remain terminal until Reset.

Copyable game prompt

Create an original self-contained HTML/CSS/JavaScript symbol-sequence practice game with readable source and an acceptance-test report. Use four native buttons: 1 Circle, 2 Triangle, 3 Square, 4 Star. No copied toy branding, artwork, firmware, audio, or code.

Use states idle/playback/response/between/won/lost. Maximum length is five. Development sequence is [1,3,1,4,2]; ordinary Start independently chooses five IDs from 1..4, allowing repeats. Round n plays the first n IDs. Use illustrative 350 ms on and 150 ms off; after the final off interval clear feedback, reset response index to 0 and enter response. This is untimed practice, not Rice's timed hardware variant.

Accept a symbol only in response. Use one native click handler so pointer or native keyboard activation counts once; do not also count pointerdown/keydown as guesses. Compare to the current sequence position. Wrong ID loses immediately; correct ID advances once. Only all n correct positions complete the round. Set completedRounds to max(previous,n), never add replay credit. Rounds 1..4 enter between; explicit Next Round starts n+1. Full round 5 enters won with completedRounds=5, never round 6.

Replay Round is allowed only in response/between: cancel previous playback, reset response index/feedback and replay the same prefix. Replay itself adds no credit; a completed replay cannot increase completedRounds beyond that round. Correct replay returns to between; wrong input loses. Won/lost accept only Reset. Reset clears sequence, round, index, feedback, completed count and result, and invalidates old timers through session/generation guards. Hidden page or window blur during playback/response/between aborts to interrupted idle, clears progress and requires Start for a fresh game; stale callbacks cannot re-enable responses. Won/lost remain terminal until Reset.

Test round 3 responses [1,3] incomplete, [1,3,1] complete, [1,3,2] lost on third. Test [3,3] requires two activations. Ignore guesses during playback/between. Test replay without credit, round 5 terminal, and Reset during playback. Show phase, round, completed count and response progress, with Start/Replay Round/Next Round/Reset controls. Optional review mode exposes the development sequence explicitly as a practice key.

Check native keyboard focus, timing/gates, duplicate events, old callbacks, article width and 360 px. Report each unexecuted check as not_tested. Do not claim memory improvement, full accessibility conformance, storage, host compatibility, or a working game without actual evidence.

Keep the sequence test with the HTML

The source and ordered-response fixtures remain the reference for this game. If you prepare an HTML version in NOS, the supplied product evidence supports HTML saving and rendering; verify playback, native activation, and reset in the actual workspace before describing that version as playable. Explore NOS with prepared HTML, and keep the third-position failure case beside it so a future change cannot quietly turn a partial response into a completed round.

Keep reading