Courtesy of pxhere

Lösungen

Vorwarnung

Achtung! Im Folgenden werden die Lösungen für das zweite Projekt präsentiert. Falls du das Projekt noch nicht vollständig bearbeitet hast, nutze zunächst die Tipps. Sofern dir die Tipps für einen Teil nicht geholfen haben, kannst du die Lösungen dafür benutzen, einen Schritt weiterzukommen und beim nächsten Abschnitt weiterzumachen.

Lösung zu Aufgabe 1: Grundprinzip Roulette

Lösung anzeigen

Das europäische Roulette verwendet eine Scheibe mit den Zahlen von 0 bis 36, also hat sie 37 verschiedene Fächer. Demnach entspricht das einer einfachen Zufallsziehung aus den Zahlen 0 bis 36, bei der jede Zahl mit gleicher Wahrscheinlichkeit auftritt, da die Fächer alle die gleiche Fläche einnehmen.

Mit sample kannst du - ohne Zurücklegen - alle Nummern ziehen. Es wird als eine zufällige Reihenfolge der Zahlen generiert:

sample(0:36)
##  [1] 26  3  6 13  0 25  9 21  2 22 23 14  4 34  5 18 10 17 32 24 11  8 31 19 36
## [26] 33 15 30 35  7 29 16 28  1 12 27 20

Was hier nun passiert, ist eine Urnenziehung ohne Zurücklegen bis alle Nummern gezogen wurden. Das entspricht jedoch nicht der Zufallsziehung beim Roulette. Dort wird jeweils “mit Zurücklegen” gespielt. Das kann man nun auf zwei Wegen erreichen:

Man könnte jeweils nur eine Ziehung durchführen. Dafür beschränkt man den Befehl auf eine Ziehung aus allen Zahlen. Möchte man nun mehrere Durchgänge simulieren, führt man diesen Befehl einfach mehrfach aus.

sample(0:36, 1)
## [1] 23

Man könnte auch mit dem Argument replace = T festlegen, dass die gezogenen Zahlen immer wieder ersetzt werden. Jetzt kann man mit dem zweiten Argument festlegen, wie oft man die Zufallsziehung durchführen möchte und man erhält eine mathematische Simulation der Zufallsziehung beim Roulette.

sample(0:36, 5, replace = T)
## [1] 25  3 27  3  6

Jetzt lassen wir die Roulettekugel 50 Mal rollen (Loop) und speichern die Ergebnisse in der Variable “Ziehungen”.

Das kann entweder, wie bereits beschrieben, über das replace-Argument im sample-Befehl gemacht werden (das Ergebnis ist ein numerischer Vektor, den wir hier dem Objekt Ziehungen zuweisen).

Ziehungen <- sample(0:36, 50, replace = T)
Ziehungen
##  [1] 33 12 24  1 12 22  1 29 11 12 30  1 26 16 28 18 19  8  3 30 19 22  0 36 33
## [26] 26 33  5 14 32 28 35 30 17 15 21  2 32 31 25 12 34  3  7 13 23 26 24 15 28

Oder man geht einen etwas schwierigeren Weg über eine for-Schleife. Dafür erstellt man zuerst ein leeres Objekt, in dem man dann im Folgenden die einzelnen Ziehungen speichern kann, und führt dann die Schleife aus.

Ziehungen <- NULL
for (i in 1:50) {
  Ziehungen[i] <- sample(0:36, 1)
}
Ziehungen
##  [1] 24 11 10 29 10  9  0 27  8 24 22 19 15 34 24  1  0 20  4  5  8  3 14  9 19
## [26]  4 25 26 13 11  8 31 35  9  9 24  5 27 31 35  5  5  3  9 17 16 28 31  5 35

Die erste Variante ist zwar wesentlich einfacher zu schreiben (und für R auch wesentlich einfacher und schneller auszuführen), aber die Zweite erlaubt es uns, nach dem Rollen jeder einzelnen Kugel noch andere Dinge zu tun.

Nun können wir die Zufallsziehung im Roulette simulieren und auch mehrfach ablaufen lassen. Was jetzt noch fehlt, sind die Wetten und die Berechnung des Gewinns.

Dazu wenden wir uns erst einmal der Frage zu: Wie hoch wäre mein Gewinn, wenn ich in jeder Runde 5 Euro auf die 9 gesetzt hätte?

Bei der Wette auf die 9 handelt es sich um eine einfache Wette auf eine Zahl. Die Wahrscheinlichkeit liegt bei 1:37 mit einer Gewinnausschüttung mit dem Faktor 36 (Die Gewinnausschüttung berechnet sich immer ohne Einbezug der Null. - Aus diesem Grund geht das Casino auf Dauer als Sieger in diesem Spiel hervor.). Setzt man beispielsweise 5 Euro auf eine einzelne Zahl, erhält man - wenn man richtig liegt - das 36-fache wieder, also 180 Euro. Damit hat man, unter Abzug des Einsatzes, einen Gewinn von 175 Euro, wenn man gewinnt, und einen Verlust von 5 Euro, wenn man verliert.

Nun können wir eine Funktion auf das Objekt Ziehungen (Vektor) anwenden, die einen weiteren Vektor mit den Gewinnen zu den Ziehungen erstellt. Diesen weisen wir dem Objekt Gewinne zu.

Gewinne <- ifelse(Ziehungen == 9, 175, -5)

Die ifelse-Funktion ist folgendermaßen aufgebaut:

  1. Man gibt die Bedingung an.
  2. Man gibt die Ausgabe für den Fall an, dass die Bedingung zutrifft.
  3. Man gibt die Ausgabe für den Fall an, dass die Bedingung nicht zutrifft.

Wenn also eine 9 herausgekommen ist, soll ein Gewinn von 175 eingesetzt werden; ansonsten der Gewinn von -5 (= Verlust). Der dadurch bestimmte Vektor sieht dann folgendermaßen aus:

##  [1]  -5  -5  -5  -5  -5 175  -5  -5  -5  -5  -5  -5  -5  -5  -5  -5  -5  -5  -5
## [20]  -5  -5  -5  -5 175  -5  -5  -5  -5  -5  -5  -5  -5  -5 175 175  -5  -5  -5
## [39]  -5  -5  -5  -5  -5 175  -5  -5  -5  -5  -5  -5

Jetzt kann man zu jeder Runde den Gewinn bzw. Verlust ablesen. Insgesamt ergibt das eine Ausbeute von:

Gesamtgewinn <- sum(Gewinne)
Gesamtgewinn
## [1] 650

Wie man sehen kann, hatten wir in diesem Fall sehr viel Glück. Die 9 wurde in 5 Durchläufen gezogen. Dadurch ergab sich ein phänomenaler Gewinn von 650 Euro.

Lösung zu Aufgabe 2: Implementierung verschiedener Wettmöglichkeiten

Lösung anzeigen

Auf Vektoren kann man ifelse-Funktionen nur sehr schlecht anwenden. Aus diesem Grund muss man den Gewinn einen Schritt vorher ermitteln. Das Problem ist dann, dass die gedrehten Zahlen nicht mehr ausgegeben werden, sondern lediglich der Gewinn. Eine Möglichkeit dafür ist es, eine Schleife zu erstellen und die gedrehten Zahlen in einem eigenen Objekt abzuspeichern.

Beim Roulette kann man auf beinahe jede vorstellbare Kombination von Zahlen wetten. Um das Ganze zu vereinfachen, bauen wir hier aber nur 7 Möglichkeiten ein: rote Zahlen (RED), schwarze Zahlen (BLACK), gerade (EVEN) und ungerade (ODD) Zahlen, sowie die drei Douzaines - Dutzende - in die sich die Zahlen 1 bis 36 einteilen lassen. Wir müssen diese Möglichkeiten zunächst als Objekte mit den dazugehörigen Zahlen füllen. Außer RED und BLACK können wir dabei alle Vektoren abkürzen:

RED <- c(1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36)
BLACK <- c(2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33, 35)
EVEN <- seq(2, 36, by = 2)
ODD <- seq(1, 35, by = 2)
firstThird <- 1:12
secondThird <- 13:24
lastThird <- 25:36

Grundsätzlich gibt es beim Roulette drei Variablen: den Einsatz, die Wette und die Zufallsziehung. Alle drei gehen in die Berechnung des Gewinns mit ein. Der Einsatz ist die Basis zur Berechnung des Gewinns. Dazu kommt die Wette im Abgleich mit der Zufallsziehung: je nachdem, ob man richtig tippt oder nicht, ergibt sich eine andere Gewinnberechnung.

# x = Ergebnis Roulette
x <- sample(0:36, 1)
# y = Einsatz (beispielhaft 10 Euro)
y <- 10
# z = Zahl/Gruppe von Zahlen, auf die gesetzt wurde (beispielhaft ungerade Zahlen)
z <- ODD

Bei der Gewinnberechnung nutzt man wie bereits in der ersten Aufgabe eine if-Funktion. Dort hat man die Bedingung jedoch nach dem Prinzip “Wenn die Zufallsziehung x der Wette z gleicht, dann gewinnt man.” geschrieben. Das kann man zwar wieder übernehmen, aber für die neu hinzugefügten Wetten (wie zum Beispiel auf die ungeraden Zahlen) funktioniert das nicht. Hierfür kann man die Bedingung mit dem is.element-Argument formulieren. Wenn x (die Zufallsziehung) ein Element von z (der Wette) ist, hat man gewonnen.

Zusätzlich zu der neuen Bedingung baut man nun bei Zutreffen der Bedingung eine weitere if-Funktion ein, die die unterschiedlichen Berechnungen des Gewinns für die unterschiedlichen Wetten beinhaltet. Damit erhält man eine Funktion, die abhängig von Zufallsziehung, Einsatz und Wette den Gewinn bzw. Verlust ermittelt.

Das sieht dann folgendermaßen aus:

if (is.element(x, z)) {
  if (z == RED) {
    y
  } else if (z == BLACK) {
    y
  } else if (z == ODD) {
    y
  } else if (z == EVEN) {
    y
  } else if (z == firstThird) {
    y * 2
  } else if (z == secondThird) {
    y * 2
  } else if (z == lastThird) {
    y * 2
  } else {
    y * 35
  }
} else {
  -y
}
## [1] -10

Hier stößt man jetzt auf ein Problem. Wenn man auf eine der neuen Wettmöglichkeiten setzt und gewinnt, erscheint folgende Warnmeldung: the condition has length > 1 and only the first element will be used. Im Folgenden sieht man ein Beispiel dafür. Dafür haben wir das Ergebnis der Zufallsziehung selbstständig bestimmt, um sicherzugehen, dass wir gewinnen.

x <- 13
if (is.element(x, z)) {
  if (z == RED) {
    y
  } else if (z == BLACK) {
    y
  } else if (z == ODD) {
    y
  } else if (z == EVEN) {
    y
  } else if (z == firstThird) {
    y * 2
  } else if (z == secondThird) {
    y * 2
  } else if (z == lastThird) {
    y * 2
  } else {
    y * 35
  }
} else {
  -y
}
## Warning in if (z == RED) {: Bedingung hat Länge > 1 und nur das erste Element
## wird benutzt
## [1] 10

Dieser Fehler taucht auf, weil die logische Abfrage == nur einzelne Zahlen miteinander vergleichen kann und nicht ganze Vektoren. Aus diesem Grund gibt R eine Warnung aus, führt den Befehl jedoch trotzdem unter der Auflage aus, dass nur der erste Wert für die Abfrage benutzt wird. Das ist erst einmal nicht schlimm; kann jedoch unter bestimmten Umständen zu Fehlern führen.

Beispiel: Nehmen wir an, dass wir 10 Euro auf die 1 gesetzt haben. Zu unserem Glück hat die Zufallsziehung eine 1 ergeben und wir gewinnen 350 Euro + den Einsatz von 10 Euro. Für diesen Fall berechnet die Funktion folgendes:

x<-1
z<-1
y<-10
if (is.element(x, z)) {
  if (z == RED) {
    y
  } else if (z == BLACK) {
    y
  } else if (z == ODD) {
    y
  } else if (z == EVEN) {
    y
  } else if (z == firstThird) {
    y * 2
  } else if (z == secondThird) {
    y * 2
  } else if (z == lastThird) {
    y * 2
  } else {
    y * 35
  }
} else {
  -y
}
## Warning in if (z == RED) {: Bedingung hat Länge > 1 und nur das erste Element
## wird benutzt
## [1] 10

Wie man sieht errechnet die Funktion uns einen Gewinn von 10 Euro. Dieser Fehler passiert bereits in der 2./3. Zeile des Befehls: if (z == RED) {y}. Was diese Zeile aussagen soll ist, dass man bei einer Wette auf RED einen Gewinn in der Höhe des Einsatzes zu verzeichnen hat. Die Abfrage, die wir dort jedoch eingebaut haben, kann nur einzelne Zahlen auf Gleichheit überprüfen. Aus diesem Grund benutzt R in diesem Fall nur die erste Zahl des Vektors RED für den Abgleich; und das ist die Zahl 1. Aus diesem Grund gilt in diesem Fall z == RED (das besagt, dass unsere Wette der Wette RED gleicht, obwohl wir eigentlich nur auf die 1 gesetzt haben), weshalb ein Gewinn von y ausgegeben wird.

Um diesen Fehler zu vermeiden, müssen wir die Abfrage verändern. Dafür eignet sich der identical()-Befehl. Dieser Befehl überprüft, ob zwei Elemente identisch sind, unabhängig von der Struktur bzw. Größe dieser beiden Elemente. Die korrigierte Funktion sieht dann folgendermaßen aus:

if (is.element(x, z)) {
  if (identical(z, RED)) {
    y
  } else if (identical(z, BLACK)) {
    y
  } else if (identical(z, ODD)) {
    y
  } else if (identical(z, EVEN)) {
    y
  } else if (identical(z, firstThird)) {
    y * 2
  } else if (identical(z, secondThird)) {
    y * 2
  } else if (identical(z, lastThird)) {
    y * 2
  } else {
    y * 35
  }
} else {
  -y
}
## [1] 350

Wie man sehen kann, berechnet diese Funktion nun den korrekten Gewinn für unser Beispiel.

Ein weiterer Kritikpunkt dieser Funktion ist die mehrfache Wiederholung fast identischer Befehle. Das kann man durch die Verwendung logischer Verknüpfungen; und zwar dem “oder” in R: |, verhindern. Im Folgenden kann man die optimierte Version des Befehls sehen:

if (is.element(x, z)) {
  if (identical(z, RED) | identical(z, BLACK) | 
      identical(z, ODD) | identical(z, EVEN)) {
    y
  } else if (identical(z, firstThird) | 
      identical(z, secondThird) | 
      identical(z, lastThird)) {
    y * 2
  } else {
    y * 35
  }
} else {
  -y
}
## [1] 350

Da die Funktion nun okönomisch und ohne Fehler läuft, können wir das Ganze nun in die Schleife einsetzen, die wir bereits in der ersten Aufgabe benutzt haben. Damit enthält diese Schleife die Verbesserung, dass in jedem Durchlauf auch der Gewinn ermittelt wird.

Um das jetzt auch einmal auszuprobieren, müssen wir die beiden Variablen Ziehungen und Gewinne von den Daten aus der ersten Aufgabe befreien und die Wette beispielhaft auf ODD festlegen:

Gewinne <- NULL
Ziehungen <- NULL
z <- ODD

Die Schleife sieht nun folgendermaßen aus:

for (i in 1:50) {
  x <- sample(0:36, 1)
  Ziehungen[i] <- x
  Gewinne[i] <- if (is.element(x, z)) {
    if (identical(z, RED) | identical(z, BLACK) | 
        identical(z, ODD) | identical(z, EVEN)) {
      y
    } else if (identical(z, firstThird) | 
        identical(z, secondThird) |
        identical(z, lastThird)) {
      y * 2
    } else {
      y * 35
    }
  } else {
  -y
  }
}

Die Ergebnisse können wir uns nun entweder einzeln anschauen, oder wir verbinden beide Objekte zu einem Datensatz.

Ziehungen
##  [1]  3 13  1 29 24 12 32 17 34 18 18  0 19 12 15 34  6  9 16  8 25 34 22 12 17
## [26] 34 16  8  7 25 20 36 31  9 17 27 23 10 33  9 21 14 36 32 10 21 24 29  6 27
Gewinne
##  [1]  10  10  10  10 -10 -10 -10  10 -10 -10 -10 -10  10 -10  10 -10 -10  10 -10
## [20] -10  10 -10 -10 -10  10 -10 -10 -10  10  10 -10 -10  10  10  10  10  10 -10
## [39]  10  10  10 -10 -10 -10 -10  10 -10  10 -10  10
Spiel_Odd_50 <- data.frame(Ziehungen, Gewinne)
head(Spiel_Odd_50)
##   Ziehungen Gewinne
## 1         3      10
## 2        13      10
## 3         1      10
## 4        29      10
## 5        24     -10
## 6        12     -10

Den Gesamtgewinn kann man sich dann auch noch für jede Runde mithilfe der cumsum-Funktion anzeigen lassen, oder man benutzt die sum-Funktion, um nur das Endergebnis zu erhalten.

cumsum(Gewinne)
##  [1]  10  20  30  40  30  20  10  20  10   0 -10 -20 -10 -20 -10 -20 -30 -20 -30
## [20] -40 -30 -40 -50 -60 -50 -60 -70 -80 -70 -60 -70 -80 -70 -60 -50 -40 -30 -40
## [39] -30 -20 -10 -20 -30 -40 -50 -40 -50 -40 -50 -40
sum(Gewinne)
## [1] -40

Lösung zu Aufgabe 3: Spiele, bis du X Euro gewonnen hast

Lösung anzeigen

Wir spielen nun beispielhaft mit einem Einsatz von 10 Euro auf RED. Dafür erstellen wir außerdem ein Objekt, das den Gewinn in der jeweiligen Runde kurzzeitig abspeichert, damit wir damit arbeiten können.

y <- 10
z <- RED
Gewinn <- NULL

Nun fehlen noch genau zwei Dinge:

  1. Wie ermitteln wir jeden Durchgang erneut den Gesamtgewinn, sodass dieser immer wieder mit der Bedingung abgeglichen werden kann?
  2. Wie zählen wir die Durchgänge?

Zu 1. - Für die Bedingung entscheiden wir uns für 50 Euro. Das heißt, dass wir so lange spielen wollen, bis wir 50 Euro gewonnen haben. Dafür brauchen wir ein weiteres Objekt für den Gesamtgewinn. Dieses Objekt soll in jedem Durchgang geupdatet werden. Starten soll es (logischerweise) bei Null. Also erstellen wir dafür das Objekt Gesamtgewinn mit dem Wert 0.

Gesamtgewinn <- 0

Dieses Objekt soll dann in jedem Durchgang mit dem Gewinn addiert werden; also schreibt man in die Funktion: Gesamtgewinn <- Gesamtgewinn + Gewinn. So wird der Gesamtgewinn in jedem Durchgang geupdatet und mit der Bedingung Gesamtgewinn < 50 verglichen. Damit wäre das erste Problem gelöst.

Zu 2. - Für das Zählen der Durchgänge wendet man eine identische Technik an. Dafür erstellt man wiederum ein Objekt (Durchgaenge) mit dem Wert 0.

Durchgaenge <- 0

Dieses Objekt updatet man auch in jedem Durchgang, indem man jedes Mal 1 addiert: Durchgaenge <- Durchgaenge + 1. Somit zählt man automatisch die Durchgänge mit.

Damit wären die beiden Probleme gelöst und wir kommen zu einem vorläufigen Ergebnis der Schleife.

Wenn man möchte, kann man sich auch in jedem Durchgang noch den Zwischenstand (Gesamtgewinn) oder den Gewinn der Runde (Gewinn) mithilfe der print-Funktion ausgeben lassen. Das Endergebnis sieht dann folgendermaßen aus:

while (Gesamtgewinn < 50) {
  x <- sample(0:36, 1)
  Gewinn <- if (is.element(x, z)) {
    if (identical(z, RED) | identical(z, BLACK) |
        identical(z, ODD) | identical(z, EVEN)) {
      y
    } else if (identical(z, firstThird) |
        identical(z, secondThird) |
        identical(z, lastThird)) {
      y * 2
    } else {
      y * 35
    }
  } else {
  -y
  }
  Gesamtgewinn <- Gesamtgewinn + Gewinn
  print (Gesamtgewinn)
  Durchgaenge <- Durchgaenge + 1
}

Die Funktion wird nun so lange alle Schritte wiederholen, bis die Bedingung Gesamtgewinn < 50 nicht mehr zutrifft. Bis dahin werden auch die Durchgänge gezählt. Das heißt, dass man, sofern die Funktion irgendwann stoppt, an dem Objekt Durchgaenge ablesen kann, wie lange man für einen Gewinn von 50 Euro hätte spielen müssen.

Wie man vielleicht merkt, hat das Ganze einen Haken. Wenn man Pech hat, dann kommt diese Funktion nie zum Ende, weil man nie oft genug in Folge gewinnt, um auf einen Gesamtgewinn von 50 Euro zu kommen. Keep in mind: Das Casino gewinnt letztlich immer; und das ist ein Fakt! Die Gewinnausschüttung beim Roulette berechnet sich nämlich derart, dass ein/eine Spieler:in, je öfter er spielt, umso wahrscheinlicher mit leeren Händen nach Hause gehen wird.

Aus diesem Grund sollten wir eine weitere Bedingung einbauen, die die Schleife nach einer bestimmten Zeit unterbricht. Eine Möglichkeit ist es, eine maximale Anzahl an Durchgängen festzulegen, bei der die Schleife beendet wird. Dafür kann man den break-Befehl benutzen. Diesen kann man in eine Schleife integrieren und bei Eintreten der dazugehörigen Bedingung (if) wird die Schleife unterbrochen. Im folgenden Beispiel brechen wir die Schleife nach 500 Durchgängen ab.

Gesamtgewinn <- 0
Durchgaenge <- 0
while (Gesamtgewinn < 50) {
  x <- sample(0:36, 1)
  Gewinn <- if (is.element(x, z)) {
    if (identical(z, RED) | identical(z, BLACK) |
        identical(z, ODD) | identical(z, EVEN)) {
      y
    } else if (identical(z, firstThird) |
        identical(z, secondThird) |
        identical(z, lastThird)) {
      y * 2
    } else {
      y * 35
    }
  } else {
  -y
  }
  Gesamtgewinn <- Gesamtgewinn + Gewinn
  Durchgaenge <- Durchgaenge + 1
  if (Durchgaenge == 500) break
}
Gesamtgewinn
## [1] -560

Das heißt, dass man nun so lange spielt, bis man entweder 50 Euro gewonnen oder 500 Runden gespielt hat.

Lösung zu Aufgabe 4: Funktionen

Abschnitt 1 anzeigen

Für das Erstellen einer Funktion kann man den function-Befehl benutzen. Dieser Befehl ist folgendermaßen aufgebaut: function (Variablen) {Funktion}. Man gibt in den normalen Klammern an, welche Variablen in der Funktion verwendet werden und zur Durchführung benötigt werden. In den geschwungenen Klammern gibt man dann die Operationen der Funktion an, die unter Verwendung der Variablen durchgeführt werden. Dem Ganzen kann man mithilfe der Zuweisung mit dem Pfeil einen Namen geben.

Für das Roulette ergeben sich zwei Variablen: der Einsatz y und die Wette z. Die Funktion kann man aus den vorherigen Aufgaben kopieren. Das ist zum einen die Zufallsziehung und zum anderen die Funktion zur Ermittlung des Gewinns in Abhängigkeit von Einsatz y und Wette z.

Das Problem ist nun, dass die Funktion noch keine Ergebnisse ausgibt. Dafür können wir zunächst ganz einfach den print-Befehl nutzen. Wichtig: der print-Befehl kann nur ein Objekt ausgeben, deshalb muss man Zufallsziehung und Gewinn in einen Vektor packen. Das sieht dann folgendermaßen aus:

Roulette <- function (y, z) {
  x <- sample (0:36, 1)
  Gewinn <- if (is.element(x, z)) {
    if (identical(z, RED) | identical(z, BLACK) |
        identical(z, ODD) | identical(z, EVEN)) {
      y
    } else if (identical(z, firstThird) |
        identical(z, secondThird) |
        identical(z, lastThird)) {
      y * 2
    } else {
      y * 35
    }
  } else {
  -y
  }
  print(c(x, Gewinn))
}
Roulette(10,7)
## [1]  20 -10

Nun kann man ganz einfach Roulette spielen, indem man Einsatz und Wette angibt und erhält Zufallsziehung und Gewinn. Wie man in diesem Beispiel sieht, wurden 10 Euro auf die Zahl 7 gesetzt. Ausgegeben wird, welche Zahl bei der Ziehung herauskam und der Gewinn.

Das Ganze ist aber noch nicht so schön. Deshalb versuchen wir, das Roulettespiel mit Pausen und Nachrichten etwas authentischer zu gestalten. Das Praktische dabei ist, dass man auch Variablen in diese Nachrichten schreiben kann, sodass man zum Beispiel eine Nachricht mit dem Ergebnis allgemein formulieren kann [message("Es wurde eine ", x, " gedreht!")]. Des Weiteren kann man, je nach Resultat (Sieg oder Niederlage) unterschiedliche Nachrichten mithilfe einer if-Funktion ausgeben lassen. Das könnte dann folgendermaßen aussehen:

Roulette <- function (y, z) {
  x <- sample (0:36, 1)
  Gewinn <- if (is.element(x, z)) {
    if (identical(z, RED) | identical(z, BLACK) |
        identical(z, ODD) | identical(z, EVEN)) {
      y
    } else if (identical(z, firstThird) |
        identical(z, secondThird) |
        identical(z, lastThird)) {
      y * 2
    } else {
      y * 35
    }
  } else {
  -y
  }
  message ("Roulettekugel startet")
  Sys.sleep (2.0)
  message ("Rien ne va plus!")
  Sys.sleep (2.0)
  message ("Es ist eine ", x, ".")
  Sys.sleep (2.0)
  if (is.element (x, z)) {
    message ("Du hast gewonnen!")
    Sys.sleep (2.0)
    message ("Dein Gewinn beträgt ", Gewinn, " Euro." )
  } else {
    message ("Du hast verloren!")
    Sys.sleep (2.0)
    message ("Gib nicht auf! In der nächsten Runde wird das Glück wieder auf deiner Seite stehen.")
  }
}

Das testen wir jetzt, indem wir die Funktion einmal benutzen. In diesem Beispiel setzen wir 10 Euro auf RED.

Roulette(10,RED)
## Roulettekugel startet
## Rien ne va plus!
## Es ist eine 36.
## Du hast gewonnen!
## Dein Gewinn beträgt 10 Euro.

Die Ausgabe in diesem Beispiel ist schon deutlich schöner/authentischer und hält alle nötigen Informationen bereit.

In dieser Funktion kann man jedoch nur einmal spielen und muss die Funktion dann erneut starten. Dafür können wir eine neue Funktion schreiben, die die alte Funktion dahingehend erweitert, als dass man mehrere Runden auf einmal spielen kann. Das wird im zweiten Abschnitt erläutert.

Abschnitt 2 anzeigen

Für das Umsetzen einer Roulette-Funktion mit variabler Rundenzahl müssen wir einige Anpassungen und Erweiterungen an der Funktion in Abschnitt 1 vornehmen. Übernehmen können wir wiederum die Zufallsziehung und die Gewinnberechnung aus den vorherigen Aufgaben. Wir wissen auch schon, dass wir drei Variablen haben werden: y = Einsatz, z = Wette und o = Anzahl der Runden. Die Funktion nennen wir Roulette_Schleife. Das sieht dann vorerst folgendermaßen aus:

Roulette_Schleife <- function(y, z, o) {
  x <- sample(0:36, 1)
  Gewinn <- if (is.element(x, z)) {
    if (identical(z, RED) | identical(z, BLACK) |
        identical(z, ODD) | identical(z, EVEN)) {
      y
    } else if (identical(z, firstThird) |
        identical(z, secondThird) |
        identical(z, lastThird)) {
      y * 2
    } else {
      y * 35
    }
  } else {
  -y
  }
}

Jetzt müssen wir uns überlegen, wie wir Zufallsziehung und Gewinnberechnung wiederholt durchführen können bis eine bestimmte Anzahl an Runden gespielt wurde. Wir wissen, dass die Variable o angibt, wie viele Runden gespielt werden sollen. Wir erstellen also eine weitere Variable Durchgaenge, die die gespielten Runden zählen soll. Das Vorgehen dabei sollte bereits aus den vorherigen Aufgaben bekannt sein. Mithilfe dieser beiden Variablen o und Durchgaenge können wir nun eine Bedingung erstellen, sodass gespielt wird bis o == Durchgaenge gilt.

Dafür verwenden wir eine neue Funktion: die repeat-Funktion. Diese Funktion führt alle ihre Operationen durch, bis die Bedingung (in unserem Fall o == Durchgaenge) erfüllt ist. Anders als bei bereits bekannten Funktionen schreibt man die Bedingung hier an das Ende der Funktion. Und zwar ist die repeat-Funktion folgendermaßen aufgebaut: repeat {Operation 1 ENTER Operation 2 ENTER etc. ENTER if (o == Durchgaenge) break}. Das sieht dann bei uns folgendermaßen aus:

Roulette_Schleife <- function (y, z, o) {
  Durchgaenge <- 0
  repeat {
    Durchgaenge <- Durchgaenge + 1
    x <- sample (0:36, 1)
    Gewinn <- if (is.element(x, z)) {
      if (identical(z, RED) | identical(z, BLACK) |
          identical(z, ODD) | identical(z, EVEN)) {
        y
      } else if (identical(z, firstThird) |
          identical(z, secondThird) |
          identical(z, lastThird)) {
        y * 2
      } else {
        y * 35
      }
    } else {
      -y
    }
  if(Durchgaenge == o) break
  }
}

Ebenso wie bei der Funktion im ersten Abschnitt fehlt nun eine Ausgabe mit den wichtigen Informationen/Ergebnissen. Dazu können wir unsere Funktion nun um die Pausen und Nachrichten aus dem ersten Abschnitt erweitern.

Roulette_Schleife <- function (y, z, o) {
  Durchgaenge <- 0
  repeat {
    Durchgaenge <- Durchgaenge + 1
    x <- sample (0:36, 1)
    Gewinn <- if (is.element(x, z)) {
      if (identical(z, RED) | identical(z, BLACK) |
          identical(z, ODD) | identical(z, EVEN)) {
        y
      } else if (identical(z, firstThird) |
          identical(z, secondThird) |
          identical(z, lastThird)) {
        y * 2
      } else {
        y * 35
      }
    } else {
      -y
    }
    message ("Roulettekugel startet")
    Sys.sleep (2.0)
    message ("Rien ne va plus!")
    Sys.sleep (2.0)
    message ("Es ist eine ", x, ".")
    Sys.sleep (2.0)
    if (is.element (x, z)) {
      message ("Du hast gewonnen!")
      Sys.sleep (2.0)
      message ("Dein Gewinn beträgt ", Gewinn, " Euro." )
      Sys.sleep (1.0)
    } else {
      message ("Du hast verloren!")
      Sys.sleep (2.0)
      message ("Gib nicht auf! In der nächsten Runde wird das Glück wieder auf deiner Seite stehen.")
      Sys.sleep (1.0)
    }
  if(Durchgaenge == o) break
  }
}

Jetzt ist die Ausgabe schon um einiges schöner, doch einige relevante Informationen fehlen noch. In dieser Funktion besteht nämlich die Möglichkeit, mehrere Runden auf einmal zu spielen. Damit kann man noch zusätzlich Information zur aktuellen Runde und zum aktuellen Gesamtgewinn ausgeben.

Die Ausgabe des Gesamtgewinns gestaltet sich jedoch nicht so leicht wie die Rundenzahl, denn den Gesamtgewinn muss man jede Runde aufs Neue updaten. Das Prinzip für solche Operationen wurde bereits in einer vorherigen Aufgabe beschrieben. Bevor die Schleife beginnt erstellt man ein Objekt Gesamtgewinn beginnend mit der Null. In der Schleife nutzt man dann dieses Objekt und überschreibt diesen Wert jede Runde aufs Neue, indem man immer wieder den Gewinn aus der gerade laufenden Runde addiert. [Achtung: Die Nachricht zum Gesamtgewinn muss nach dieser erneuten Gesamtgewinn-Berechnung erfolgen, ansonsten gibt man den jeweils den Gesamtgewinn nach der vorherigen Runde an.]

Nachdem man diese beiden Dinge impliziert hat, sieht die Funktion folgendermaßen aus:

Roulette_Schleife <- function (y, z, o) {
  Durchgaenge <- 0
  Gesamtgewinn <- 0
  repeat {
    Durchgaenge <- Durchgaenge + 1
    message ("Runde ", Durchgaenge, "!")
    x <- sample (0:36, 1)
    Gewinn <- if (is.element(x, z)) {
      if (identical(z, RED) | identical(z, BLACK) |
          identical(z, ODD) | identical(z, EVEN)) {
        y
      } else if (identical(z, firstThird) |
          identical(z, secondThird) |
          identical(z, lastThird)) {
        y * 2
      } else {
        y * 35
      }
    } else {
      -y
    }
    Gesamtgewinn <- Gesamtgewinn + Gewinn
    message ("Roulettekugel startet")
    Sys.sleep (2.0)
    message ("Rien ne va plus!")
    Sys.sleep (2.0)
    message ("Es ist eine ", x, ".")
    Sys.sleep (2.0)
    if (is.element (x, z)) {
      message ("Du hast gewonnen!")
      Sys.sleep (2.0)
      message ("Dein Gewinn beträgt ", Gewinn, " Euro." )
      Sys.sleep (1.0)
      message ("Damit liegt dein Gesamtgewinn bisher bei ", Gesamtgewinn, " Euro.")
      Sys.sleep (1.0)
    } else {
      message ("Du hast verloren!")
      Sys.sleep (2.0)
      message ("Damit liegt dein Gesamtgewinn bisher bei ", Gesamtgewinn, " Euro.")
      Sys.sleep (1.0)
      message ("Gib nicht auf! In der nächsten Runde wird das Glück wieder auf deiner Seite stehen.")
      Sys.sleep (1.0)
    }
  if(Durchgaenge == o) break
  }
}

Insgesamt funktioniert die Funktion, jedoch endet das Spiel nun ganz abrupt ohne irgendeine abschließende Nachricht. Aus diesem Grund fügen wir nun noch mehrere Nachrichten ein:

  • Eine Nachricht, dass die o Runden nun gespielt sind.
  • Eine Nachricht, die Einsatz, Wette und Rundenzahl nocheinmal zusammenfasst und den daraus folgenden Gesamtgewinn beinhaltet.
  • Eine Nachricht, die vom Gesamtgewinn abhängt (Ob Geld gewonnen oder verloren wurde oder ob am Ende bei Null rauskam, soll durch verschiedene Nachrichten angezeigt werden.)

Das kann dann folgendermaßen aussehen:

Roulette_Schleife <- function (y, z, o) {
  Durchgaenge <- 0
  Gesamtgewinn <- 0
  repeat {
    Durchgaenge <- Durchgaenge + 1
    message ("Runde ", Durchgaenge, "!")
    x <- sample (0:36, 1)
    Gewinn <- if (is.element(x, z)) {
      if (identical(z, RED) | identical(z, BLACK) |
          identical(z, ODD) | identical(z, EVEN)) {
        y
      } else if (identical(z, firstThird) |
          identical(z, secondThird) |
          identical(z, lastThird)) {
        y * 2
      } else {
        y * 35
      }
    } else {
      -y
    }
    Gesamtgewinn <- Gesamtgewinn + Gewinn
    message ("Roulettekugel startet")
    Sys.sleep (2.0)
    message ("Rien ne va plus!")
    Sys.sleep (2.0)
    message ("Es ist eine ", x, ".")
    Sys.sleep (2.0)
    if (is.element (x, z)) {
      message ("Du hast gewonnen!")
      Sys.sleep (2.0)
      message ("Dein Gewinn beträgt ", Gewinn, " Euro." )
      Sys.sleep (1.0)
      message ("Damit liegt dein Gesamtgewinn bisher bei ", Gesamtgewinn, " Euro.")
      Sys.sleep (1.0)
    } else {
      message ("Du hast verloren!")
      Sys.sleep (2.0)
      message ("Damit liegt dein Gesamtgewinn bisher bei ", Gesamtgewinn, " Euro.")
      Sys.sleep (1.0)
      message ("Gib nicht auf! In der nächsten Runde wird das Glück wieder auf deiner Seite stehen.")
      Sys.sleep (1.0)
    }
  if(Durchgaenge == o) break
  }
  message ("Deine ", Durchgaenge, " Runden sind durch.")
  Sys.sleep (3.0)
  message ("Du hast heute in ", Durchgaenge, " Spielrunden jeweils mit einem Einsatz von ", y, " Euro auf ", z, " einen Gesamtgewinn von ", Gesamtgewinn, " Euro erzielt!")
  Sys.sleep (3.0)
  if (Gesamtgewinn > 0) {
    message("Herzlichen Glueckwunsch!")
  } else if (Gesamtgewinn == 0) {
    message("Sie haben heute nichts gewonnen. Wollen Sie wirklich schon gehen?")
  } else {
    message("Schade. Aber seien Sie nicht traurig. Das nächste Mal steht das Glueck wieder auf Ihrer Seite!")
  }
}

Hier seht ihr jetzt zwei Beispiele:

  • Ein Mal wurden in 3 Runden jeweils 5 Euro auf BLACK gesetzt.
  • Ein Mal wurden in 4 Runden jeweils 100 Euro auf ODD gesetzt.
Roulette_Schleife(5, BLACK, 3)
## Runde 1!
## Roulettekugel startet
## Rien ne va plus!
## Es ist eine 2.
## Du hast gewonnen!
## Dein Gewinn beträgt 5 Euro.
## Damit liegt dein Gesamtgewinn bisher bei 5 Euro.
## Runde 2!
## Roulettekugel startet
## Rien ne va plus!
## Es ist eine 3.
## Du hast verloren!
## Damit liegt dein Gesamtgewinn bisher bei 0 Euro.
## Gib nicht auf! In der nächsten Runde wird das Glück wieder auf deiner Seite stehen.
## Runde 3!
## Roulettekugel startet
## Rien ne va plus!
## Es ist eine 17.
## Du hast gewonnen!
## Dein Gewinn beträgt 5 Euro.
## Damit liegt dein Gesamtgewinn bisher bei 5 Euro.
## Deine 3 Runden sind durch.
## Du hast heute in 3 Spielrunden jeweils mit einem Einsatz von 5 Euro auf 24681011131517202224262829313335 einen Gesamtgewinn von 5 Euro erzielt!
## Herzlichen Glueckwunsch!
Roulette_Schleife(100, ODD, 4)
## Runde 1!
## Roulettekugel startet
## Rien ne va plus!
## Es ist eine 14.
## Du hast verloren!
## Damit liegt dein Gesamtgewinn bisher bei -100 Euro.
## Gib nicht auf! In der nächsten Runde wird das Glück wieder auf deiner Seite stehen.
## Runde 2!
## Roulettekugel startet
## Rien ne va plus!
## Es ist eine 27.
## Du hast gewonnen!
## Dein Gewinn beträgt 100 Euro.
## Damit liegt dein Gesamtgewinn bisher bei 0 Euro.
## Runde 3!
## Roulettekugel startet
## Rien ne va plus!
## Es ist eine 27.
## Du hast gewonnen!
## Dein Gewinn beträgt 100 Euro.
## Damit liegt dein Gesamtgewinn bisher bei 100 Euro.
## Runde 4!
## Roulettekugel startet
## Rien ne va plus!
## Es ist eine 26.
## Du hast verloren!
## Damit liegt dein Gesamtgewinn bisher bei 0 Euro.
## Gib nicht auf! In der nächsten Runde wird das Glück wieder auf deiner Seite stehen.
## Deine 4 Runden sind durch.
## Du hast heute in 4 Spielrunden jeweils mit einem Einsatz von 100 Euro auf 1357911131517192123252729313335 einen Gesamtgewinn von 0 Euro erzielt!
## Sie haben heute nichts gewonnen. Wollen Sie wirklich schon gehen?
Robin Mehler
Projekte