【问题标题】:How can I keep track of specific values rolled in a dice-rolling script?如何跟踪掷骰子脚本中的特定值?
【发布时间】:2011-08-24 22:43:08
【问题描述】:

我仍然认为自己是一个编程新手(我的名声主要是因为 gamedev.SE),因此我遇到了一个我自己无法解决的问题。

我有一个函数,它接受指定数量的骰子并掷骰子,然后返回结果。但是,如果它碰巧掷出最高可用值,例如 6 面骰子上的 6,它会移除有问题的骰子并在其位置掷两个新骰子。它按预期工作,但我在实现另一个必要部分时遇到了问题:跟踪掷出的 1 的数量,特别是在初始骰子中掷出的任何 1。

from random import randint

def roll_die(number, sides=6):
    results = []
    for dice in range(number):
        roll = randint(1, sides)
        if roll == sides:
            #rolling two new dice instead
            results.append(roll_die(2, sides))
        else:
            results.append(roll)
    return sum(results)

我也不确定是否将结果存储在列表中然后对其求和是否是最好的方法,但我想我永远不会达到足够多的骰子来担心这一点。

如何跟踪掷出的第一个骰子?当我说“第一个”时,我的意思是在最初指定的要滚动的数字中,在由于滚动六点而添加任何新骰子之前。

【问题讨论】:

    标签: python list random


    【解决方案1】:

    你(和另一个答案)把这件事弄得太复杂了。

    不要立即掷新骰子。计算有多少新骰子要滚动,并在您完成簿记后滚动它们。

    不要建立一个所有滚动的列表。你不需要它。掷初始骰子,收集统计数据,然后递归掷更多骰子。

    避免编写显式循环来累积数据。 Python 知道如何积累数据。告诉它你想在列表中得到什么(通过列表理解)。

    不要进行多次递归调用。一个会做的。想想你会如何用物理骰子来做:你把所有的六点都拿出来,然后把它们加倍并重新掷骰子。

    from random import randint
    
    def roll_dice(count, sides=6):
        if count == 0: return (0, 0) # we need to guard against infinite recursion.
        initial = [randint(1, sides) for die in range(count)]
        initial_mins = initial.count(1)
        initial_maxes = initial.count(sides)
        # Add up all the dice that weren't maximum.
        subtotal = sum(result for result in initial if result != sides)
        # Recurse to re-roll the maxed-out dice.
        ignored, reroll = roll_dice(2 * initial_maxes, sides)
        return (initial_mins, subtotal + reroll)
    

    请注意,递归调用会返回一些我们忽略的初始值,因为我们只关心第一次滚动的那些。我们将递归结果解包并保留有趣的值,即递归重掷骰子的总数。

    我们也可以迭代地做,只在第一次迭代时加起来:

    from random import randint
    
    def roll_dice(count, sides=6):
        initial_mins = None
        result = 0
        while count:
            dice = [randint(1, sides) for die in range(count)]
            if initial_mins == None: initial_mins = dice.count(1)
            result += sum(result for result in dice if result != sides)
            count = 2 * dice.count(sides) # number to roll the next time through.
        return (initial_mins, result)
    

    注意None 标记值如何用于确保我们第一次设置initial_mins,然后每隔一次跳过它。这比使用“不可能的”整数值(例如 -1)更清晰。拥抱动态类型。 :)

    【讨论】:

    • 第一个版本进入死循环;第二个非常好,所以谢谢你!列表推导式绝对是我需要更多练习的东西。
    • 呃,对不起。需要检查 count == 0 是否要以这种方式递归。 :) 已修复。
    【解决方案2】:

    有第二个数组可能是original = [] 并在roll == sides 部分如果在else 中附加sides 附加roll。然后你可以return [sum(results), original]。在您的if roll == sides: 中,您将不得不执行类似results.append(roll_die(2,sides)[0]) 的操作

    在回答您的列表问题时,您可以将卷的值添加到每个卷的整数,然后返回。

    一个例子:

    from random import randint
    
    def roll_die(number, sides=6):
        results = []
        ones = 0
        for dice in range(number):
            roll = randint(1, sides)
            if roll == sides:
                #rolling two new dice instead
                results.append(roll_die(2, sides)[0])
            else:
                results.append(roll)
            if roll == 1:
                ones += 1
        return sum(results), ones
    

    【讨论】:

    • 我从阅读您的答案中得到了这个想法,所以我不想单独发布它并可能从您那里获得投票,所以我只是将它编辑到您的答案中。如果您不喜欢它,请随时将其取出。
    • @agf 啊,所以它会返回一个元组,并且任何递归也会返回一个元组,并且您将结果附加到元组索引0(新卷的总和)?我读得对吗?
    猜你喜欢
    • 2022-01-21
    • 1970-01-01
    • 2017-07-31
    • 1970-01-01
    • 2018-09-08
    • 2021-06-18
    • 2021-06-16
    • 1970-01-01
    • 2012-02-29
    相关资源
    最近更新 更多