Mastermind Code Breaker Game — Free HTML CSS JS Snippet
Mastermind Code Breaker Game · Games · Plain HTML, CSS & JS · Live preview
For supporters
Source Code
Want the source code?
Play the game for free. Become a WebDevPuneet supporter to unlock the complete HTML, CSS and JavaScript source code, the exports (HTML, React, Vue, Angular, Tailwind) and Fork.
Extend with AI
Take This Snippet Further With AI
The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.
What's included
Features
About this UI Snippet
Mastermind Code Breaker Game — Black/White Peg Deduction Logic in Vanilla JS

Mastermind is a classic code-breaking deduction game: the computer picks a hidden sequence of colored pegs, and the player tries to guess it within a limited number of attempts, receiving black and white peg feedback after every guess. Black means a color is in the exact right position; white means a color exists in the code but in the wrong position. This snippet implements the complete game loop — secret generation, guess building from a color palette, correct peg-counting logic (the trickiest part to get right), a scrollable guess history, and win/lose states — entirely in vanilla JavaScript.
Generating the secret code
randomSecret() picks CODE_LENGTH (4) colors independently at random from the COLORS palette, with repeats allowed — a real Mastermind code can and often does repeat a color, which is part of what makes deduction interesting. The secret is stored in a closured secret array and never rendered to the DOM, so it can't be read from the page source while playing.
The peg-counting algorithm: why a naive comparison is wrong
The subtle part of Mastermind is scoring white pegs correctly when colors repeat. A naive approach that just checks "does this guessed color exist anywhere in the secret" over-counts: if the secret has one red and the guess has three reds, only one white or black peg should be awarded for red, not three. scoreGuess() solves this with a two-pass approach. The first pass counts black pegs (exact position matches) and, for everything else, pushes the *unmatched* secret and guess colors into secretLeft and guessLeft arrays — removing already-matched positions from consideration entirely. The second pass walks guessLeft and, for each color, looks it up in secretLeft with indexOf; if found, it counts a white peg and splices that specific slot out of secretLeft so the same secret peg can never be claimed twice. This splice-on-match step is exactly what keeps repeated colors from being over-counted.
Building a guess from a palette, not a text input
Instead of typing colors, the player clicks swatches in .mm-palette to push colors onto a currentGuess array, rendered live into four .mm-slot circles. This keeps the interaction fast and mirrors the physical board-game experience of placing pegs, and it structurally prevents invalid input (typos, wrong color names) since only real palette colors can ever enter currentGuess.
Feedback pegs and turn limits
After each submitted guess, renderRow() appends a row to the guess history containing the guessed colors and up to four small feedback pegs — black pegs first, then white, then empty placeholders — matching the classic physical presentation. turn increments on every non-winning guess and the game ends in a loss once it reaches MAX_TURNS (10) without four black pegs, or ends in a win the instant score.black === CODE_LENGTH.
Step by step
How to Use
- 1Click colors to build a guessClick swatches in the palette to fill the four current-guess slots. Click Clear to start the row over.
- 2Submit the guessOnce all four slots are filled, click "Submit guess" to score it against the hidden secret via scoreGuess().
- 3Read the feedback pegsBlack pegs mean a color is in the exact right position; white pegs mean a color is in the code but the wrong position. Each color can only be claimed once per row.
- 4Keep guessing until solved or out of turnsYou get 10 guesses (MAX_TURNS). Getting four black pegs wins immediately; running out of turns ends the round.
- 5Review the guess historyThe scrollable board below the input keeps every previous guess and its feedback pegs visible, newest at the top.
- 6Start a new codeClick "New code" at any time to generate a fresh random secret via randomSecret() and reset the turn counter.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
scoreGuess() first counts exact-position matches as black pegs and removes those positions from consideration. It then matches remaining guessed colors against remaining secret colors one at a time using indexOf, and splices each matched secret color out immediately so it cannot be claimed by a second white peg.
Yes. randomSecret() picks each of the four positions independently, so repeats are allowed, exactly like the physical Mastermind board game.
MAX_TURNS is set to 10. If you have not scored a full row of black pegs by your tenth submitted guess, the round ends in a loss and you can start a new code.
No, the secret array is not rendered into the DOM at any point during play, so it cannot be read from the rendered HTML — only from the JavaScript source itself if you inspect the code (as with any client-side game).
Increase CODE_LENGTH for a longer secret, add more entries to the COLORS array for more possible colors per slot, or lower MAX_TURNS to reduce the number of allowed guesses.
No. Each guessed position is classified as black, white, or neither exactly once. A position that scores black is removed from both the secret-left and guess-left pools before white pegs are counted, so it can never also contribute a white peg.