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

  1. Genau zwei menschliche Spieler (Händler ist irrelevant)
  2. 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
  3. 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).
  4. 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
  5. 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
  6. Sobald beide Spieler entweder geblieben oder den Gewinner gesprengt wird pro Regel 3 bestimmt oben.
  7. 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 kann
War es hilfreich?

Lö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:

  1. 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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top