[HN Gopher] Show HN: Zsweep - Play Minesweeper using only Vim mo...
___________________________________________________________________
Show HN: Zsweep - Play Minesweeper using only Vim motions
Author : oug-t
Score : 58 points
Date : 2026-01-18 14:00 UTC (5 days ago)
(HTM) web link (zsweep.com)
(TXT) w3m dump (zsweep.com)
| oug-t wrote:
| Hi HN,
|
| I'm the creator of zsweep. It's a keyboard-centric Minesweeper
| clone where you play entirely using Vim motions (h, j, k, l to
| move; w/b to skip words; etc.).
|
| The Backstory: I wanted to build a project to get my hands dirty
| with Svelte 5 and the new Runes system. I also wanted a way to
| practice Vim muscle memory that wasn't just typing code.
|
| Tech Stack:
|
| Frontend: Svelte 5 (Runes) + SvelteKit
|
| Styling: Tailwind CSS
|
| State: Custom Finite State Machine (FSM) for the game logic
|
| The Challenge: One of the hardest parts was getting the
| "chording" logic right (where you clear multiple squares at once)
| while keeping the keyboard navigation feeling instant and "vim-
| like."
|
| It's open source, so if you're curious about how Svelte 5 handles
| game state, feel free to poke around the code:
| https://github.com/oug-t/zsweep
|
| I'd love to hear your feedback on the controls or any edge cases
| you find!
| oug-t wrote:
| Repo: https://github.com/oug-t/zsweep
| oug-t wrote:
| also trying to add features with three.js for better visual
| impressions.
| oug-t wrote:
| Play at: https://zsweep.com
| rajeshvar wrote:
| nice!
| kej wrote:
| This is a fun idea and the implementation works pretty well.
|
| The only complaint I have is that enter for clearing feels
| awkward in conjunction with hjkl movement; maybe add (d)elete and
| (f)lag as alternatives to enter and space to keep everything on
| the home row without requiring stretching?
| oug-t wrote:
| That makes a lot of sense, I will try to find alternative for
| clearing as well!
|
| Now I mainly use `space` key for both chording and flagging.
| It's the old muscle memory I inherited from playing the classic
| minesweeper game. One good thing about using the space is that,
| thumb is always available in vim motions, where other fingers
| are on the home row.
|
| Thanks for the advise!!
| unformedelta wrote:
| This was fun!
|
| It would feel a little more intuitive if w/b worked on groups of
| unrevealed tiles instead of just moving 1 space when you were
| already on an unrevealed tile. i.e. unrevealed = words, revealed
| = spaces. That way, you could also use them to meaningfully
| navigate around unrevealed groups better than using h/l. I also
| found myself missing "e" to go to the end of a word, apparently I
| use it more often than "w".
|
| I really appreciated the attention to detail though, I was
| delighted when I realized that gg/G/0/$ all worked as expected.
| oug-t wrote:
| That makes a lot of sense regarding `w/b`. I struggled a bit
| defining a word in the game cells.
|
| I'll add `e` (end of word) support in the next push, too. Thank
| a lot for the feedback!
| 1313ed01 wrote:
| It is common in traditional roguelikes to support vi keys as an
| alternative to arrow keys. I use that all the time when playing
| Brogue. Have a great vi keys muscle memory now thanks to that,
| but I use Emacs and only rarely vi, so it's not doing me much
| good.
| tcoff91 wrote:
| Use EViL mode
| lasgawe wrote:
| This is nice! love this
| oug-t wrote:
| Thanks!!!
| zahrevsky wrote:
| Too bad it doesn't display the keyboard on mobile :-(
| oug-t wrote:
| Yes, I will try to implement the mobile support for zsweep.
|
| I opened an issue on the repo regarding this, thanks for the
| feedback.
| alejoar wrote:
| Remember to exclude vimium from the site!
| oug-t wrote:
| Yes!!!
| sodacanner wrote:
| Very useful as someone who's trying to use Vim motions more
| often, thanks!
| oug-t wrote:
| Thank you!!!
|
| I will try to integrate more advanced motions inside the game!!
| QuadmasterXLII wrote:
| For reference, here are the supported motions:
| case '0': return { type: 'ZERO' }; case '_': return {
| type: 'START_ROW' }; // --- SEARCH --- case
| '/': return { type: 'START_SEARCH' }; case 'n': return {
| type: 'NEXT_MATCH' }; case 'N': return { type:
| 'PREV_MATCH' }; // --- MOVEMENT (WASD Removed) ---
| case 'h': case 'ArrowLeft': return { type: 'MOVE_CURSOR', dx:
| -1, dy: 0 }; case 'j': case 'ArrowDown': return { type:
| 'MOVE_CURSOR', dx: 0, dy: 1 }; case 'k': case 'ArrowUp':
| return { type: 'MOVE_CURSOR', dx: 0, dy: -1 }; case 'l':
| case 'ArrowRight': return { type: 'MOVE_CURSOR', dx: 1, dy: 0 };
| // --- SKIPS --- case 'w': return { type:
| 'NEXT_UNREVEALED' }; case 'b': return { type:
| 'PREV_UNREVEALED' }; // --- ACTIONS --- case
| 'i': case 'Enter': return { type: 'REVEAL' }; case ' ':
| return { type: 'SMART' }; case 'f': return { type: 'FLAG'
| }; // --- ADVANCED MOTIONS --- case '$':
| return { type: 'MOVE_CURSOR', dx: 999, dy: 0 }; case
| 'G': return { type: 'GO_BOTTOM' }; case 'g': return {
| type: 'GO_TOP' };
|
| No macros or block select yet, still fun! probably for the best
| that /mine doesn't work yet
| johnhamlin wrote:
| Love games like this. I used Vim Snake to make the muscle memory
| for hjkl finally stick in my brain. (I wish you could disable the
| insert mode toggling -- it's cute but didn't help when I was
| trying to break the habit of moving my finger up to press W or Up
| Arrow and remember that everything is in a straight line.)
|
| https://vimsnake.com
| oug-t wrote:
| Thank you!!
|
| I will add an issue for this!
| TheGRS wrote:
| Very nice, only feedback I have rn is you should keep the board
| state displayed after you hit a mine. I like to look around the
| board to see what I missed after making a mistake.
| oug-t wrote:
| Yes, after game loss, it should display all the mines and wrong
| flags marked.
|
| I opened an issue regarding to this, Thank you for the advise!!
| oug-t wrote:
| Thanks all for the feedback and upvotes!
|
| Motivated by the response, I just pushed a cleanup of the repo to
| make it easier to build and run locally.
|
| I am now opening issues for the specific requests mentioned here
| --like adding the `e` motion, improving `w/b` logic, and
| preserving the board state when game over.
|
| Thank you again, PRs are very welcome!!
|
| Repo: https://github.com/oug-t/zsweep
| schmooser wrote:
| Reaching RET to open a block is too far from the home row, very
| unpleasant. C-m (Control-M) is much better and supported by both
| vim and Emacs.
___________________________________________________________________
(page generated 2026-01-23 23:00 UTC)