【问题标题】:Probability Dice Game in Python with two dicesPython中的概率骰子游戏,带有两个骰子
【发布时间】:2013-12-29 17:47:41
【问题描述】:

我想对以下函数进行 1000 次交互,以确定您在此游戏中是赢钱还是输钱。

该游戏的设计目的是让您掷一对骰子并获得金钱或失去金钱。假设我们从 5 个硬币开始。

投掷 12 会产生 1.5 个硬币。

投掷 11 会产生 1 个硬币。

投出 10 个硬币会产生 0.5 个硬币。

抛出 9,8 或 7 不会产生任何结果。

投掷 6,5,4,3,2 或 1 从您的硬币数量中扣除 0.5 个硬币。

这是我的实现到目前为止的样子:

def luckCalc():

    amount = 5

    # if 12 then 1/36 chance

    if random.randrange(1,7) == 6 and random.randrange(1,7) == 6:
        amount = amount + 1.5

    # if 11 then 2/36 chance
    elif  (random.randrange(1,7) == 5 and random.randrange(1,7) == 6) or (random.randrange(1,7) == 6 and random.randrange(1,7) == 5):
        amount = amount + 1

   # if 10 then 3/36 chance

   elif (random.randrange(1,7) == 5 and random.randrange(1,7) == 5) or (random.randrange(1,7) == 4 and random.randrange(1,7) == 6) or (random.randrange(1,7) == 6 and random.randrange(1,7) == 4):
       amount = amount + 0.5

   # if 9,8,7
   # 4/36 + 5/36 + 6/36 chance
   # 1+6, 2+5, 3+4, 4+3, 5+2, 6+1 chance
   # 2+6, 3+5, 4+4, 5+3, 6+2 chance
   # 3+6, 4+5, 5+4, 6+3 chance
   # then no change in amount 

   # if 6,5,4,3,2,1
   # chances...
   # then amount -0.5

return amount 

# Iterate over the dice throwing simulator and calculate total

total = 0.0
for a in range(1000):
    total = total + luckCalc()

print (total)

我在函数结束时停止了编码,因为我认识到必须有一个更优雅的解决方案来实现这一点。有什么有趣的建议,我一直听到的这个蒙特卡洛是什么?

【问题讨论】:

  • 您当前的例程为每个 if 语句“重新掷骰子”。从roll = random.randrange(1,7) + random.rangerange(1,7) 开始,然后对其进行测试。您每次通过luckCalc 重置金额,而不是在外部跟踪总数。还有,11是做什么的?
  • 干得好,你敏锐的眼睛发现了一个逻辑漏洞。 - 我添加了 11。

标签: python probability dice


【解决方案1】:

我个人喜欢将结果表设置为数组(或字典,但这更适合我的目的,因为每个结果都是少数可能的整数之一),每个掷骰子的索引设置为值由此产生的变化。见下文。

import random

def luckCalc(coins=5):

  diceroll = random.randint(1,6)+random.randint(1,6) #roll them bones

  #here's that table I was talking about....
  results_table = ['index 0 is blank',"you can't roll a one on two dice",-.5,-.5,-.5,-.5,-.5,0,0,0,.5,1,1.5]

  coins += results_table[diceroll] #changes your coins value based on your roll (as an index of results_table)

  if results_table[diceroll] > 0: #change the string if your result was + or -
    result = "gained {}".format(results_table[diceroll])
  else:
    result = "lost {}".format(results_table[diceroll]*-1)

  print("You {} coins, putting you at {}".format(result,coins)) #report back to the user
  return coins #this is how you save your output


#CONSTANTS GO HERE -- YOU CAN CHANGE THESE TO CHANGE YOUR PROGRAM
STARTING_COINS = 5
HOW_MANY_ITERATIONS = 1000

#this way we don't modify a constant
coins = STARTING_COINS

#do it how many times?
for _ in range(HOW_MANY_ITERATIONS): #oh yeah that many times
  coins = luckCalc(coins) #runs the function and saves the result back to coins

#report to the user your final result.
print("After {} rolls, your final total is {}".format(HOW_MANY_ITERATIONS,coins))

【讨论】:

    【解决方案2】:

    每次调用random.randrange(1,7),都会生成一个随机数。由于您正在测试一个“转弯”,因此滚动两次:

    def roll_die():
        return random.randrange(1, 7)
    
    total = roll_die() + roll_die()
    

    并查看总和是否在一个范围内:

    def play_turn():
        total = roll_die() + roll_die()
    
        if total == 12:
            return 1.5
        elif total == 11:
            return 1.0
        elif total == 10:
            return 0.5
        elif total <= 6:
            return -0.5
        else:  # total is 7, 8, or 9
            return 0
    

    这是 100,000 轮的结果:

    >>> from collections import Counter
    >>> counts = Counter(play_turn() for i in xrange(100000))
    >>> counts
        Counter({-0.5: 41823, 0: 41545, 0.5: 8361, 1.0: 5521, 1.5: 2750})
    >>> probabilities = {score: count / 100000.0 for score, count in counts.items()}
    >>> probabilities
        {-0.5: 0.41823, 0: 0.41545, 0.5: 0.08361, 1.0: 0.05521, 1.5: 0.0275}
    

    【讨论】:

      【解决方案3】:

      您实际上可以将(哈!)您正在执行的所有操作整合到一个函数中:

      from random import randrange
      
      def play_game(rolls=1000, amount=5, n=6):
          """Play game 'rolls' times, starting with 'amount' on 'n'-sided dice.""" 
          for i in range(rolls):
              roll = randrange(1, n+1) + randrange(1, n+1)
              if roll == 12:
                  amount += 1.5
              elif roll == 11:
                  amount += 1
              elif roll == 10:
                  amount += 0.5
              elif roll < 7:
                  amount -= 0.5
          return amount
      

      【讨论】:

      • 我非常喜欢你的回答,因为它的多功能性,你在我的问题下的快速评论也是第一,但是 Blender 做了很好的解释。
      【解决方案4】:

      我注意到您的代码中有一些内容。首先,对于 6-1 案例,您实际上并没有从金额中减去 0.5。其次,由于您没有在每个循环中传递初始数量,因此您在总数中增加了 5 到 6.5,这使得总数毫无意义。

      更有效的总计是每次传递金额:

      def luckCalc( amount ):
      

      然后为你的循环:

      total = 5.0
      for a in range(1000):
          total = luckCalc(total)
      

      在我写这篇文章时刚刚发布的 Blender 的答案是简化您的主要功能的好方法。

      【讨论】:

      • 总数由外部迭代正确计算。在luckCalc 函数代码的最后,我添加了伪代码并将其注释掉。您的示例还将传递 1000 作为硬币的起始数量,这不符合我提供的规范。
      • 我猜我误解了你的游戏。正如您所写的那样,您每轮都会凭空添加 5 个新硬币。我假设您只想从 5 个硬币开始,然后看看在 1000 轮之后您有多少。
      猜你喜欢
      • 2011-01-19
      • 2021-12-14
      • 1970-01-01
      • 2014-03-16
      • 2012-02-29
      • 2014-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多