[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)