Simply Sudoku

A familiar puzzle. Built from the rules up.

A native Android learning project exploring puzzle generation, game state, and responsive interaction in Kotlin.

Platform
Mobile App
Scope
Full-stack
Team
Solo
Status
Complete
Started
Jun 15, 2024

Project context

Sudoku has been one of my favorite puzzle games since middle school, so when I began learning Kotlin and Android development, it felt like a natural project to build from scratch.

The goal was not to reinvent the game or turn it into something overly complex. I wanted to create a clean, familiar Sudoku experience while using the project to practice algorithm design, state management, and native mobile development.

The challenge

  • Generate valid puzzles from scratch
  • Keep the board synchronized with game rules

The approach

  • One game model owns state and moves
  • Native views render the current board

From intent to interaction

  1. Generate a puzzle

    Build a solved grid and remove clues while checking for multiple solutions.

  2. Work through the board

    Select cells, enter values, and use hints or undo when needed.

  3. Save and return

    Resume a locally saved game for the selected difficulty.

What it makes possible

Play a generated puzzle

Start a locally generated puzzle with a checked solution.

Work through mistakes

Use hints, undo, redo, and reset while solving the board.

Resume a saved game

Resume saved board state and elapsed time by difficulty.

How the pieces fit

Android screens

Render the board and respond to player input.

Fragments and XML views

Shared game state

Manage puzzles, move history, and validation.

MainViewModel and GameLogic

Local save slots

Save board state and elapsed time by difficulty.

SharedPreferences

One owner for game logic

Keep board updates and gameplay tools connected to one game model.

Keep computation off the interaction path

Run heavier puzzle operations without blocking player interaction.

Engineering notebook

Explore the design, data flow, and implementation in more detail.

Android screens

Render the board and respond to player input.

Fragments and XML views

Shared game state

Manage puzzles, move history, and validation.

MainViewModel and GameLogic

Local save slots

Save board state and elapsed time by difficulty.

SharedPreferences

Simply Sudoku was built as a personal learning project around a game I already enjoyed playing.

The project gave me a focused way to practice Kotlin, Android development, recursive problem solving, and gameplay state management without hiding behind a prebuilt game engine. Because Sudoku is deterministic and rule-driven, it provided a clear environment for learning how to represent a board, validate moves, manage player interaction, and keep the interface synchronized with the underlying game state.

Implementation

Simply Sudoku is built as a native Android application in Kotlin using AppCompat fragments, XML layouts, traditional Views, and an activity-scoped MainViewModel.

The app centers around a single GameLogic instance owned by the ViewModel. GameLogic handles puzzle generation, board mutation, validation against the solved grid, hints, undo/redo, reset, completion checks, and save-state serialization, while fragments observe LiveData and refresh the board UI.

Generate a puzzle

Generate a board with a checked unique solution.

Work through the board

Enter values and use hints or undo when needed.

Save and return

Resume the saved game for the chosen difficulty.

Users open the app, start a Sudoku puzzle, select cells, enter values, and work through the board using a familiar mobile puzzle interface.

The experience is intentionally simple. The app is meant to feel like Sudoku: clear, focused, and consistent, without unnecessary layers getting in the way of solving the puzzle.

Implementation

A puzzle begins inside GameLogic, which creates a solved 9x9 grid by randomizing diagonal boxes and completing the board with recursive backtracking. It then removes clues while rejecting removals that would produce multiple solutions.

The board is represented through parallel grids for the solved puzzle, initial givens, current player-visible state, and cell color classification. When a user enters a value, the ViewModel routes the update into GameLogic, records the move in undo history, recalculates correctness against the solved grid, and republishes board state through LiveData for the fragment to render.

Generate a unique puzzle

Reject clue removals that allow multiple solutions.

Keep separate board grids

Track solved, initial, current, and color grids.

Save one game per difficulty

Save board state and elapsed time by difficulty.

Simply Sudoku is built around the gameplay loop that makes Sudoku work: board state, valid moves, puzzle solving, and responsive interaction.

The most interesting part of the project was not adding extra features, but coordinating the backtracking logic, game state, and Android UI so the app remained responsive while puzzle operations were processed. Working through that helped me better understand how coroutines can keep computation-heavy logic from blocking the user experience.

Implementation

Navigation is handled through fragment replacement inside a single FragmentContainerView, with LandingFragment, GameFragment, and ThemeFragment forming the main screens. The game board is rendered as 81 TextView cells inside a ConstraintLayout, with larger margins marking 3x3 box boundaries.

Persistence uses SharedPreferences save slots for Easy, Medium, and Hard games. Each slot stores the initial board, solved board, current user board, color grid, and elapsed time. The implementation favors a simple local architecture over accounts, remote sync, databases, or a game engine.

Generated puzzles

Generate a solved board, then remove clues while checking for multiple solutions.

Board state model

Keep solution, givens, player entries, and cell colors together inside GameLogic.

Move validation

Compare player input with the solution and reveal mistakes through Show mode.

Hints and correction tools

Support solved-cell hints, reset, clear mistakes, and in-memory undo and redo.

Local save slots

Store one game per difficulty in SharedPreferences, including grids and elapsed time.

Classic Sudoku gameplay

Provides a familiar Sudoku experience centered on solving a clean, rule-driven puzzle board.

Board interaction

Allows users to select cells, enter values, and progress through the puzzle using a simple mobile interface.

Puzzle validation

Uses Sudoku rules to keep gameplay grounded in row, column, and box constraints.

Solver-backed logic

Uses backtracking logic to support the puzzle system and reinforce the deterministic rules behind the game.

Responsive gameplay

Uses asynchronous processing patterns so puzzle logic can run without making the interface feel blocked or sluggish.

Implementation
Generated puzzles

Creates puzzles locally by seeding randomized diagonal 3x3 boxes, completing the board with recursive backtracking, and removing clues while checking for multiple solutions.

Board state model

Tracks the solved board, original givens, current user entries, and cell color state through parallel 9x9 grids managed by GameLogic.

Move validation

Compares user-entered values directly against the generated solution and uses Show mode to reveal correct, incorrect, and hinted cells.

Hints and correction tools

Supports random solved-cell hints, clear-mistakes behavior, reset, and in-memory undo/redo stacks for player actions.

Local save slots

Stores one resumable game per difficulty in SharedPreferences, including board grids and elapsed time.

Have a related challenge?
Let’s talk about it.

Bring an idea, a workflow to improve, or a technical question. We can work through what comes next.