January 24, 2021

906 words 5 mins read

How to make a deck of cards in R

How to make a deck of cards in R

Just for the fun of it, I wanted to see how to create a complete deck of playing cards in the least amount of steps possible. Obviously, I could have just imported a premade dataset based on scraping a webpage or a csv file that someone created already but what fun would that be? So here we go!

Goal: We need to create a deck of cards that includes 4 different suits of 13 different values, and 13 different faces.

  1. Make the suits in order by naming the four suits and listing them 13 times so that all 3 lists are the same length.
suits <- c('spades', 'clubs', 'diamonds', 'hearts')

suit <- unlist(map(suits, rep, 13))

head(suit)
## [1] "spades" "spades" "spades" "spades" "spades" "spades"
  1. Make the faces by listing out all 13 and we can duplicate it from there.
faces <- c('king', 'queen', 'jack', 'ten', 'nine', 'eight', 'seven', 'six', 'five', 'four', 'three', 'two', 'ace')
face <- rep(faces, 4)

head(face)
## [1] "king"  "queen" "jack"  "ten"   "nine"  "eight"
  1. Make the values of the cards by listing out the values and then duplicating that 4xs
value <- rep(13:1, 4)

head(value)
## [1] 13 12 11 10  9  8
  1. Make the deck by combining the 3 different lists.
deck <- data.frame(face, suit, value)

head(deck)
##    face   suit value
## 1  king spades    13
## 2 queen spades    12
## 3  jack spades    11
## 4   ten spades    10
## 5  nine spades     9
## 6 eight spades     8
tail(deck)
##     face   suit value
## 47   six hearts     6
## 48  five hearts     5
## 49  four hearts     4
## 50 three hearts     3
## 51   two hearts     2
## 52   ace hearts     1
deck %>%
  group_by(suit) %>%
  summarise(cards = n(),
            totalValue = sum(value))
## # A tibble: 4 x 3
##   suit     cards totalValue
## * <chr>    <int>      <int>
## 1 clubs       13         91
## 2 diamonds    13         91
## 3 hearts      13         91
## 4 spades      13         91

Now we need to create the deal function

The following is a simple deal function that will deal out 7 random cards (rows) from the deck and not replace those cards back into the deck during the random sample process.

deal <- function(x) {
  sample_n(deck, x, replace = F)
}

deal(7)
##    face     suit value
## 1  king   spades    13
## 2   six diamonds     6
## 3  jack   spades    11
## 4  four    clubs     4
## 5 seven   spades     7
## 6  five   hearts     5
## 7   ace diamonds     1

Let’s play a game of blackjack

Now that we have the deck compiled we can start playing a game. Blackjack will be a great place to start since it is fairly straight forward. The biggest problem we are going to have is dealing cards from a single deck without having it reshuffle using another function call. The remaining items in the deck must be saved as the new deck.

There is a simple solution to keeping the cards that were drawn from being pulled again. The ‘anti_join()’ function can help us with that.

We will need to remove the items from the dealers hand and save it as a list item. Then we need to deal out the 2 cards for the player. If the user wants another card then he will need to ask for a new card while supplying the dealer hand along with the user hand. It is important that these rows are not included in the deck when asked.

Let’s edit the deal function to return all 3 elements if needed.

deal <- function(x, set = NULL){
  hand <- set$myhand
  dealerhand <- set$dealerhand
  myhand = list()
  #remove the existing hand from the deck if it is included
  if(!is.null(hand)) {
    deck <- deck %>% anti_join(hand)
  }
  #remove the existing dealer's hand from the deck if it is included
  if(!is.null(dealerhand)) {
    deck <- deck %>% anti_join(dealerhand)
  }
  #if there is not dealer hand included then we need to get him 2 cards
  if(is.null(dealerhand)) {
    dealerhand <- sample_n(deck, 2, replace = F)
    #once this is done we need to remove those 2 cards from the deck
    deck <- deck %>% anti_join(dealerhand)
  }
  #the new cards need to be drawn from the deck
  newhand <- sample_n(deck, x, replace = F)
  #if the hand is not null then 
  if(!is.null(hand)) {
          myhand <- rbind(hand, newhand) 
        } else {
          myhand <- newhand
          }
  hand <- list(myhand = myhand, dealerhand = dealerhand)
  return(hand)
  
}

#Deal the cards and get your set
set <- deal(2)
## Joining, by = c("face", "suit", "value")
set$myhand
##   face     suit value
## 1  ace diamonds     1
## 2  two    clubs     2
set$dealerhand
##   face     suit value
## 1 four   spades     4
## 2 four diamonds     4
#play on if you feel lucky!
set <- deal(1, set)
## Joining, by = c("face", "suit", "value")
## Joining, by = c("face", "suit", "value")
str(set)
## List of 2
##  $ myhand    :'data.frame':  3 obs. of  3 variables:
##   ..$ face : chr [1:3] "ace" "two" "two"
##   ..$ suit : chr [1:3] "diamonds" "clubs" "spades"
##   ..$ value: int [1:3] 1 2 2
##  $ dealerhand:'data.frame':  2 obs. of  3 variables:
##   ..$ face : chr [1:2] "four" "four"
##   ..$ suit : chr [1:2] "spades" "diamonds"
##   ..$ value: int [1:2] 4 4

Now we have the dealers hand and the players hand. This is just a start but a fun excercise for me and my 11 year old son, Garrett.