Mini Sudoku Game with 24 Levels – Free HTML, CSS & JS
Mini Sudoku Puzzle (6x6) · 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
Mini Sudoku — 24 Levels, Unique-Solution Generator, Hints, Pencil Notes, Lives and a Daily Puzzle

Mini Sudoku is a 6x6 version of the classic number puzzle: every row, every column and every 3x2 box must contain the digits 1 to 6 exactly once. This version is a full game rather than a demo. It has 24 levels in four difficulty tiers, a Daily Puzzle with a streak, three lives, hints that explain themselves, pencil notes, undo, stars and saved progress. It is written in plain HTML, CSS and JavaScript, with no libraries, no images and no audio files.
A generator that guarantees one solution
Every puzzle starts from a complete grid built with randomised backtracking (fillGrid()). carve() then removes digits one at a time in random order. After each removal, countSolutions() runs a depth-first search that always branches on the cell with the fewest candidates and stops after finding two solutions. If the puzzle now has more than one solution, the digit is put back. The result is a puzzle with exactly one answer, so a player can always reason their way to it instead of guessing.
Difficulty from data, not guesses
The TIERS array holds four tiers (Warm-up, Sharp, Brain-burner, Grandmaster), each with a clue count and the hardest technique it may require. solvableBy() plays a puzzle using only naked singles (a cell with one candidate left) or also hidden singles (a digit that fits only one cell in a row, column or box). Warm-up levels must be solvable with naked singles alone, the middle tiers need hidden singles, and Grandmaster only guarantees a unique solution with as few as 11 clues. If a generated puzzle is too hard for its tier, the generator tries the next seed.
Seeded, so levels are the same for everyone
A small seeded random generator (mulberry32) drives the whole pipeline. Level number i always uses the seed 1000 + i * 7919, so level 7 is the same puzzle for every player and every visit. The Daily Puzzle uses a seed derived from the day number, so everyone gets the same puzzle on the same day, and clearing it on consecutive days builds a streak.
Hints that teach
useHint() looks at the board (ignoring wrong digits) and prefers a naked single, then a hidden single. It fills the cell and explains why in plain words: "R3C4 can only be 5: 1, 2, 3, 4 and 6 are already in its row, column or box", or "In row 2, only R2C5 can hold a 3". The player learns the technique instead of just seeing an answer, and hints reduce the star rating.
Lives, notes and undo
A digit that does not match the solution costs one of three lives, shakes the lives counter and turns the cell red. Pencil notes are stored as bit masks, one per cell, and a correct digit removes itself from the notes of every cell in its row, column and box. Undo restores a snapshot of the grid, the notes and the hint cells. Placing the last needed digit of a row, column or box sends a green wave across it.
Stars, saved progress and feel
A solved level earns up to three stars: one is lost for any mistake and one for using a hint. A level unlocks when the one before it has at least one star. Stars, best times, the streak and the daily result are saved to localStorage inside try/catch, so the game also runs in a sandboxed iframe. The board highlights the selected cell's row, column and box and every cell with the same digit, the number pad shows how many of each digit are left, and a synthesized sound and confetti mark a win. The timer pauses with P, when you open the level menu, and when the tab is hidden.
Step by step
How to Use
- 1Pick a level or the Daily PuzzleThe menu shows 24 levels in four tiers with your stars on each. Level 1 is open at first, and each level unlocks when the one before it has at least one star. The gold Daily Puzzle card starts the puzzle of the day.
- 2Select a cell and enter a numberClick a cell, then click a number on the pad or press 1 to 6. The cell, its row, column and box are highlighted, and so is every cell holding the same digit. Move with the arrow keys, and use Backspace or the Erase button to clear a cell.
- 3Use pencil notesPress N (or the Notes button) to turn numbers into small pencil marks for cells where you are unsure. Placing the correct digit removes it from the notes of its row, column and box automatically.
- 4Mind your livesA wrong digit turns red and costs one of your three lives. Lose all three and the run ends, but the puzzle stays the same, so you can retry it with what you learned.
- 5Ask for a hint when stuckPress H or the Hint button. It fills a cell that can be found by logic and explains why in the message line. You get three hints per puzzle, and using one costs a star.
- 6Earn stars and unlock moreFinish with no mistakes and no hints for three stars. The result screen shows your time against the par time, your score and your best time. The timer pauses with P, and Z undoes your last move.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
After building a full grid, carve() removes digits in random order. Each time, countSolutions() searches for solutions, always branching on the cell with the fewest candidates, and stops as soon as it finds two. If a second solution exists, the removed digit is restored. Only removals that keep exactly one solution are kept, which is why every puzzle can be solved by reasoning alone.
Each tier in the TIERS array has a target number of clues and the hardest technique it may need. solvableBy() solves a copy of the puzzle using only allowed techniques: naked singles, or naked plus hidden singles. A Warm-up puzzle must be fully solvable with naked singles, Sharp and Brain-burner with hidden singles as well, and Grandmaster only needs a unique solution with the fewest clues. A generated puzzle that is too hard for its tier is thrown away and the next seed is tried.
Randomness comes from mulberry32, a seeded generator, and level i uses the fixed seed 1000 + i * 7919. The same seed always gives the same grid and the same removals, so level 7 is identical for every player. The Daily Puzzle uses a seed built from the number of days since a start date.
You get three lives and three hints per puzzle. A digit that does not match the solution costs a life, and losing all three ends the run. A solved puzzle gives three stars, minus one if you made any mistake and minus one if you used a hint, with a minimum of one. The next level unlocks as soon as the previous one has a star.
Edit the TIERS array: clues is how many digits are given, logic is the hardest technique allowed (naked, hidden or null) and par is the target time in seconds. Each tier has six levels, so adding a tier means adding an object and raising the star total in the HTML (three stars per level). levelSpec() lowers the clue count by one for the second half of each tier.
Yes. All localStorage reads and writes are wrapped in try/catch, so a blocked storage only means progress is not saved. The AudioContext is created on the first level start and every sound call is wrapped in try/catch. The board uses pointer events and a number pad, so it plays by touch as well as by keyboard.