Какова оптимальная стратегия выигрыша для этой модифицированной игры в блэкджек? - PullRequest
9 голосов
/ 20 февраля 2010

Вопросы

Существует ли значение best , чтобы я мог выиграть как можно больший процент игр? Если так, что это?

Редактировать: Существует ли точная вероятность выигрыша, которая может быть рассчитана для данного лимита, независимо от того, что делает противник? (Я не делал вероятности и статистику с колледжа). Мне было бы интересно увидеть это как ответ, чтобы сопоставить его с моими смоделированными результатами.

Редактировать: Исправлены ошибки в моем алгоритме, обновлена ​​таблица результатов.

Фон

Я играю в модифицированную игру в блэкджек с некоторыми довольно раздражающими изменениями правил из стандартных правил. Я выделил курсивом правила, которые отличаются от стандартных правил блэкджека, а также включил правила блэкджека для тех, кто не знаком.

Измененные правила блэкджека

  1. Ровно два человека (дилер не имеет значения)
  2. Каждый игрок получает по две карты лицом вниз
    • Ни один из игроков _ever_ не знает значения _any_ карт противника
    • Ни один из игроков не знает значения руки оппонента до тех пор, пока _both_ не закончит эту руку
  3. Цель - приблизиться к 21 очку. Результаты:
    • Если у игрока A & B одинаковый счет, игра представляет собой ничью
    • Если A & B игрока имеют счет более 21 (перебор), игра представляет собой ничья
    • Если игрок А набрал <= 21, а игрок Б выиграл, игрок А <em>выиграл
    • Если счет игрока А больше, чем у игрока Б, и ни один из них не сорван, игрок А выигрывает
    • В противном случае игрок А проиграл (выиграл Б).
  4. Карты стоят:
    • Карты со 2 по 10 приносят соответствующее количество очков
    • Карты J, Q, K стоят 10 очков
    • Карта туза стоит 1 или 11 очков
  5. Каждый игрок может запрашивать дополнительные карты по одной до тех пор, пока:
    • Игрок больше не хочет (остаться)
    • Оценка игрока, при этом тузы считаются равными 1, превышает 21 (перебор)
    • Ни один из игроков не знает, сколько карт использовал другой в любое время
  6. После того, как оба игрока либо остались, либо проиграли, победитель определяется по правилу 3 выше.
  7. После каждой раздачи вся колода перетасовывается, и все 52 карты снова в игре

Что такое колода карт?

Колода карт состоит из 52 карт, по четыре из следующих 13 значений:

2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, A

Никакое другое свойство карточек не имеет отношения.

Представление Ruby:

CARDS = ((2..11).to_a+[10]*3)*4

Алгоритм

Я подхожу к этому следующим образом:

  • Я всегда захочу нанести удар, если мой счет от 2 до 11, так как невозможно разорить
  • Для каждого из баллов с 12 по 21 я буду симулировать N рук против оппонента.
    • Для этих N рук счет будет моим «пределом». Как только я достигну лимита или больше, я останусь .
    • Мой противник будет следовать той же стратегии
    • Я буду моделировать N рук для каждой перестановки множеств (12..21), (12..21)
  • Вывести разницу в выигрышах и проигрышах для каждой перестановки, а также разницу в чистых выигрышах

Вот алгоритм, реализованный в Ruby:

#!/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

Использование

ruby blackjack.rb [num_iterations] [num_decks]

Сценарий по умолчанию имеет 100 000 итераций и 4 колоды. 100 000 занимает около 5 минут на быстром MacBook Pro.

Выход (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

Интерпретация

Здесь я борюсь. Я не совсем уверен, как интерпретировать эти данные. На первый взгляд кажется, что всегда , оставаясь в 16 или 17, - это путь, но я не уверен, так ли это легко. Я думаю, что маловероятно , что реальный человеческий оппонент останется на 12, 13 и, возможно, 14, так что я должен выбросить эти значения противник-предел? Кроме того, как я могу изменить это, чтобы учесть изменчивость реального человеческого оппонента? например настоящий человек, скорее всего, останется на 15 только из-за «чувства», а также может достичь 18 из-за «чувства»

Ответы [ 3 ]

4 голосов
/ 20 февраля 2010

Я с подозрением отношусь к вашим результатам. Например, если противник стремится к 19, ваши данные говорят о том, что лучший способ победить его - это наносить удары, пока вы не достигнете 20. Это не проходит базовый тест на запах. Вы уверены, что у вас нет ошибки? Если мой оппонент стремится к 19 или лучше, моя стратегия состоит в том, чтобы избежать разорения любой ценой: оставаться на чем-то 13 или выше (может быть, даже 12?). Идти на 20 - неправильно, и не только с небольшим отрывом, но и с большим.

Откуда я знаю, что ваши данные плохие? Потому что игра в блэкджек, в которую вы играете, не является необычной . Именно так играет дилер в большинстве казино: он достигает цели и затем останавливается, независимо от того, что другие игроки держат в своих руках. Что это за цель? Встаньте на 17 и попробуйте на 17. Когда вы избавитесь от ошибок в вашем скрипте, это должно подтвердить, что казино знают свое дело.

Когда я делаю следующие замены в вашем коде:

# 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

Результаты согласуются с поведением дилеров казино: 17 является оптимальной целью .

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

Несколько разных комментариев :

Нынешний дизайн негибкий. С помощью небольшого рефакторинга вы можете добиться четкого разделения между операцией игры (раздачей, перетасовкой, сохранением статистики бега) и принятием решения игроком. Это позволит вам проверить различные стратегии друг против друга. В настоящее время ваши стратегии встроены в циклы, которые все запутаны в коде игры. Ваши эксперименты будут лучше подкреплены дизайном, который позволит вам создавать новых игроков и устанавливать их стратегию по желанию.

2 голосов
/ 20 февраля 2010

Два комментария:

  1. Похоже, что нет единой доминирующей стратегии, основанной на "ограничении попадания":

    • Если вы выберете 16ваш оппонент может выбрать 17
    • , если вы выберете 17, ваш оппонент может выбрать 18
    • , если вы выберете 18, ваш оппонент может выбрать 19
    • , если вы выберете 19, ваш оппонент может выбрать 20
    • если вы выберете 20, ваш противник может выбрать 12
    • , если вы выберете 12, ваш противник может выбрать 16.

2,Вы не упоминаете, могут ли игроки видеть, сколько карт вытянул их оппонент (я бы так предположил).Я ожидаю, что эта информация будет включена в «лучшую» стратегию. (ответил)


Без информации о решениях других игроков игра становится проще.Но поскольку явно не существует доминирующей «чистой» стратегии , оптимальной стратегией будет стратегия « смешанная ».То есть: набор вероятностей для каждой оценки от 12 до 21 для того, стоит ли вам останавливать или брать другую карту (РЕДАКТИРОВАТЬ: вам понадобятся разные вероятности для данной оценки без тузов и против тузов.) Для выполнения стратегии требуетсяВы случайным образом выбираете (в соответствии с вероятностями), останавливаться или продолжать после каждого нового розыгрыша.Затем вы можете найти равновесие Нэша для игры.

Конечно, если вы задаете только более простой вопрос: какова оптимальная выигрышная стратегия против неоптимальных игроков (например, тех, которые всегдаостановитесь на 16, 17, 18 или 19) вы задаете совершенно другой вопрос, и вам нужно будет точно указать, каким образом другой игрок ограничен по сравнению с вами.

1 голос
/ 20 февраля 2010

Вот некоторые соображения по поводу собранных вами данных:

  • Мягко полезно сказать, каким должен быть ваш «предел попадания», но только если вы знаете, что ваш противник придерживается аналогичной стратегии «ограничения попадания».
  • Даже тогда, это только действительно полезно, если вы знаете, каков или может быть «предел» попадания вашего оппонента. Вы можете просто выбрать лимит, который даст вам больше побед, чем они.
  • Вы можете более или менее игнорировать фактические значения в таблице. Важен ли он положительным или отрицательным.

Чтобы показать ваши данные иначе, первое число - это предел вашего оппонента, а вторая группа чисел - это пределы, которые вы можете выбрать и выиграть. «Звездочка» - самый выигрышный выбор:

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

Исходя из этого, вы можете видеть, что предел попадания 17 или 18 является самым безопасным вариантом, если противник следует случайной стратегии выбора «предела попадания», потому что 17 и 18 побьют 7/10 «пределов попадания» противника.

Конечно, если ваш оппонент человек, вы не можете ответить на него, налагая «лимит попадания» в 18 или более 19, так что это полностью сводит на нет предыдущие вычисления. Я все еще думаю, что эти цифры полезны, однако:


Я согласен, что для любой отдельной руки вы можете быть достаточно уверены, что у вашего оппонента будет предел, после которого он перестанет бить, и он останется. Если вы можете угадать этот предел, вы можете выбрать свой собственный предел на основе этой оценки.

Если вы думаете, что они настроены оптимистично или они готовы рисковать, выберите лимит 20 - вы победите их в долгосрочной перспективе, если их предел превысит 17. Если вы действительно уверены, выберите предел 12 - он выиграет, если их лимит превысит 18, и здесь будет гораздо более частый выигрыш.

Если вы считаете, что они консервативны или склонны к риску, выберите предел 18. Это победит, если они останутся где-то ниже 18 лет.

Для нейтральной земли, возможно, подумайте о том, каким будет ваш предел без какого-либо влияния извне. Вы обычно бы попали на 16? A 17?

Короче говоря, вы можете только догадываться, каков предел вашего оппонента, но если вы хорошо угадываете, вы можете победить их в долгосрочной перспективе с помощью этой статистики.

...