【问题标题】:Simulate several rounds of rock, paper and scissors模拟几轮石头、纸和剪刀
【发布时间】:2013-05-21 20:08:44
【问题描述】:

我正在尝试实现一个函数,该函数采用整数 n 并在玩家 1 和玩家 2 之间模拟 n 轮石头、纸、剪刀。赢得最多回合的玩家将赢得 n 轮游戏,可能出现平局.该函数应打印游戏结果,如图所示。

    >>> simul(1)
    Player 1
    >>> simul(1)
    Tie
    >>>simul(100)
    Player 2

我认为我需要以模块化的方式来解决这个问题。换句话说,我需要结合至少 2 个功能,我的问题是我似乎无法弄清楚如何做到这一点。调用simul()函数时如何激活嵌入函数的结果?

所以我创建了一个函数,通过执行函数rps(p1, p2) 来模拟Rock, Paper, Scissors 游戏。代码如下:

    def rps(p1,p2):
        #tie
        if (p1==p2):
            return 0
        # player 1 wins    
        elif p1+p2 in ['PR','RS','SP']:
            return -1
        else:
            return 1
        # player 2 wins

这是我有点卡住的地方。我需要在执行simul()函数时激活这个函数——我该怎么做?到目前为止,我有以下内容:

    def rps(p1,p2):
    #tie
        if (p1==p2):
            return 0
    # player 1 wins    
        elif p1+p2 in ['PR','RS','SP']:
            return -1
        else:
            return 1
    # player 2 wins

    def choose_rps():
        import random
        random.choice('RPS')

    def simul(n):
        p1_wins, p2_wins = 0, 0
        for i in range(n):
            p1 = choose_rps()
            p2 = choose_rps()
            result = rps(p1, p2)
            if result == -1:
                p1_wins += 1
            elif result == 1:
                p2_wins += 1
            if p1_wins > p2_wins:
                return 'Player 1'
            elif p1_wins == p2_wins:
                return 'Tie'
            else:
                return 'Player 2'

【问题讨论】:

    标签: python


    【解决方案1】:

    要“激活”一个函数,只需调用它即可。例如:

    def simul(n):
        score = 0
        for i in range(n):
            p1 = choose_rps()
            p2 = choose_rps()
            result = rps(p1, p2)
            score += result
        if score < 0:
            print('Player 1')
        elif score == 0:
            print('Tie')
        else:
            print('Player 2')
    

    当然,您需要编写 choose_rps 函数(randomly chooses 并返回 R、P 或 S 之一)—但是,正如您所看到的,您只需将其称为相同方式为rps 函数。


    将所有内容放在一个脚本中:

    def rps(p1, p2):
        # ... your code here
    
    def choose_rps():
        # implement this here
    
    def simul(n):
        # code from above
    

    然后你可能会想要一些东西来驱动它,例如:

    if __name__ == '__main__':
        import sys
        n = int(sys.argv[1]) if len(sys.argv) > 1 else 5
        simul(n)
    

    ……或者……

    while True:
        n = int(input('How many trials?')) # raw_input for Python 2.x
        simul(n)
    

    如果你愿意,你可以进一步简化。例如,您可以将整个循环转换为带有生成器表达式的sum 调用:

    def simul(n):
        score = sum(rps(choose_rps(), choose_rps()) for _ in range(n))
    

    【讨论】:

    • 谢谢,但我如何明智地合并这两个函数代码 - 换句话说,我如何将这些函数写入一个代码? rps 一定是第一个吧?
    • 嗯,我想我从未见过选择功能:)
    • @Snarre:让我编辑答案以处理您的第一个问题。但实际上,这应该包含在任何教程或课程中,让你能够写出任何内容……
    • 是 random.choice(rps) 吗??
    • 关闭,但random.choice 采用一系列值(列表、字符串等)可供选择。 rps 不是一个值序列,它是一个函数。您希望它从值'R'、'P' 和'S' 中进行选择,所以random.choice('RPS')。 (另外,请确保在脚本顶部import random。)
    【解决方案2】:

    这是一个没有 RPS 叙述的等效函数:

    import random
    
    def simul(n):
        score = sum([random.choice([-1, 0, 1]) for i in xrange(n)])
        winner_idx = 0 if score > 0 \
                else 1 if score < 0 \
                else 2
        print ['Player 1', 'Player 2', 'Tie'][winner_idx]
    

    这是一个跟随故事并扩展为 Rock、Paper、Scissors、Lizard、Spock:

    import random
    
    def rand_RPSLK():
        while True:
            yield random.choice('PSKLR')
    
    def simul(n):
        p1 = rand_RPSLK()
        p2 = rand_RPSLK()
        choice = lambda px: 'PSKLR'.index(next(px))
        score = sum([[0,1,-1,1,-1][choice(p1)-choice(p2)] for i in xrange(n)])
        winner_idx = 0 if score > 0 \
                else 1 if score < 0 \
                else 2
        print ['Player 1', 'Player 2', 'Tie'][winner_idx]
    

    【讨论】:

    • 这缺少模拟rps 函数的关键部分。当然,您知道这个游戏的赢/平/输机会均等,但模拟游戏的全部意义在于您不知道这一点。或者,如果您想忽略这一点,为什么还要费心总结 n 场比赛,而您只需调用 random 即可计算结果?
    • 一个系列赛中不止一场比赛的获胜、输球或平局的机会不均等。 Win 或 Loose 是相等的,但随着 n 的增加,平局的概率会降低,这就是需要总和的原因。查看 n=1000 导致平局的频率。该程序提供的统计输出行为与为叙事建模而构建的更复杂版本完全相同。
    • 谁说过 N 游戏系列具有均等分布? 计算给定 N 的分布,然后调用 random.random 是很简单的。
    • 更重要的是,您仍然没有抓住重点。你不是在模拟游戏。 “这个程序提供完全相同的统计输出行为……”当然是正确的,但您知道正确的唯一方法是您已经分析了游戏并确定了它的统计行为,而无需模拟它.您编写模拟的原因是为了验证或替代分析。您的代码就像通过编写返回 n*(n-1)/2 的 sum 函数然后将其结果与 n*(n-1)/2 进行比较来验证 sum(range(n))==n*(n-1)/2。
    • 你能展示一下吗?我认为我的等效函数在没有不必要的额外复杂性的情况下抓住了问题的本质,而且也不会太迟钝而无法隐藏正在做的事情。问题本质上是对一系列游戏的结果进行建模。
    猜你喜欢
    • 1970-01-01
    • 2019-02-23
    • 1970-01-01
    • 2020-06-20
    • 2013-12-09
    • 1970-01-01
    • 2013-04-06
    • 2014-11-21
    • 2015-01-15
    相关资源
    最近更新 更多