What You'll Build
- A 2048 puzzle game with:
- A 4x4 grid with numbered tiles that merge
- Arrow key and swipe controls for moving tiles
- Score counter and best score tracking
- Game over detection when no moves remain
- Smooth sliding and merging animations
- A clean, modern tile design with distinct colors per value
Tool: Cursor (no coding needed) Difficulty: Beginner Time: ~20 minutes Coding required: None
2048 is one of the most addictive puzzle games ever made. You slide numbered tiles around a 4x4 grid — when two tiles with the same number collide, they merge into one tile with double the value. The goal is to reach the 2048 tile, but most players keep going to see how high they can get. It's simple to learn and impossible to put down.
This is a great beginner vibe coding project because the game has clear rules that translate well into a prompt. Cursor's agent can handle the grid logic, tile merging, animation, and responsive design from a single detailed prompt. You'll have a fully playable 2048 clone in minutes, then refine it step by step.
What You Need
The Founding Prompt
Open Cursor and start a new project. In the agent chat, paste this prompt:
Build a 2048 puzzle game using React and TypeScript that runs in the browser. Grid: A 4x4 grid of tiles on a rounded container with a warm gray background (#bbada0). Empty cells show as slightly darker rounded squares. Tiles display their number centered in the cell. Tile colors: Each tile value gets a distinct background color and text color: - 2: #eee4da (dark text), 4: #ede0c8 (dark text), 8: #f2b179 (white text) - 16: #f59563 (white text), 32: #f67c5f (white text), 64: #f65e3b (white text) - 128: #edcf72 (white text), 256: #edcc61 (white text), 512: #edc850 (white text) - 1024: #edc53f (white text), 2048: #edc22e (white text) - Tiles above 2048 should be dark (#3c3a32) with white text. Font: Use a bold sans-serif font. Tile text size should shrink for 4+ digit numbers so they fit. Controls: Arrow keys to move tiles. All tiles slide in the pressed direction. Tiles with the same value merge into one tile with double the value. After each move, spawn a new tile (90% chance of 2, 10% chance of 4) in a random empty cell. Scoring: Display "Score" and "Best" counters above the grid. Add merged tile values to the score. Save best score to localStorage. Show a "+N" floating animation above the score when points are added. Game states: - Win: Show a translucent overlay saying "You Win!" with a "Keep Playing" button when the player reaches 2048. - Game Over: Show an overlay saying "Game Over!" with a "Try Again" button when no valid moves remain. - Include a "New Game" button above the grid that resets everything (except best score). Animations: Tiles should slide smoothly to their new position (150ms ease). New tiles should pop in with a scale animation (0 to 1 over 200ms). Merging tiles should briefly scale up to 1.2x then back to 1x. Mobile support: Add swipe gesture detection (touchstart/touchend with minimum 30px threshold) for up/down/left/right movements. The grid should be centered and responsive, filling up to 500px wide on desktop and the full width (with padding) on mobile.
Click Generate and wait for Cursor to build your game.
Step 1: Run and Test the Game
Start the dev server in Cursor's terminal and open the preview. Use arrow keys to slide tiles around. Verify that tiles merge correctly (two 2s make a 4, two 4s make an 8), new tiles spawn after each move, and the score updates when tiles merge.
Step 2: Fix Tile Animations
The merging and sliding animations need to feel snappy and polished. Test them and refine if they look off.
Improve the tile animations. Sliding tiles should move smoothly to their target cell over 120ms with an ease-out curve. When two tiles merge, the resulting tile should pop (scale to 1.15x over 100ms, then back to 1x over 100ms). New tiles should appear with a quick pop-in (scale from 0.5 to 1 over 150ms with a slight overshoot). Make sure animations don't stack or conflict — a tile that just merged should not also play the new-tile animation.
Step 3: Add an Undo Button
Players love being able to take back a bad move. Add an undo feature that remembers the previous state.
Add an "Undo" button next to the "New Game" button. When clicked, it reverts the grid, score, and tile positions to the state before the last move. Only allow one level of undo (can't undo twice in a row). Disable the undo button (grayed out) when there's nothing to undo or when the player just used it. Store the previous state in memory, not localStorage.
Step 4: Add Visual Polish
Small visual details make the game feel professional and satisfying to play.
Add visual polish to the game. Add a subtle drop shadow to each tile. Add a background gradient to the page (dark warm gray at top to slightly lighter at bottom). Style the "New Game" and "Undo" buttons as rounded pill buttons with hover effects. Add a header above the grid with the title "2048" in large bold text on the left and the score boxes on the right. Below the title, add a subtitle: "Join the numbers and get to the 2048 tile!" in smaller gray text.
Step 5: Add Sound Effects
Subtle audio feedback makes each move feel more impactful.
Add sound effects using the Web Audio API. Play a soft slide sound when tiles move. Play a satisfying pop sound when tiles merge — make the pitch slightly higher for higher-value merges. Play a chime when the player reaches 2048. Play a soft thud on game over. Add a mute/unmute toggle icon in the top-right corner. Sounds should be very subtle and short (under 200ms each) so they don't become annoying during fast play.
Step 6: Make It Fully Mobile Friendly
Swipe controls need to feel natural on touch devices, and the layout should adapt perfectly.
Improve the mobile experience. Swipe detection should work reliably with a 30px minimum distance threshold and ignore swipes that are more diagonal than directional. Prevent the page from scrolling when swiping on the game grid (use touch-action: none on the grid container). The grid should have 16px padding on mobile. Score boxes should stack horizontally and stay readable on small screens. Add haptic feedback using navigator.vibrate(10) on each valid move if the API is available. Prevent pull-to-refresh on mobile browsers when swiping down.
Step 7: Deploy and Share
Push your project to GitHub from Cursor's terminal and deploy it with npx vercel. You'll get a live URL — share it with friends and family and see who can reach the highest tile.
Level Up Your Game
Try these follow-up prompts to make your game even better:
Add difficulty levels:
Add a grid size selector before starting: 3x3 (harder — less space), 4x4 (classic), 5x5 (easier — more room). Adjust the target tile for each size: 512 for 3x3, 2048 for 4x4, 4096 for 5x5. Save separate best scores for each grid size.
Add a timer:
Add a move counter and elapsed time display next to the score. The timer starts on the first move and pauses on game over or win. Show both stats on the game over and win overlays. Track the fewest moves and fastest time to reach 2048 as records in localStorage.
Add animations:
Add a subtle background color shift as the highest tile on the board increases — warm beige for low values, transitioning to warmer oranges and reds as values climb. Add a confetti burst when reaching 2048. Add a gentle board shake when a move results in no tile movement (invalid move feedback).
Add high score saving:
Save the top 10 scores to localStorage with the date, highest tile reached, and number of moves. Add a "Leaderboard" button next to "New Game" that opens a modal showing the ranking table. Highlight the current game's score if it's in the top 10. Add a "Share Score" button that copies a text summary to the clipboard.
Add tile themes:
Add a theme selector with 3 options: Classic (default warm colors), Dark Mode (dark gray tiles with neon-colored numbers), and Pastel (soft pastel tile colors). Save the selected theme to localStorage. Apply the theme to tiles, background, and buttons. Add a palette icon button in the top corner to toggle between themes.
Want persistent high scores? Follow our leaderboard guide to connect your game to a database.
Common Errors
Blank screen after prompt If Cursor generates a blank screen, add to your prompt: "Make sure the game renders immediately on page load with no user setup required."
Game not responding to keyboard Add to your prompt: "Ensure keyboard event listeners are attached to the document, not a specific element. Auto-focus the game container on load."
Mobile touch controls not working Add to your prompt: "Add touch event handlers for mobile. Include visible on-screen buttons for all controls on screens under 768px wide."