Skip to content

Repository files navigation

Blackjack Clone

A modern, interactive Blackjack game built with Next.js, React, and TypeScript. This project implements a complete casino-style Blackjack game with a 6-deck shoe, standard game rules, and a polished user interface.

Features

  • Full Blackjack Gameplay

    • Standard casino rules with 6-deck shoe
    • Player actions: Hit, Stand, Double Down, Split
    • Dealer AI that follows standard rules (stands on 17)
    • Automatic win/loss detection and payout calculation
  • Game Mechanics

    • Initial balance: $1,000
    • Betting system with customizable bet amounts
    • Payout multipliers:
      • Blackjack win: 2.5x
      • Normal win: 2x
      • Push: 1x (bet returned)
      • Loss: 0x
  • User Interface

    • Responsive design (mobile and desktop)
    • Card animations and visual feedback
    • Game state indicators
    • Payout rules display
    • Game statistics tracking
  • Technical Implementation

    • TypeScript for type safety
    • React Context API for state management
    • Custom game engine with Fisher-Yates shuffle algorithm
    • Component-based architecture
    • Tailwind CSS for styling

Tech Stack

  • Framework: Next.js 16.0.3
  • React: 19.2.0
  • TypeScript: 5.x
  • Styling: Tailwind CSS 4.1.9
  • Build Tool: Next.js built-in bundler

Getting Started

Prerequisites

  • Node.js 18+ (recommended: latest LTS version)
  • npm, yarn, pnpm, or bun

Installation

  1. Clone the repository:
git clone <repository-url>
cd shuffle-blackjack-clone
  1. Install dependencies:
npm install
# or
yarn install
# or
pnpm install
# or
bun install
  1. Run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
  1. Open http://localhost:3000 in your browser to see the game.

Building for Production

npm run build
npm start

Project Structure

shuffle-blackjack-clone/
├── app/                    # Next.js app directory
│   ├── page.tsx           # Main game page
│   ├── layout.tsx         # Root layout
│   └── globals.css        # Global styles
├── components/            # React components
│   ├── BetButton/        # Betting button component
│   ├── BetInput/         # Bet amount input
│   ├── CardUI/           # Card display component
│   ├── DoubleButton/     # Double down action
│   ├── GameStats/        # Game statistics display
│   ├── GameTable/        # Main game table container
│   ├── HandUI/           # Hand display component
│   ├── HitButton/        # Hit action button
│   ├── PlayButton/       # Start round button
│   ├── SplitButton/      # Split action button
│   ├── StandButton/      # Stand action button
│   └── ui/               # Reusable UI components
├── constants/            # Game constants
│   └── blackjack.ts      # Blackjack rules and constants
├── contexts/             # React Context providers
│   └── game-context.tsx  # Game state management
├── lib/                  # Core game logic
│   ├── game-engine.ts    # Game engine implementation
│   └── utils.ts          # Utility functions
└── parts/                # Composite components
    ├── BetControl/       # Betting controls
    ├── BlackjackActionsWrapper/  # Action buttons wrapper
    ├── ControlsWrapper/  # Controls container
    └── HandsWrapper/     # Hands display container

Game Rules

  • Objective: Get as close to 21 as possible without going over, and beat the dealer's hand.
  • Card Values:
    • Number cards (2-10): Face value
    • Face cards (J, Q, K): 10
    • Ace: 1 or 11 (automatically chosen for best hand)
  • Dealer Rules: Dealer must hit on 16 and stand on 17 or higher.
  • Blackjack: 21 with first two cards (Ace + 10-value card) pays 2.5x.
  • Double Down: Double your bet and receive exactly one more card.
  • Split: When you have two cards of the same rank, you can split them into two separate hands.

Features to Implement

Split Feature

Status: Not implemented (UI component exists but disabled)

Requirements:

  • State Management (contexts/game-context.tsx)

    • Add support for multiple player hands in GameState (currently only single playerHand)
    • Add activeHandIndex or similar to track which hand is currently being played
    • Add START_PLAYER_SPLIT and FINISH_PLAYER_SPLIT actions
    • Update reducer to handle split logic:
      • Split the two-card hand into two separate hands
      • Add a second bet equal to the original bet
      • Deduct the second bet from balance
      • Deal one card to each split hand
      • Handle turn-based play for multiple hands
  • Game Engine (lib/game-engine.ts)

    • canSplit() method already exists and checks eligibility
    • Add method to split a hand into two hands (if needed)
    • Update comparison logic to handle multiple player hands
    • Ensure split hands are evaluated independently
  • UI Components

    • Update SplitButton (components/SplitButton/index.tsx) to:
      • Check if split is available using gameEngine.canSplit()
      • Enable/disable based on game state and hand eligibility
      • Dispatch split action on click
    • Update HandUI (components/HandUI/index.tsx) to display multiple hands
    • Update HandsWrapper to show all player hands with active hand indicator
    • Ensure actions (Hit, Stand, Double) work on the active hand only
  • Rules to Implement:

    • Split can only be done on initial two-card hand
    • Each split hand requires an equal bet
    • After splitting, player plays each hand independently
    • If both split hands win, player wins both bets
    • If dealer has blackjack, all hands lose (including split hands)
    • Standard rule: Cannot double after split (already enforced in canDouble)

Current State:

  • SplitButton component exists but is disabled (splitButtonDisabled = true)
  • gameEngine.canSplit() method is implemented and functional
  • Game state only supports single player hand

Insurance Feature

Status: Not implemented

Requirements:

  • State Management (contexts/game-context.tsx)

    • Add insuranceBet field to GameState
    • Add insuranceOffered boolean flag
    • Add START_INSURANCE and FINISH_INSURANCE actions
    • Update FINISH_INITIAL_DEAL to check if dealer shows Ace
    • Add insurance payout logic when dealer has blackjack
  • Game Engine (lib/game-engine.ts)

    • Add method to check if insurance should be offered (dealer's first card is Ace)
    • Add method to calculate insurance payout (2:1 if dealer has blackjack)
    • Update result comparison to handle insurance bets separately
  • UI Components

    • Create InsuranceButton component (components/InsuranceButton/index.tsx)
    • Create InsuranceInput or similar for insurance bet amount
    • Display insurance offer when dealer shows Ace
    • Show insurance bet amount in game stats
    • Display insurance win/loss result
  • Rules to Implement:

    • Insurance is offered when dealer's up card is an Ace
    • Insurance bet is up to half of the original bet
    • Insurance pays 2:1 if dealer has blackjack
    • Insurance bet is independent of main bet outcome
    • If dealer has blackjack:
      • Main bet loses (unless player also has blackjack = push)
      • Insurance bet wins 2:1
    • If dealer does not have blackjack:
      • Insurance bet loses
      • Main hand continues normally

Current State:

  • No insurance-related code exists
  • Need to detect dealer Ace after initial deal
  • Need to pause game flow to offer insurance before revealing dealer's hole card

Development

Linting

npm run lint

Code Style

The project uses ESLint with Next.js configuration. TypeScript strict mode is enabled for type safety.

Acknowledgments

Game engine implements standard casino Blackjack rules with a 6-deck shoe system.

About

A modern, interactive Blackjack game built with Next.js, React, and TypeScript. Features casino-style rules, betting system, and polished UI.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages