如何在掷骰子脚本中跟踪特定值的出现?

0 投票
2 回答
3967 浏览
提问于 2025-04-17 00:18

我还是觉得自己是个编程新手(我的声望大部分是因为gamedev.SE),所以我遇到了一个自己解决不了的问题。

我有一个函数,它可以掷指定数量的骰子,并返回结果。但是,如果掷出的结果是最高值,比如在六面骰子上掷出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)

我也不太确定把结果存储在一个列表中然后再求和是否是最好的方法,不过我想我也不会掷到足够多的骰子去担心这个问题。

我该如何记录最开始掷出的骰子呢?我说的“最开始”是指在最初指定的要掷的数量中,在因为掷出6而添加新骰子之前。

2 个回答

2

可以再创建一个数组,比如叫 original = []。在判断 roll == sides 的那部分,如果条件成立,就把 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
2

你和其他回答者把这个问题搞得太复杂了。

不要马上就掷新的骰子。先算一下要掷多少个新骰子,等你把账目整理好之后再一起掷。

也不用把所有掷过的骰子都列出来。其实不需要。先掷初始的骰子,收集一些数据,然后再递归地掷更多的骰子。

尽量避免写显式的循环来累积数据。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,要干净得多。要善于利用动态类型哦。:)

撰写回答