Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 这个改良的21点游戏的最佳获胜策略是什么? 问题_Ruby_Algorithm_Language Agnostic_Probability_Playing Cards - Fatal编程技术网

Ruby 这个改良的21点游戏的最佳获胜策略是什么? 问题

Ruby 这个改良的21点游戏的最佳获胜策略是什么? 问题,ruby,algorithm,language-agnostic,probability,playing-cards,Ruby,Algorithm,Language Agnostic,Probability,Playing Cards,是否有一个最佳的价值观可以让我尽可能多地赢得比赛?如果是,是什么 编辑:是否有一个精确的获胜概率可以根据给定的限制进行计算,而与对手所做的任何事情无关?(我从大学开始就没有做过概率统计)。我很想把它作为一个答案,与我的模拟结果进行对比 编辑:修复了我的算法中的错误,更新了结果表 背景 我一直在玩一个修改过的21点游戏,其中有一些来自标准规则的恼人的规则调整。我已经将与标准21点规则不同的规则斜体化了,还为那些不熟悉的人加入了21点规则 修改21点规则 正好有两个人类玩家(与庄家无关) 每位玩家正

是否有一个最佳的价值观可以让我尽可能多地赢得比赛?如果是,是什么

编辑:是否有一个精确的获胜概率可以根据给定的限制进行计算,而与对手所做的任何事情无关?(我从大学开始就没有做过概率统计)。我很想把它作为一个答案,与我的模拟结果进行对比

编辑:修复了我的算法中的错误,更新了结果表

背景 我一直在玩一个修改过的21点游戏,其中有一些来自标准规则的恼人的规则调整。我已经将与标准21点规则不同的规则斜体化了,还为那些不熟悉的人加入了21点规则

修改21点规则
  • 正好有两个人类玩家(与庄家无关)
  • 每位玩家正面朝下发两张牌
    • 任何一个玩家都不知道对方牌的价值
    • 在双方完成手牌之前,双方都不知道对方手牌的价值
  • 目标是尽可能接近21分。结果:
    • 若球员的A&B得分相同,则比赛为平局
    • 若球员的A&B得分均超过21分(半身),则比赛为平局

    • 如果玩家A的得分,以下是您收集的数据的一些想法:

      • 这对于告诉你你的“命中极限”应该是什么有点帮助,但前提是你知道你的对手也在遵循类似的“命中极限”策略
      • 即使如此,只有当你知道对手的“命中极限”是或可能是什么时,它才真正有用。你可以选择一个能给你比他们更多胜利的极限
      • 您可以或多或少忽略表中的实际值。重要的是它们是积极的还是消极的
      以另一种方式显示您的数据,第一组数字是您对手的限制,第二组数字是您可以选择并赢得的限制。带星号的是“Winningse”选项:

      由此可以看出,如果对手采用随机的“命中极限”选择策略,那么命中极限为17或18是最安全的选择,因为17和18将击败7/10的对手“命中极限”

      当然,如果你的对手是人类,你不能给他们施加18岁以下或19岁以上的“命中极限”,这样就完全否定了之前的计算。不过,我仍然认为这些数字很有用:


      我同意,对于任何一只手,你都有理由相信你的对手会有一个极限,在这个极限之后,他们会停止击球,并留下来。如果你能猜到这个极限,你可以根据这个估计选择你自己的极限

      如果你认为他们是乐观的,或者他们乐于冒险,那么选择20个上限——如果他们的上限在17以上,你将在长期内击败他们。如果你真的很有信心,选择12个上限——如果他们的上限超过18,并且这里有更频繁的赢家,那么这将获胜

      如果你认为他们是保守的或是规避风险的,那么选择18的上限。如果他们自己保持在18岁以下的话,那就赢了

      对于中性接地,考虑一下在没有任何外部影响的情况下,你的极限是多少。你通常会打16分吗?17岁

      简而言之,你只能猜测对手的极限是多少,但如果你猜对了,你就可以用这些统计数据在长期内击败他们。

      两条评论:

    • 似乎没有一个基于“命中极限”的单一主导战略:

      • 如果你选择16,你的对手可以选择17
      • 如果你选择17,你的对手可以选择18
      • 如果你选择18,你的对手可以选择19
      • 如果你选择19,你的对手可以选择20
      • 如果你选择20,你的对手可以选择12
      • 如果你选择12,你的对手可以选择16
    • 二,。你没有提到玩家是否能看到他们的对手抽了多少张牌(我想是的)。我希望这些信息能纳入“最佳”战略。(回答)


      由于没有关于其他玩家决策的信息,游戏变得更简单。但是,由于显然没有主导战略,最优战略将是“战略”。也就是说:每个分数的一组概率,从12到21,决定你是否应该停牌或抽另一张牌(编辑:对于给定的没有得分的分数和有得分的分数,你需要不同的概率)。执行策略需要你随机选择(根据概率)每次新绘图后是停止还是继续。然后你可以找到游戏的答案


      当然,如果你只是问一个简单的问题:对次优玩家(例如总是停在16、17、18或19号的玩家)的最佳获胜策略是什么?你问的是一个完全不同的问题,你必须明确指出,与你相比,另一个玩家在哪些方面受到限制。

      我对你的结果表示怀疑。例如,如果对手的目标是19,你的数据显示击败他的最好方法是一直打到20。这不能通过基本的气味测试。你确定你没有窃听器吗?如果我的对手争取19岁或更高,我的策略是不惜一切代价避免失败:坚持13岁或更高(甚至12岁?)。选择20肯定是错误的——而且不仅仅是小幅度的,而是大幅度的

      我怎么知道你的数据是坏的?因为你玩的21点游戏并不罕见。这是大多数赌场中庄家的游戏方式:庄家击中目标,然后停下来,不管其他玩家手里拿着什么。这个目标是什么?站在硬17上,打软17。当您清除脚本中的bug时,它应该确认
      CARDS = ((2..11).to_a+[10]*3)*4
      
      #!/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]
      
                                                             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
      
      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
      
      # 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
      
      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        --