← BackView on GitHub

Niner: the daily sudoku

A clean, calm sudoku for Android. One daily puzzle, five modes, zero ads, zero tracking.

Get it on Google PlayPublished on Google Play as nyznah

Play a web port of Niner

A stripped-down web version of the core game, using Classic rules on Medium. The full Android app has all five modes and difficulty levels, plus notes, hints, achievements, and a daily puzzle.

MediumClassic
Mistakes0/3
Time0:00

Select a cell, then type a digit or tap the pad.

Main menu Game in progress Statistics Achievements


Why Niner exists

Most sudoku apps on the Play Store bury the puzzle under interstitial ads, "remove ads" upsells, and analytics SDKs that track every cell tap. The puzzle itself is fine. Everything around it isn't.

Niner is the opposite. A puzzle, a board, and the time it takes to solve it.

Your puzzles, stats, and achievements live in a single SharedPreferences file on your device. Uninstall the app and they're gone. No server-side data, no shadow copy.


Features

Game

Polish

Accessibility


Tech stack

Layer Technology
Language Kotlin 2.0.21
UI Jetpack Compose, Material 3
Compose BOM 2024.09.03
Architecture Single-activity, AndroidViewModel + StateFlow + mutableStateOf
Persistence SharedPreferences + org.json (no Room, no DataStore)
Concurrency Kotlin Coroutines
Build AGP 8.7.0, Gradle KTS, R8 minification + resource shrinking
Min / Target SDK 26 / 35

Architecture overview

app/src/main/java/com/ninersudoku/
├── MainActivity.kt
├── achievements/      Achievement enum + AchievementManager (StateFlow + persistence)
├── daily/             DailyManager (deterministic per-date seed, streak tracking)
├── game/
│   ├── Board.kt       Immutable 9×9 board with conflict detection
│   ├── Cell.kt        Cell with value, given/hint flags, pencil notes
│   ├── Difficulty.kt  Per-level clue counts + hint caps
│   ├── GameMode.kt    Mode enum with display name + description
│   ├── Generator.kt   Classic puzzle generator with uniqueness check
│   ├── Solver.kt      Bitmask backtracking with MRV
│   ├── HintEngine.kt  Naked + hidden singles + cage-aware hints
│   └── Killer.kt      2- or 3-cell cage generator + Killer-aware solver
├── onboarding/        OnboardingManager (3-page first-run experience)
├── persistence/       SaveManager (in-progress game serialisation)
├── prefs/             DisplayPreferences (a11y + behaviour toggles)
├── sound/             SoundManager (ToneGenerator-based chimes)
├── stats/             StatsManager + per-mode best-time tracking
├── viewmodel/         GameViewModel: single source of state truth
└── ui/
    ├── BoardView.kt        Canvas-rendered grid + transparent semantics overlay for TalkBack
    ├── NumberPad.kt        Digit pad with remaining counts + tap/long-press
    ├── DifficultyScreen.kt Main menu (Daily, Continue, Mode picker, difficulty cards)
    ├── GameScreen.kt       Top bar + board + actions + pause + hint dialog + celebration
    ├── StatsScreen.kt      Hero card + summary + heatmap + per-difficulty cards + achievements
    ├── OnboardingScreen.kt 3-page intro
    ├── AboutScreen.kt
    ├── celebration/        Particle engine + style preview
    ├── components/         SettingsSheet (themes, modes, a11y)
    └── theme/              5 colour palettes × light + dark

Notable design decisions

Build and release-signing steps are in the repo README.


Roadmap

Things deferred for v1.x:


License

MIT. Fork it, learn from it, remix it.


Credits

Built solo by Raymond Jack. Made for people who love sudoku.