Was ist die optimale für dieses modifizierte Blackjack-Spiel zu gewinnen Strategie?
-
21-09-2019 - |
Frage
Fragen
Gibt es ein am besten Wert so zu bleiben, dass ich den größten Prozentsatz von Spielen möglich gewinnen? Wenn ja, was ist das?
Edit: Gibt es eine genaue Wahrscheinlichkeit, dass zu gewinnen für eine gegebene Grenze berechnet wird, unabhängig von was auch immer der Gegner tut? (Ich habe nicht Wahrscheinlichkeit & Statistik seit dem College gemacht). Ich würde interessieren zu sehen, dass als Antwort es mit meinem simulierten Ergebnis zu kontrastieren.
Edit:. Fixed bugs in meinem Algorithmus, aktualisiert Ergebnistabelle
Hintergrund
Ich habe mit einigem ziemlich ärgerlich Regel Tweaks aus den Standardregeln ein modifizierte Blackjack-Spiel zu spielen. Ich habe die Regeln kursiv gedruckt, die von den Standard-Blackjack-Regeln unterschiedlich sind, sowie die Regeln von Black Jack für diejenigen, die nicht enthalten sind.
Modifizierte Blackjack-Regeln
- Genau zwei menschliche Spieler (Händler ist irrelevant)
- Jeder Spieler erhält zwei verdeckte Karten
- Keiner der beiden Spieler _ever_ kennt den Wert von _jeder_ des Gegners Karten
- Kein Spieler kennt den Wert der Hand des Gegners, bis _both_ die Hand beendet haben
- Ziel ist so nahe zu kommen, von 21 wie möglich zu erzielen. Ergebnisse:
- Wenn Spieler A & B identische Punktzahl haben, Spiel ist ein ziehen
- Wenn Spieler A & B haben beide eine Punktzahl über 21 (a Büste), Spiel ist ein draw
- Wenn Spieler A-Score ist <= 21 und Spieler B gesprengt hat, Spieler A gewinnt
- Wenn Spieler A-Score größer als Spieler B, und weder hat gesprengt, Spieler A gewinnt
- Andernfalls Spieler A verloren hat (B hat gewonnen).
- Karten sind es wert:
- Karten von 2 bis 10 ist es wert, die entsprechende Anzahl an Punkten
- Karten J, Q, K sind 10 Punkte wert
- Card Ace ist im Wert von 1 oder 11 Punkte
- kann jeder Spieler zusätzliche Karten ein, bis zu einem Zeitpunkt anfordern:
- Der Spieler will nicht mehr (Aufenthalt)
- Die Punktzahl des Spielers, mit irgendwelchen Asse als 1 gezählt, überschreitet 21 (Büste)
- Keiner der Spieler weiß, wie viele Karten die anderen jederzeit verwendet hat
- Sobald beide Spieler entweder geblieben oder den Gewinner gesprengt wird pro Regel 3 bestimmt oben.
- Nach jeder Hand das gesamte Deck neu gemischt und alle 52 Karten im Spiel sind wieder
Was ist ein Kartenspiel?
Ein Kartenspiel besteht aus 52 Karten, vier für jede der folgenden 13 Werte:
2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, A
Keine andere Eigenschaft der Karten sind relevant.
Ein Ruby-Darstellung ist das:
CARDS = ((2..11).to_a+[10]*3)*4
Algorithm
Ich habe nähere dies wie folgt:
- Ich werde will immer treffen, wenn meine Punkte 2 bis 11 ist, da es unmöglich ist, Büste
- Für jeden der Punkte 12 bis 21 werde ich N Hände gegen einen Gegner simulieren
- Für diese N Hände, wird die Punktzahl mein „limit“ sein. Sobald ich die Grenze oder mehr erreichen, ich will Aufenthalt .
- Mein Gegner wird genau die gleiche Strategie folgen
- Ich werde simulieren N Hände für jede Permutation der Sätze (12..21), (12..21)
- Drucken der Unterschied in den Gewinnen und Verlusten für jede Permutation sowie der Nettogewinn Verlust Differenz
Hier ist der Algorithmus in Ruby implementiert:
#!/usr/bin/env ruby
class Array
def shuffle
sort_by { rand }
end
def shuffle!
self.replace shuffle
end
def score
sort.each_with_index.inject(0){|s,(c,i)|
s+c > 21 - (size - (i + 1)) && c==11 ? s+1 : s+c
}
end
end
N=(ARGV[0]||100_000).to_i
NDECKS = (ARGV[1]||1).to_i
CARDS = ((2..11).to_a+[10]*3)*4*NDECKS
CARDS.shuffle
my_limits = (12..21).to_a
opp_limits = my_limits.dup
puts " " * 55 + "opponent_limit"
printf "my_limit |"
opp_limits.each do |result|
printf "%10s", result.to_s
end
printf "%10s", "net"
puts
printf "-" * 8 + " |"
print " " + "-" * 8
opp_limits.each do |result|
print " " + "-" * 8
end
puts
win_totals = Array.new(10)
win_totals.map! { Array.new(10) }
my_limits.each do |my_limit|
printf "%8s |", my_limit
$stdout.flush
opp_limits.each do |opp_limit|
if my_limit == opp_limit # will be a tie, skip
win_totals[my_limit-12][opp_limit-12] = 0
print " --"
$stdout.flush
next
elsif win_totals[my_limit-12][opp_limit-12] # if previously calculated, print
printf "%10d", win_totals[my_limit-12][opp_limit-12]
$stdout.flush
next
end
win = 0
lose = 0
draw = 0
N.times {
cards = CARDS.dup.shuffle
my_hand = [cards.pop, cards.pop]
opp_hand = [cards.pop, cards.pop]
# hit until I hit limit
while my_hand.score < my_limit
my_hand << cards.pop
end
# hit until opponent hits limit
while opp_hand.score < opp_limit
opp_hand << cards.pop
end
my_score = my_hand.score
opp_score = opp_hand.score
my_score = 0 if my_score > 21
opp_score = 0 if opp_score > 21
if my_hand.score == opp_hand.score
draw += 1
elsif my_score > opp_score
win += 1
else
lose += 1
end
}
win_totals[my_limit-12][opp_limit-12] = win-lose
win_totals[opp_limit-12][my_limit-12] = lose-win # shortcut for the inverse
printf "%10d", win-lose
$stdout.flush
end
printf "%10d", win_totals[my_limit-12].inject(:+)
puts
end
Verwendung
ruby blackjack.rb [num_iterations] [num_decks]
Das Skript standardmäßig auf 100.000 Iterationen und 4 Decks. 100.000 dauert ca. 5 Minuten auf einem schnellen macbook pro.
Ausgabe (N = 100 000)
opponent_limit
my_limit | 12 13 14 15 16 17 18 19 20 21 net
-------- | -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
12 | -- -7666 -13315 -15799 -15586 -10445 -2299 12176 30365 65631 43062
13 | 7666 -- -6962 -11015 -11350 -8925 -975 10111 27924 60037 66511
14 | 13315 6962 -- -6505 -9210 -7364 -2541 8862 23909 54596 82024
15 | 15799 11015 6505 -- -5666 -6849 -4281 4899 17798 45773 84993
16 | 15586 11350 9210 5666 -- -6149 -5207 546 11294 35196 77492
17 | 10445 8925 7364 6849 6149 -- -7790 -5317 2576 23443 52644
18 | 2299 975 2541 4281 5207 7790 -- -11848 -7123 8238 12360
19 | -12176 -10111 -8862 -4899 -546 5317 11848 -- -18848 -8413 -46690
20 | -30365 -27924 -23909 -17798 -11294 -2576 7123 18848 -- -28631 -116526
21 | -65631 -60037 -54596 -45773 -35196 -23443 -8238 8413 28631 -- -255870
Interpretation
Dies ist, wo ich kämpfen. Ich bin mir nicht ganz sicher, wie diese Daten zu interpretieren. Auf den ersten Blick scheint es wie immer Aufenthalt im 16 oder 17 ist der Weg zu gehen, aber ich bin nicht sicher, ob es das einfach. Ich denke, es ist unwahrscheinlich , dass eine tatsächliche menschliche Gegner würde stay auf 12, 13 und möglicherweise 14, also sollte ich diese opponent_limit Werte hinauswerfen? Auch, wie kann ich das ändern Berücksichtigung der Variabilität eines echten menschlichen Gegner zu nehmen? z.B. nur auf der Grundlage eines „Gefühl“ ein echter Mensch ist wahrscheinlich auf 15 bleiben und auch auf 18 basiert auf einem „Gefühl“
treffen kannLösung
Ich bin misstrauisch Ihre Ergebnisse. Zum Beispiel, wenn der Gegner Ziele für 19, sagt die Daten, dass der beste Weg, um ihn zu schlagen ist zu schlagen, bis Sie 20 erreichen dies nicht einen grundlegenden Geruch Test. Sind Sie sicher, Sie nicht einen Fehler haben? Wenn mein Gegner wird für 19 oder besser streben, wäre meine Strategie, um jeden Preis zu vermeiden Zerschlagung sein: Aufenthalt auf etwas 13 oder höher (vielleicht sogar 12?). Gehen für 20 muss falsch -. Und nicht nur mit einer geringen Marge, aber durch eine Menge
Wie kann ich wissen, dass Ihre Daten schlecht ist? Da das Blackjack-Spiel Sie spielen sind, ist nicht ungewöhnlich . Es ist die Art und Weise ein Händler in den meisten Casinos spielt: der Dealer trifft auf ein Ziel und hält dann an, unabhängig davon, was die anderen Spieler in ihren Händen halten. Was ist das Ziel? Stehen auf harten 17 und traf weich 17. Wenn Sie die Fehler in Ihrem Skript loszuwerden, sollte bestätigen, dass die Casinos kennen ihr Geschäft.
Wenn ich die folgenden Ersetzungen, um Ihren Code zu machen:
# Replace scoring method.
def score
s = inject(0) { |sum, c| sum + c }
return s if s < 21
n_aces = find_all { |c| c == 11 }.size
while s > 21 and n_aces > 0
s -= 10
n_aces -= 1
end
return s
end
# Replace section of code determining hand outcome.
my_score = my_hand.score
opp_score = opp_hand.score
my_score = 0 if my_score > 21
opp_score = 0 if opp_score > 21
if my_score == opp_score
draw += 1
elsif my_score > opp_score
win += 1
else
lose += 1
end
Die Ergebnisse stimmen mit dem Verhalten der Kasinohändler: 17 ist das optimale Ziel
.n=10000
opponent_limit
my_limit | 12 13 14 15 16 17 18 19 20 21 net
-------- | -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
12 | -- -843 -1271 -1380 -1503 -1148 -137 1234 3113 6572
13 | 843 -- -642 -1041 -1141 -770 -93 1137 2933 6324
14 | 1271 642 -- -498 -784 -662 93 1097 2977 5945
15 | 1380 1041 498 -- -454 -242 -100 898 2573 5424
16 | 1503 1141 784 454 -- -174 69 928 2146 4895
17 | 1148 770 662 242 174 -- 38 631 1920 4404
18 | 137 93 -93 100 -69 -38 -- 489 1344 3650
19 | -1234 -1137 -1097 -898 -928 -631 -489 -- 735 2560
20 | -3113 -2933 -2977 -2573 -2146 -1920 -1344 -735 -- 1443
21 | -6572 -6324 -5945 -5424 -4895 -4404 -3650 -2560 -1443 --
Einige verschiedene Kommentare :
Das aktuelle Design ist unflexibel. Mit einem nur wenig Refactoring, könnten Sie eine saubere Trennung zwischen dem Betrieb des Spiels (Umgang, schlurfen, am Laufen zu halten Statistiken) und Spieler Entscheidungsfindung erreichen. Dies würde es ermöglichen Ihnen verschiedene Strategien gegeneinander zu testen. Derzeit sind Ihre Strategien in Schleifen eingebettet, die im Spiel Operationscode alle verstrickt sind. Ihre Experimente besser durch ein Design bedient würden, dass Sie neue Spieler zu schaffen erlaubt und setzen ihre Strategie nach Belieben.
Andere Tipps
Zwei Anmerkungen:
-
Es sieht aus wie es nicht eine einzige dominierende Strategie auf einem „Hit Limit“ basiert:
- Wenn Sie 16 kann dein Gegner 17 wählen
- , wenn Sie wählen 17 kann dein Gegner 18 wählen
- , wenn Sie wählen 18 kann dein Gegner 19 wählen
- , wenn Sie wählen 19 kann dein Gegner 20 wählen
- , wenn Sie wählen 20 kann dein Gegner 12 wählen
- , wenn Sie wählen 12 kann dein Gegner 16 wählen.
2. Sie erwähnen nicht, ob die Spieler sehen können, wie viele Karten ihre Gegner gezogen hat (ich würde vermuten, so). Ich würde diese Informationen erwartet in die „beste“ Strategie einbezogen werden. (beantwortet)
Ohne Informationen über die anderen Spieler Entscheidungen, das Spiel einfacher. Da es aber offenbar nicht dominant ist „reine“ Strategie wird die optimale Strategie eines „< a href = "http://en.wikipedia.org/wiki/Mixed_strategy" rel = "nofollow noreferrer"> gemischte “-Strategie. Das heißt: eine Reihe von Wahrscheinlichkeiten für jeden Score 12-21 dafür, ob Sie eine andere Karte stoppen oder ziehen sollte (EDIT:. Sie unterschiedliche Wahrscheinlichkeiten für eine bestimmte Punktzahl ohne Asse vs der Partitur mit Assen benötigt) Die Ausführung der Strategie erfordert dann Sie nach dem zufalls~~POS=TRUNC zu wählen (nach den Wahrscheinlichkeiten), ob zu stoppen oder fortzusetzen nach jedem neuen Unentschieden. Sie können dann finden Sie das Nash-Gleichgewicht für das Spiel.
Natürlich, wenn Sie nur die einfachere Frage: Was ist die optimale Strategie gegen suboptimal Spieler zu gewinnen (zum Beispiel diejenigen, die immer auf 16 stoppen, 17, 18 oder 19), die Sie eine völlig diiferent Frage stellen, und Sie angeben muß genau in welcher Art und Weise wird die anderen Spieler Sie begrenzt verglichen.
Hier sind einige Gedanken über die Daten, die Sie gesammelt haben:
- Es ist leicht nützlich für das Erklären Sie, was Ihre „hit limit“ sein sollte, aber nur, wenn Sie wissen, dass der Gegner einen ähnlichen „hit limit“ Strategie.
- Selbst dann ist es nur wirklich nützlich, wenn Sie wissen, was dein Gegner „hit limit“ ist oder sein dürfte. Sie können nur ein Limit wählen, dass Sie mehr Gewinne als sie gibt.
- Sie können mehr oder weniger ignorieren die tatsächlichen Werte in der Tabelle. Es ist egal ob sie positiv oder negativ ist, was zählt.
Um Ihre Daten eine andere Art und Weise zu zeigen, die erste Zahl Grenze deines Gegners, und die zweite Gruppe von Zahlen sind die Grenzen Sie können wählen, und gewinnen Sie mit. Die mit einem Stern ist der „winnin“ Wahl:
12: 13, 14, 15, 16*, 17, 18
13: 14, 15, 16*, 17, 18, 19
14: 15, 16, 17*, 18, 19
15: 16, 17*, 18, 19
16: 17, 18*, 19
17: 18*, 19
18: 19*, 20
19: 12, 20*
20: 12*, 13, 14, 15, 16, 17
21: 12*, 13, 14, 15, 16, 17, 18, 19, 20
Von diesem können Sie sehen, dass ein Hit Grenze von 17 oder 18 die sicherste Option ist, wenn der Gegner folgt eine zufällige „hit limit“ Auswahlstrategie, da 17 und 18 7/10 Gegner schlagen „Hit Grenzen“.
Natürlich, wenn dein Gegner ein Mensch ist, kann man nicht auf sie antworten Selbst zur Einführung eines „hit limit“ von unter 18 oder über 19, so dass vollständig die bisherigen Berechnungen negiert. Ich denke immer noch, diese Zahlen sind nützlich, aber:
Ich bin damit einverstanden, dass für jede einzelne Hand, können Sie ziemlich sicher sein, dass dein Gegner eine Grenze, nach dem hat sie schlagen zu stoppen, und sie werden bleiben. Wenn Sie an dieser Grenze denken können, können Sie Ihre eigene Grenze wählen auf der Grundlage dieser Schätzung.
Wenn Sie denken, sie sind optimistisch oder sie sind glücklich, es zu riskieren, wählen Sie eine Grenze von 20 - Sie können sie auf lange Sicht schlagen werde, wenn ihr Limit über 17 ist, wenn Sie wirklich sicher sind, wählen eine Grenze von 12 -. das wird zu gewinnen, wenn ihre Grenze über 18 und es gibt viel häufige Gewinne hier zu haben ist
Wenn Sie denken, sie sind abgeneigt konservativ oder das Risiko, eine Grenze von 18 wählen, das gewinnen, wenn sie irgendwo unter 18 selbst zu bleiben.
Für neutralen Boden, denkt vielleicht über das, was Ihr Limit ohne Einfluss von außen wäre. Würden Sie in der Regel auf einem 16 schlagen? A 17?
Kurz gesagt, kann man nur vermuten, was Grenze des Gegners ist, aber wenn man gut erraten, können Sie sie auf lange Sicht mit diesen Statistiken schlagen.