The project recreates the classic logic-based number-placement puzzle using Python. The objective is to fill a 9×9 grid with digits so that each column, each row, and each of the nine 3×3 boxes that compose the grid contain all of the digits from 1 to 9.
It is an interactive game featuring dynamic board generation, input validation system, a hint mechanic, and a recursive backtracking solver that can complete any puzzle instantly.
- Dynamic Difficulty: The game includes four difficulty levels (Very Easy, Easy, Medium, Hard). The board is generated by first creating a valid full solution and then removing a specific range of numbers based on the chosen difficulty.
- Hint System: Players are not left stuck. They can request a hint (
h), which fills the first empty cell with the correct number. The players can accumulate up to a maximum of 7 hints, and they earn new hints by successfully filling in 3 cells on their own. - Recursive Backtracking Solver: If a player chooses to surrender (
s), the game utilizes a recursive backtracking algorithm. This algorithm tries numbers 1-9 in empty cells, moves forward if valid, and "backtracks" to the previous cell if it hits a dead end. - Timer & Leaderboard: Tracks completion time. Top scores are saved in a local SQLite database and displayed on a color-coded leaderboard (🥇 Gold, 🥈 Silver, 🥉 Bronze).
- Save/Continue Game: Don't lose your progress. You can easily save multiple games with custom names and resume them exactly where you left off.
- UI: The game uses the
shutillibrary to detect terminal size and dynamically center the board. Features ASCII art titles (viapyfiglet).
Played entirely using the keyboard (coordinate-based). Input format: Row_number Column_number Number_to_be_entered (e.g., 1 2 5). Special commands:
- s : Surrender and view the final solution.
- h : Use a hint (fills first empty cell).
- e : Exit to main menu (prompts to save game progress).
The project is organized into a clean, modular structure:
game.py: The application entry point. Handles the main menu, difficulty selection, and primary game loop.requirements.txt: Lists the external dependencies (pyfiglet).vercel.json: Configuration for the serverless API deployment.
modules/database.py: Handles SQLite (local saves) and API calls (global leaderboard).modules/ui.py: Handles terminal rendering, colors, and centered text.modules/sudoku_logic.py: Contains the Sudoku generation and solving algorithms.
tests/test_game.py: Unit tests usingpytestto verify core game logic.
api/index.py: Python Flask application that connects to the Neon PostgreSQL database.api/requirements.txt: Dependencies for the Vercel-hosted API.
Lists the external dependencies required to run the project.
pyfiglet: Used for generating the large ASCII art headers in the menus.psycopg2-binary: Used for connecting to the remote Neon PostgreSQL database.python-dotenv: Used for securely loading the.envdatabase connection string.
The game uses a hybrid database architecture:
- Public Leaderboard (Neon PostgreSQL): All high scores are saved to a global cloud database, allowing players to compete globally.
- Private Game Saves (SQLite): All in-progress saved games are stored securely on the user's local machine, ensuring privacy and ownership over save data.
One of the key challenges was displaying the board neatly in a terminal. I spent a lot of time trying to make it look clean and centred. I chose to use shutil.get_terminal_size() to calculate padding dynamically. This prevents the board from looking "stuck" to the left side of the screen on large monitors.
For the input system, I decided against a cursor-based navigation system and instead opted for a coordinate-based input. To make this user-friendly, I implemented robust input validation using Regular Expressions that handles extra spaces and invalid formats gracefully without crashing the game.
The solver uses a standard backtracking approach because it is the most efficient and mathematically guaranteed way to solve a standard 9x9 Sudoku grid. This also allowed me to implement the "Generator" by simply seeding a blank board with random numbers and asking the solver to fill the rest.
Clone the repository to your local machine, then install the required dependencies:
git clone https://github.com/your-username/python-sudoku.git
cd python-sudoku
pip install -r requirements.txtYou are all set! The local SQLite database (sudoku_stats.db) will be generated automatically the first time you run the game.
python game.pyIf you want to host your own version of the global leaderboard API, you can deploy the included api/ directory for free on Vercel.
- Create a free PostgreSQL database on Neon (neon.tech).
- Run
init_neon_db.sqlin your Neon SQL Editor to create thescorestable. - Import this repository into Vercel.
- In your Vercel project settings, add an Environment Variable named
DATABASE_URLwith your Neon connection string. - Once your Vercel project deploys, copy your new API URL and replace
API_URLinsidedatabase.py.