Tracks
/
R
R
/
Übungen
/
Blackjack
Blackjack

Blackjack

Lernübung

Einführung

Die Funktion switch() kann ein knapper Ersatz für eine lange Reihe von if ... else if-Tests sein. Die Variable, auf die switch() angewendet wird, ist meistens ein String, und dann kannst du die Anführungszeichen im Selektor weglassen.

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"

Beachte, dass Optionen nur dann durchfallen, wenn der Wert leer bleibt, wie bei M im obigen Beispiel. Du musst keine break-Anweisungen einfügen, wie es in manchen anderen Sprachen nötig ist.

Wenn du auf character-Typen prüfst, ist der letzte Wert ein Standardwert, wie hier. Bei Ganzzahl-Typen kann kein Standardwert angegeben werden.

Funktionen in dplyr

Das switch in Base R ist ziemlich eingeschränkt: Es führt nur einen exakten Abgleich mit einem einzelnen Eingabewert durch. Das war sinnvoll, als R 1993 zum ersten Mal veröffentlicht wurde, aber für den modernen Einsatz muss es verbessert werden.

Note

Wie im Konzept Conditionals erwähnt, ist die Paketsammlung tidyverse darauf ausgelegt, die Funktionalität von Base R zu ergänzen (und manchmal zu ersetzen), ohne die Abwärtskompatibilität zu beeinträchtigen.

Du kannst das Paket dplyr in den Gültigkeitsbereich holen, indem du entweder library(dplyr) (für das einzelne Paket) oder library(tidyverse) (für die ganze Sammlung) an den Anfang deines Codes schreibst.

Die Bibliothek dplyr bietet zwei zusätzliche Funktionen rund um switch.

Die Funktionen recode_values und replace_values

Diese beiden verwandten Funktionen ermöglichen eine vektorisierte, switch-ähnliche Zuordnung alter Werte zu neuen Werten.

Der Hauptunterschied zwischen ihnen ist, dass recode_values() einen völlig neuen Vektor erzeugt, während replace_values() teilweise Aktualisierungen eines vorhandenen Vektors erlaubt.

Der Abgleich ist weiterhin exakt, aber:

  • Die Optionen auf der linken Seite können Vektoren sein, und die Eingabe passt, wenn ein beliebiges Element übereinstimmt.
  • Optionen links und Ergebnisse rechts werden mit einer Tilde ~ statt mit = verknüpft.
  • In allen Fällen kann ein Standardwert angegeben werden.
library(dplyr)

x <- c("a", "b", "a", "d", "b", NA, "c", "e", "z")
recode_values(
  x,
  "a" ~ 1,
  "b" ~ 2,
  "c" ~ 3,
  c("d", "e") ~ 4, # either "d' or "e" will match
  NA ~ 0,          # matches missing values
  default = 100   # note the different syntax for the default
)
#> [1]   1   2   1   4   2   0   3   4 100

Die Funktion case_when

case_when führt die Syntax von case_match noch einen Schritt weiter, indem es jeden beliebigen logischen Ausdruck links von der ~ erlaubt.

Der Eingabevektor (x im Beispiel unten) wird nicht als Argument übergeben, er muss nur schon definiert sein.

x <- 1:10
case_when(
  x < 3 ~ "low",
  between(x, 3, 5) ~ "mid",
  between(x, 6, 8) ~ "high",
  .default = "what?"
)
#>  [1] "low"   "low"   "mid"   "mid"   "mid"   "high"  "high"  "high"  "what?" "what?"

Die Funktion between() ist ebenfalls Teil von dplyr.

Anleitung

In dieser Übung simulieren wir den ersten Zug eines Blackjack-Spiels.

Du bekommst zwei Karten und kannst die offene Karte des Dealers sehen. Alle Karten werden durch einen String dargestellt, zum Beispiel „ace“, „king“, „three“, „two“ usw. Die Werte der einzelnen Karten sind:

Karte Wert Karte Wert
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

Hinweis: Normalerweise können „ace“-Karten den Wert 1 oder 11 haben, aber der Einfachheit halber gehen wir davon aus, dass sie nur den Wert 11 haben.

Je nach deinen zwei Karten und der Karte des Dealers gibt es eine Strategie für den ersten Zug. Dabei hast du die folgenden Möglichkeiten:

  • Stehen (S)
  • Ziehen (H)
  • Splitten (P)
  • Automatisch gewinnen (W)

Sie ist zwar noch nicht optimal, aber du folgst der Strategie, die dein Freund Alex entwickelt hat. Sie sieht so aus:

  • Wenn du zwei „ace“-Karten hast, musst du sie immer splitten.
  • Wenn du einen Blackjack hast (zwei Karten, die zusammen einen Wert von 21 ergeben) und der Dealer keine „ace“-Karte, keine Bildkarte und keine „ten“-Karte hat, dann gewinnst du automatisch. Hat der Dealer eine dieser Karten, musst du stehen bleiben und warten, bis die andere Karte aufgedeckt wird.
  • Wenn deine Karten zusammen einen Wert im Bereich [17, 20] ergeben, solltest du immer stehen bleiben.
  • Wenn deine Karten zusammen einen Wert im Bereich [12, 16] ergeben, solltest du immer stehen bleiben, es sei denn, der Dealer hat eine 7 oder höher. In dem Fall solltest du immer ziehen.
  • Wenn deine Karten zusammen 11 oder weniger ergeben, solltest du immer ziehen.

1. Berechne den Wert einer beliebigen Karte.

Implementiere eine Funktion parse_card, die den numerischen Wert einer Karte berechnet:

parse_card("ace")
# => 11

2. Implementiere die Entscheidungslogik für den ersten Zug.

Schreibe eine Funktion first_turn, die die oben beschriebene Entscheidungslogik umsetzt:

first_turn(card1, card2, dealer_card)

Hier sind einige Beispiele für die erwarteten Ergebnisse:

first_turn("ace", "ace", "jack") == "P"
first_turn("ace", "king", "ace") == "S"
first_turn("five", "queen", "ace") == "H"
Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab
R Exercism

Bereit, mit Blackjack zu starten?

Melde dich bei Exercism an, um R mit 21 Konzepte111 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.