🐍 nsnake
A clean, polished, cross-platform terminal Snake game built from scratch in Python.
_ _ ___ _ _ __ _ _ ____
|\ | |__ |\ | /__\ |_/ |___
| \| ___|| \|/ \ | \_ |___
"Snake is one of those games that doesn't need an explanation. You move, you eat, you grow, and eventually you make one terrible turn."
🐍 About the Project
This project is my own recreation of the classic Snake game many of us grew up playing.
The inspiration came from exploring terminal-based games like nsnake and asking myself:
"What if I built my own version of this from the ground up?"
The goal wasn't to invent a completely new game concept. Instead, I wanted to take a deeply nostalgic, familiar game and rebuild it cleanly for the modern terminal—focusing on clean code architecture, decoupled game engine design, terminal rendering, state management, cross-platform compatibility, and unit test coverage.
It turned out to be a fantastic learning project that taught me much more than just making a snake move around a grid.
✨ Features
- 🐍 Classic Gameplay Mechanics: Smooth 2D grid movement, continuous velocity, non-reversing direction locks, and growth upon eating food.
- 🎮 Dual Keyboard Controls: Full support for both Arrow Keys and WASD.
- 🎨 Terminal UI with Matrix Animation: Centered ASCII logo with a live, real-time Matrix "Snake Rain" background particle animation on the main menu.
- 🗺️ 9 Map Layouts:
- Classic (Open field)
- Progressive (Evolving) (Map dynamically spawns new obstacle tiers as your score increases!)
- The Cage (Central box frame with gateways)
- Crossfire (Center-cleared cross arms)
- Pillars (4 corner blocks)
- Tunnels (Dual horizontal divider walls)
- Whirlpool (Spiral walls extending inward)
- Labyrinth (Multi-lane corridor maze)
- Grid Matrix (Checkerboard barrier blocks)
- Fortress (Double ring walls with staggered gates)
- ⭐ Bonus Food & Power-Ups: Golden Bonus Stars (
★) spawn periodically with a countdown timer, awarding +30 PTS extra bonus score. - ⚡ Dynamic Speed Scaling: Speed levels 1 to 10 that automatically accelerate as you eat more food.
- 🛡️ Custom Wall Modes: Toggle between Solid Boundaries (Die) and Wrap Around (Teleport) modes in settings.
- 🎨 GUI Customization: Customize Snake Head (
@,O,0,X,▲), Body (o,#,*,+,=), and Food ($,*,@,♥,♦) symbols. - 📊 Lifetime Statistics: Tracks Games Played, Highest Score, Average Score, Total Food Eaten, Bonus Food Eaten, and Longest Snake achieved.
- 💾 Persistent Data: Automatic JSON persistence for scores, settings, and lifetime stats stored in
~/.config/nsnake/. - 🖥️ Cross-Platform: Native
cursessupport on Linux and macOS, with automaticwindows-cursesadaptation on Windows.
🖥️ Terminal Experience
Here is a visual representation of the arcade gameplay in action:
┌─nsnake 0.1.0─────────────────────────────Progressive (Solid Wall)─┐
│ │
│ oo@ ★ (18) │
│ $ │
│ │
│ # # # # # # │
│ # # # # # # │
│ │
├──────────────────────────────────────────────────────────────────┤
│ Hi-Score: 450 Score: 120 Speed: 5 ★ BONUS(18) │
└──────────────────────────────────────────────────────────────────┘
🚀 Installation
Option 1: Install directly with pip / pipx
You can install and run the game directly from GitHub:
# Using pip
pip install git+https://github.com/chvsaicharan/nsnake.git
# Or using pipx (recommended for isolated CLI tools)
pipx install git+https://github.com/chvsaicharan/nsnake.git
Option 2: Clone and Install Locally
# 1. Clone the repository
git clone https://github.com/chvsaicharan/nsnake.git
cd nsnake
# 2. Install package in editable mode
pip install -e .
# 3. Launch the game
snake
Or run directly with Python:
python3 -m snake
🎮 Controls
| Key | Action |
|---|---|
↑ ↓ ← → / W A S D |
Move Snake / Navigate Menus |
Enter / Space |
Select Menu Option / Action |
P |
Pause / Resume Game |
R |
Restart Game |
Q / Esc |
Quit Game / Return to Main Menu |
🧩 Architecture
The project is strictly separated into a pure Python core engine (100% decoupled from terminal code) and a curses rendering UI layer, ensuring every piece of game logic can be unit-tested cleanly.
flowchart TD
Input[Keyboard Input Driver\nterminal.py] --> GameLoop[Game Loop / CLI\ncli.py]
Food[Food & Bonus Spawner\nfood.py] --> GameLoop
GameLoop --> Snake[Snake Engine\nsnake.py]
GameLoop --> Collision[Board & Map Collision\nboard.py / maps.py]
GameLoop --> Renderer[Curses Renderer\nrenderer.py]
GameLoop --> Score[Scores & Stats Storage\nscores.py / stats.py]
Module Breakdown
nsnake/
├── pyproject.toml # Package metadata & `snake` entrypoint
├── README.md
├── src/
│ └── snake/
│ ├── __init__.py
│ ├── __main__.py # Entrypoint launcher
│ ├── cli.py # Application tick loop & state switcher
│ ├── config.py # User settings configuration (~/.config/nsnake/settings.json)
│ ├── core/ # Pure Game Engine (Zero UI dependencies)
│ │ ├── vector.py # 2D Grid coordinates & direction math
│ │ ├── snake.py # Snake body, movement, growth & self-collision
│ │ ├── food.py # Standard Food & Bonus Food spawners
│ │ ├── board.py # Grid bounds & obstacle checks
│ │ ├── maps.py # 9 Map layout generators & progressive map engine
│ │ └── game.py # Game state machine, scoring, speed scaling
│ ├── ui/ # Curses UI & Rendering Engine
│ │ ├── terminal.py # Curses screen init, color pairs, key input reader
│ │ └── renderer.py # Matrix Snake Rain animation, board frame, menus & popups
│ └── storage/ # Persistence Layer
│ ├── scores.py # High score storage (~/.config/nsnake/scores.json)
│ └── stats.py # Lifetime statistics storage (~/.config/nsnake/stats.json)
└── tests/ # Unit test suite (24 tests)
├── test_vector.py
├── test_snake.py
├── test_board.py
├── test_food.py
├── test_game.py
├── test_scores.py
├── test_config.py
├── test_stats.py
└── test_maps.py
🧠 What I Learned
Building this project provided hands-on experience with several core software engineering concepts:
- Decoupled Architecture: Keeping game logic strictly separate from curses rendering allowed me to write comprehensive unit tests without spawning terminal interfaces.
- State Machine Pattern: Managing transitions cleanly between
MENU,RUNNING,PAUSED, andGAME_OVERstates. - Real-Time Frame Loops: Managing non-blocking input polling (
nodelay) and tick intervals (from 150ms down to 42ms) to achieve smooth game performance at 60 FPS without high CPU usage. - Algorithmic Safety: Designing a Safe Spawn Clearance Zone algorithm so map obstacle generators and food spawners never overlap with the snake's starting position or body.
- Cross-Platform Compatibility: Handling terminal differences across Linux, macOS, and Windows seamlessly via
windows-cursesconditional packaging. - Automated Testing: Writing a 24-test suite using standard
unittestto prevent regressions.
🎨 Why Terminal?
There is something deeply satisfying about opening a terminal, typing snake, and instantly jumping into a game using nothing but your keyboard.
No heavy graphical desktop engines, no loading screens—just pure retro arcade fun inside your favorite terminal emulator.
🛠️ Tech Stack
- Language: Python 3.10+
- Terminal UI Driver:
curses(Unix) /windows-curses(Windows) - Build System:
setuptools(pyproject.toml) - Testing: Python Standard Library
unittest - Persistence: JSON
🧪 Testing
The project includes an automated test suite covering vector math, snake movement, wall/obstacle collision, food spawning, state transitions, configuration persistence, and map safety.
Run the tests using standard unittest:
PYTHONPATH=src python3 -m unittest discover -s tests
Output:
........................
----------------------------------------------------------------------
Ran 24 tests in 0.005s
OK
🗺️ Future Ideas
- Additional obstacle maps and custom user-designed maps.
- Sound effects / bell notifications for bonus food.
- Local 2-player split-keyboard mode.
- PyPI publishing (
pip install nsnake).
❤️ The Fun Part
Why build Snake when Snake already exists?
Because sometimes the best way to learn software engineering is to take something simple, rebuild it yourself, and do it right.
This project was genuinely fun to build. From watching the snake segments finally follow the head correctly without tearing, to designing the Matrix falling snake animation, getting the terminal box frames aligned, and watching the test suite turn all green—it was a rewarding project from start to finish.
👨💻 Author
Sai Charan
- GitHub: @chvsaicharan
⭐ Closing
$ snake
> Initializing curses driver...
> Loading settings & high scores...
> Spawning food...
> Ready.
🐍 Have fun.
Release files for nsnake 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nsnake-0.1.0.tar.gz | 30.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nsnake-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 53.5 kB
Release files / nsnake-0.1.0.tar.gz
| Download URL | nsnake-0.1.0.tar.gz |
|---|---|
| Size | 30.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5c35af61a8b9247a4bf6e1687453da075447e1561064c2bad3f90b06a51021c3
|
|
BLAKE2b-256 checksum How to use checksums |
c0c69bd8116b1435b579644cab201745442818fcc3aaa692d6e9a2d44d6bb904
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / nsnake-0.1.0-py3-none-any.whl
| Download URL | nsnake-0.1.0-py3-none-any.whl |
|---|---|
| Size | 23.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d1e3286ee78a31e0a604a70e99c1633b83db7ae6a6dc07e5aadc40bdfc4c91dc
|
|
BLAKE2b-256 checksum How to use checksums |
c237fceec6eb555f4d133c21fefb4ca96ede6c3c204091efff70d810913308b7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|