Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

blackjack concept exercise #275

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@
"booleans"
],
"status": "wip"
},
{
"slug": "blackjack",
"name": "Blackjack",
"uuid": "f76b5124-6627-47a2-b39b-acec27c0a67f",
"concepts": [
"switch"
],
"prerequisites": [
"conditionals"
],
"status": "wip"
}
],
"practice": [
Expand Down
1 change: 1 addition & 0 deletions exercises/concept/blackjack/.docs/hints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Hints
57 changes: 57 additions & 0 deletions exercises/concept/blackjack/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Instructions

In this exercise we will simulate the first turn of a [Blackjack](https:#en.wikipedia.org/wiki/Blackjack) game.

You will receive two cards and will be able to see the face up card of the dealer. All cards are represented using a string such as "ace", "king", "three", "two", etc. The values of each card are:

| card | value | card | value |
| :---: | :---: | :-----: | :---: |
| ace | 11 | eight | 8 |
| two | 2 | nine | 9 |
| three | 3 | ten | 10 |
| four | 4 | jack | 10 |
| five | 5 | queen | 10 |
| six | 6 | king | 10 |
| seven | 7 | *other* | 0 |

**Note**: Commonly, aces can take the value of 1 or 11 but for simplicity we will assume that they can only take the value of 11.

Depending on your two cards and the card of the dealer, there is a strategy for the first turn of the game, in which you have the following options:

- Stand (S)
- Hit (H)
- Split (P)
- Automatically win (W)

Although not optimal yet, you will follow the strategy your friend Alex has been developing, which is as follows:

- If you have a pair of aces you must always split them.
- If you have a Blackjack (two cards that sum up to a value of 21), and the dealer does not have an ace, a figure or a ten then you automatically win. If the dealer does have any of those cards then you'll have to stand and wait for the reveal of the other card.
- If your cards sum up to a value within the range [17, 20] you should always stand.
- If your cards sum up to a value within the range [12, 16] you should always stand unless the dealer has a 7 or higher, in which case you should always hit.
- If your cards sum up to 11 or lower you should always hit.

## 1. Calculate the value of any given card.

Implement a function `parse_card` to calculate the numerical value of a card:

```R
parse_card("ace")
# => 11
```

## 2. Implement the decision logic for the first turn.

Write a function `first_turn` that implements the decision logic as described above:

```R
first_turn(card1, card2, dealer_card)
```

Here are some examples for the expected outcomes:

```R
first_turn("ace", "ace", "jack") == "P"
first_turn("ace", "king", "ace") == "S"
first_turn("five", "queen", "ace") == "H"
```
24 changes: 24 additions & 0 deletions exercises/concept/blackjack/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Introduction

The `switch()` function can be a concise replacement for a long series of `if` ... `else if` tests.
The variable being switched on is most commonly a string, and if so the quotes can be omitted from the selector.

```R
star <- function(type) {
switch(type,
M = , # will "fall through" if no value given
K = "red dwarf",
G = "Earth-like",
"bigger star" # only correct for O,B,A,F
)
}

> star("M")
[1] "red dwarf"
```

Note that options will only fall through if the value is left blank, as with `M` in the example above.
There is no need to include `break` statements as with some other languages.

With character types, the final value can be a default, as here, or a `stop()` to throw an error if the conditions are intended to be exhaustive.
Switching on an integer is slightly different: for these the default is always `NULL`.
11 changes: 11 additions & 0 deletions exercises/concept/blackjack/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"authors": ["colinleach"],
"contributors": [],
"files": {
"solution": ["blackjack.R"],
"test": ["test_blackjack.R"],
"exemplar": [".meta/exemplar.R"]
},
"forked_from": ["go/blackjack"],
"blurb": "Learn about switch and conditionals by playing blackjack"
}
26 changes: 26 additions & 0 deletions exercises/concept/blackjack/.meta/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Design

## Goal

The goal of this exercise is to teach the student the use of `switch()` in R, as well as practicing conditional branching learned previously.

## Learning objectives

- Know the syntax of a `switch()`.
- Know that this is most often used with string values, where the quotes can be omitted.
- Know that a default is possible when switching on strings, but this is always `NULL` when switching on integers.

## Out of scope

Nothing relevant to R was deliberately excluded, as this topic is relatively self-contained.

## Concepts

The Concepts this exercise unlocks are:

- `loops`

## Prerequisites

- `conditionals`

33 changes: 33 additions & 0 deletions exercises/concept/blackjack/.meta/exemplar.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
parse_card <- function(card) {
switch(card,
ace = 11,
two = 2,
three = 3,
four = 4,
five = 5,
six = 6,
seven = 7,
eight = 8,
nine = 9,
ten = ,
jack = ,
queen = ,
king = 10,
0
)
}

first_turn <- function(card1, card2, dealer_card) {
hand_score <- parse_card(card1) + parse_card(card2)
dealer_score <- parse_card((dealer_card))
if (hand_score == 22) {
return("P")
}
if (hand_score == 21) {
return(ifelse(dealer_score < 10, "W", "S"))
}
if (hand_score >= 17 || (hand_score >= 12 && dealer_score < 7)) {
return("S")
}
"H"
}
5 changes: 5 additions & 0 deletions exercises/concept/blackjack/blackjack.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
parse_card <- function(card) {
}

first_turn <- function(card1, card2, dealer_card) {
}
190 changes: 190 additions & 0 deletions exercises/concept/blackjack/test_blackjack.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
source("./blackjack.R")
library(testthat)

# 1) parse_card

test_that("parse ace", {
expect_equal(parse_card("ace"), 11)
})

test_that("parse two", {
expect_equal(parse_card("two"), 2)
})

test_that("parse three", {
expect_equal(parse_card("three"), 3)
})

test_that("parse four", {
expect_equal(parse_card("four"), 4)
})

test_that("parse five", {
expect_equal(parse_card("five"), 5)
})

test_that("parse six", {
expect_equal(parse_card("six"), 6)
})

test_that("parse seven", {
expect_equal(parse_card("seven"), 7)
})

test_that("parse eight", {
expect_equal(parse_card("eight"), 8)
})

test_that("parse nine", {
expect_equal(parse_card("nine"), 9)
})

test_that("parse ten", {
expect_equal(parse_card("ten"), 10)
})

test_that("parse jack", {
expect_equal(parse_card("jack"), 10)
})

test_that("parse queen", {
expect_equal(parse_card("queen"), 10)
})

test_that("parse king", {
expect_equal(parse_card("king"), 10)
})

test_that("parse other", {
expect_equal(parse_card("joker"), 0)
})

# first_turn

test_that("pair of aces", {
expect_equal(first_turn("ace", "ace", "ace"), "P")
})

test_that("pair of jacks", {
expect_equal(first_turn("jack", "jack", "ace"), "S")
})

test_that("pair of kings", {
expect_equal(first_turn("king", "king", "ace"), "S")
})

test_that("pair of twos", {
expect_equal(first_turn("two", "two", "ace"), "H")
})

test_that("pair of fives", {
expect_equal(first_turn("five", "five", "ace"), "H")
})

test_that("blackjack with ace for dealer", {
expect_equal(first_turn("ace", "jack", "ace"), "S")
})

test_that("blackjack with queen for dealer", {
expect_equal(first_turn("king", "ace", "queen"), "S")
})

test_that("blackjack with five for dealer", {
expect_equal(first_turn("ace", "ten", "five"), "W")
})

test_that("blackjack with nine for dealer", {
expect_equal(first_turn("ace", "king", "nine"), "W")
})

test_that("score of 20", {
expect_equal(first_turn("ten", "king", "ace"), "S")
})

test_that("score of 19", {
expect_equal(first_turn("ten", "nine", "ace"), "S")
})

test_that("score of 18", {
expect_equal(first_turn("ten", "eight", "ace"), "S")
})

test_that("score of 17", {
expect_equal(first_turn("seven", "king", "ace"), "S")
})

test_that("score of 16 with six for dealer", {
expect_equal(first_turn("ten", "six", "six"), "S")
})

test_that("score of 16 with seven for dealer", {
expect_equal(first_turn("ten", "six", "seven"), "H")
})

test_that("score of 16 with ace for dealer", {
expect_equal(first_turn("ten", "six", "ace"), "H")
})

test_that("score of 15 with six for dealer", {
expect_equal(first_turn("ten", "five", "six"), "S")
})

test_that("score of 15 with seven for dealer", {
expect_equal(first_turn("ten", "five", "seven"), "H")
})

test_that("score of 15 with king for dealer", {
expect_equal(first_turn("ten", "five", "king"), "H")
})

test_that("score of 14 with six for dealer", {
expect_equal(first_turn("ten", "four", "six"), "S")
})

test_that("score of 14 with seven for dealer", {
expect_equal(first_turn("ten", "four", "seven"), "H")
})

test_that("score of 14 with queen for dealer", {
expect_equal(first_turn("ten", "four", "queen"), "H")
})

test_that("score of 13 with six for dealer", {
expect_equal(first_turn("ten", "three", "six"), "S")
})

test_that("score of 13 with seven for dealer", {
expect_equal(first_turn("ten", "three", "seven"), "H")
})

test_that("score of 13 with queen for dealer", {
expect_equal(first_turn("ten", "three", "queen"), "H")
})

test_that("score of 12 with six for dealer", {
expect_equal(first_turn("ten", "two", "six"), "S")
})

test_that("score of 12 with seven for dealer", {
expect_equal(first_turn("ten", "two", "seven"), "H")
})

test_that("score of 12 with queen for dealer", {
expect_equal(first_turn("ten", "two", "queen"), "H")
})

test_that("score of 11 with queen for dealer", {
expect_equal(first_turn("nine", "two", "queen"), "H")
})

test_that("score of 10 with two for dealer", {
expect_equal(first_turn("eight", "two", "two"), "H")
})

test_that("score of 5 with queen for dealer", {
expect_equal(first_turn("three", "two", "queen"), "H")
})

test_that("score of 4 with five for dealer", {
expect_equal(first_turn("two", "two", "five"), "H")
})