Skip to contents

Introduction

Welcome to the Blackjack game vignette! This package allows you to simulate a full round of Blackjack with multiple players. Players can perform actions like hitting, standing, splitting, doubling down, and even making insurance bets. The game follows classic Blackjack rules, with enhancements for player interaction.

This vignette will walk you through:

  • An overview of Blackjack rules

  • How to install and load the package

  • How to play the game interactively

  • How to use individual functions

⚙️ Setup

To start using the Blackjack package, you need to install it. If you haven’t done so yet, you can install the package from GitHub. For detailed instructions, please refer to the installation guide on the homepage.

Once installed, you can load the package using:

Blackjack Rules

Blackjack, also known as 21, is a popular card game played between a dealer and one or more players. The goal of the game is to have a hand total that is closer to 21 than the dealer’s hand, without going over 21 (which is known as “busting”).

The Card Values

  • Aces: Can be worth 1 or 11, depending on the hand.
  • Number cards (2-10): Worth their face value.
  • Face cards (J, Q, K): Worth 10 points each.

Gameplay

  1. Dealing the Cards: Each player is dealt two cards, and the dealer is dealt two cards. One of the dealer’s cards is face-up (the “upcard”), and the other is face-down (the “hole card”).

  2. Player’s Turn: Each player takes turns to play their hand. They have the following options:

    • Hit: Draw another card from the deck to improve their hand.
    • Stand: Keep the current hand and end their turn.
    • Double Down: Double the bet and receive exactly one more card.
    • Split: If the player has two cards of the same rank, they can split them into two hands and continue playing each hand individually.
  3. Dealer’s Turn: After all players have completed their turns, the dealer reveals their hole card and plays according to these rules:

    • The dealer must hit if their total is 16 or less.
    • The dealer must stand if their total is 17 or higher.
    • If the dealer gets 21, they have a “Blackjack.”
  4. Winning: The player wins if their hand total is closer to 21 than the dealer’s without busting. If both the player and dealer have the same total, it’s a tie (push). If the dealer busts, the player wins.

▶️ Start experimenting and playing the game!

By using play_blackjack(), you will be able to enter the world of Blackjack!

This function allows you to play a full interactive game of Blackjack. This function handles the following:

  1. Setup: Prompts the user for the number of players and decks, and initializes the deck and hands.
  2. Gameplay: Guides each player through their turn, including options to hit, stand, double down, and split.
  3. Dealer’s Play: Handles the dealer’s turn according to Blackjack rules.
  4. Outcome: Announces the winner for each player based on the final hand values.

Example Gameplay

To play a full interactive round of Blackjack, run:

Here’s what a typical interactive session might look like when running play_blackjack():

🎮 Welcome to Blackjack!

🎲 How many players? 3

🃏 How many decks? (Enter for default):

🤵 Dealer shows: 3♣

👤 Player1 initial hand: 9♦, Q♠

➤ Do you want to surrender? (y/n): n

➤ Current hand: 9♦, Q♠ ( 19 )

➤ Hit or stand? (h/s): h

➤ Current hand: 9♦, Q♠, A♥ ( 20 )

➤ Hit or stand? (h/s): s

→ Final score: 20

👤 Player2 initial hand: 8♦, 7♣

➤ Do you want to surrender? (y/n): n

➤ Current hand: 8♦, 7♣ ( 15 )

➤ Hit or stand? (h/s): h

→ Final score: 25 💥 BUST!

👤 Player3 initial hand: K♥, Q♣

➤ Do you want to surrender? (y/n): n

➤ Current hand: K♥, Q♣ ( 20 )

➤ Hit or stand? (h/s): s

→ Final score: 20

🤵 Dealer’s full hand: 3♣, 9♦

✅ Dealer’s final hand: 3♣, 9♦, 10♠

➡ Dealer score: 22 💥 BUST!

👤 Player1 : Win

👤 Player2 : Lose

👤 Player3 : Win

Created on 2025-06-05 with reprex v2.1.1

This example illustrates how multiple players can take actions (hit, stand, surrender), and how the dealer automatically plays their hand. Results are calculated based on Blackjack rules and shown at the end of the round.

🧩 Using Helper Functions

You can also manually test or explore game logic using core functions:

Create Deck

deck <- create_board(num_decks = 1)
head(deck)
#> [1] "Q♠"  "6♦"  "3♣"  "10♠" "10♥" "Q♦"

Deal Cards

hands <- deal_cards(num_players = 2, deck)
hands$player_hands
#> [[1]]
#> [1] "Q♠" "6♦"
#> 
#> [[2]]
#> [1] "3♣"  "10♠"
hands$dealer_hand
#> [1] "10♥"

Score a Hand

score_hand(c("A♠", "K♦")) # Returns 21
#> [1] 21

Split a Hand

player_split(c("8♠", "8♦"))
#> $can_split
#> [1] TRUE
#> 
#> $hands
#> $hands[[1]]
#> [1] "8♠"
#> 
#> $hands[[2]]
#> [1] "8♦"

Surrender

surrender_hand(c("10", "6"), TRUE)
#> $status
#> [1] "surrendered"
#> 
#> $payout
#> [1] 0.5
#> 
#> $message
#> [1] "Player surrendered. Half bet lost."

Double Down

dd_result <- double_down(c("5♠", "6♠"), create_board())
dd_result$new_hand
#> [1] "5♠" "6♠" "8♦"

Dealer Play

dealer_play(c("7♠", "9♦"), create_board())
#> $dealer_hand
#> [1] "7♠" "9♦" "J♣"
#> 
#> $deck
#>   [1] "A♣"  "8♦"  "9♥"  "6♦"  "Q♥"  "6♠"  "K♥"  "5♥"  "10♥" "7♣"  "8♣"  "K♠" 
#>  [13] "Q♠"  "5♥"  "Q♣"  "2♦"  "8♦"  "2♥"  "8♠"  "3♣"  "2♣"  "9♦"  "8♣"  "10♣"
#>  [25] "6♦"  "Q♥"  "8♥"  "8♦"  "4♥"  "7♦"  "K♣"  "9♣"  "8♠"  "J♥"  "Q♠"  "A♠" 
#>  [37] "3♣"  "8♥"  "Q♣"  "6♥"  "Q♦"  "7♠"  "7♥"  "9♦"  "10♦" "J♠"  "A♥"  "3♠" 
#>  [49] "10♠" "3♥"  "6♥"  "2♣"  "7♦"  "9♥"  "5♦"  "K♣"  "J♣"  "10♠" "J♣"  "2♣" 
#>  [61] "4♦"  "J♥"  "5♣"  "K♠"  "Q♠"  "2♥"  "9♠"  "5♠"  "4♠"  "2♠"  "9♦"  "4♣" 
#>  [73] "J♦"  "2♥"  "8♣"  "K♠"  "5♣"  "K♥"  "A♣"  "A♠"  "5♣"  "J♥"  "9♠"  "4♥" 
#>  [85] "10♦" "4♥"  "A♥"  "3♣"  "6♥"  "K♥"  "Q♥"  "7♣"  "4♣"  "7♠"  "10♣" "10♥"
#>  [97] "Q♦"  "9♣"  "2♦"  "7♥"  "2♥"  "A♠"  "4♠"  "9♣"  "7♦"  "7♠"  "10♠" "3♠" 
#> [109] "8♠"  "2♦"  "3♦"  "K♥"  "A♥"  "K♠"  "5♥"  "4♠"  "2♣"  "2♠"  "8♠"  "3♦" 
#> [121] "3♠"  "A♦"  "A♣"  "4♣"  "5♠"  "7♥"  "10♥" "5♠"  "J♦"  "2♦"  "Q♠"  "10♥"
#> [133] "10♣" "3♥"  "6♠"  "3♠"  "K♦"  "9♣"  "7♣"  "6♠"  "Q♦"  "10♠" "A♦"  "5♦" 
#> [145] "Q♣"  "3♦"  "9♥"  "6♣"  "9♠"  "8♣"  "6♥"  "10♦" "4♦"  "6♣"  "A♦"  "6♣" 
#> [157] "J♠"  "7♠"  "3♥"  "5♦"  "7♦"  "J♠"  "3♦"  "J♥"  "9♥"  "Q♥"  "4♣"  "2♠" 
#> [169] "6♠"  "10♦" "8♥"  "Q♦"  "6♦"  "K♦"  "2♠"  "5♣"  "A♦"  "J♦"  "3♥"  "9♦" 
#> [181] "K♣"  "K♦"  "5♦"  "A♥"  "A♠"  "5♥"  "8♥"  "K♦"  "8♦"  "J♠"  "Q♣"  "6♣" 
#> [193] "9♠"  "K♣"  "A♣"  "4♦"  "7♣"  "3♣"  "4♥"  "6♦"  "7♥"  "5♠"  "J♦"  "10♣"
#> [205] "4♦"  "4♠"  "J♣"

Advanced: Custom Card Vector

To manage cards in a more structured way, this package includes a custom vctrs-based class called card_vector. This class allows you to work with cards while maintaining strong type consistency and formatting.

Create a card vector

You can create a card_vector from a character vector of cards:

deck <- card_vector(c("A♠", "10♣", "K♥"))
deck
#> <card_vector[3]>
#> [1] [A♠]  [10♣] [K♥]

Coercion Methods

You can safely convert between card_vector and base types using vctrs coercion:

# Convert to character
as.character(deck)
#> [1] "A♠"  "10♣" "K♥"

# Convert from character to card_vector
char_deck <- c("Q♥", "8♣")
vec_cast(char_deck, to = card_vector())
#> [1] "Q♥" "8♣"

Extract Card Ranks and Suits

card_rank(deck)  
#> [1] "A"  "10" "K"
card_suit(deck)  
#> [1] "♠" "♣" "♥"

Check for face cards

card_is_face(deck)  # FALSE FALSE TRUE
#> [1] FALSE FALSE  TRUE

Type Compatibility

The card_vector integrates smoothly with vctrs generics like vec_ptype2() and vec_cast():

vec_ptype2(deck, deck)
#> <card_vector[0]>
vec_cast(deck, to = character())
#> <card_vector[3]>
#> [1] [A♠]  [10♣] [K♥]
vec_cast(c("J♣", "3♠"), to = card_vector())
#> [1] "J♣" "3♠"

We hope this helps you simulate, test, and enjoy Blackjack in a fun and programmable way!

🃏 Good luck at the virtual table!