Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.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
实现随机滚动表的pythonic方法是什么?_Python_Random - Fatal编程技术网

实现随机滚动表的pythonic方法是什么?

实现随机滚动表的pythonic方法是什么?,python,random,Python,Random,随机滚动表是用于桌面游戏等中随机生成的表。虽然它们可能非常简单,但也可能趋向于复杂 随机滚动表的一个不寻常的例子是命运之轮式游戏,其中某些类别的游戏发生的几率更高 我正在为D&D 5e魔法项目构建一个随机生成器(请参见此处:),但我已经决定要对表格进行加权,以便在特定时间选择特定结果 非常简单的表格可能如下所示: (1d6) 1: First result 2: Second result 3: Third result 4: Fourth result 5: Fifth result 6: S

随机滚动表是用于桌面游戏等中随机生成的表。虽然它们可能非常简单,但也可能趋向于复杂

随机滚动表的一个不寻常的例子是命运之轮式游戏,其中某些类别的游戏发生的几率更高

我正在为D&D 5e魔法项目构建一个随机生成器(请参见此处:),但我已经决定要对表格进行加权,以便在特定时间选择特定结果

非常简单的表格可能如下所示:

(1d6)
1: First result
2: Second result
3: Third result
4: Fourth result
5: Fifth result
6: Sixth result
(1d6)
1-3: First result
4-5: Second result
6: Third result
通过使用列表和1到6之间的随机性,可以很容易地解决这个问题

稍微复杂一点(但仍然基于1d6)的表可能如下所示:

(1d6)
1: First result
2: Second result
3: Third result
4: Fourth result
5: Fifth result
6: Sixth result
(1d6)
1-3: First result
4-5: Second result
6: Third result
我的桌子看起来更像:

(1d20)
1-5: First result
6-15: Second result
16-17: Third result
18: Fourth result
19: Fifth result
20: Sixth result
这些表格对某些类别具有更高的
权重
,以便更频繁地选择这些类别。在我的魔法物品示例中,剑应该有6-15把作为
金属
刀刃,而1-5把是
骨头
刀刃,20把是非常不寻常的东西,比如
黑暗
刀刃或
光明
刀刃

一个可能的选择是在每个类别中添加一个
重量
,并对每一卷进行计算,通过将之前的重量加在一起来查看它的重量,但这感觉非常笨拙

我以前曾尝试在PHP中实现此项生成器,并在实例上使用了带有比较运算符的开关实例来解决此问题,但显然,这在Python中不起作用


对于这种加权表实现,推荐的Python设计是什么,或者有人对实现有任何想法吗?我愿意完全重写我的数据结构以利用任何想法。

一个简单的解决方案就是简单地使用。第二个例子是:

>>> random.choice([1, 1, 1, 2, 2, 3])
你的第三个问题很简单:

>>> choices = [1]*5 + [2]*10 + [3]*2 + [4, 5, 6]
>>> random.choice(choices)

选项1:使用一个
列表
,在你的骰子上每个数字有一个元素-这具有算法映射非常接近滚动骰子和从表中查找结果的优点。缺点是,对于一个10000面的骰子来说,它的规模会非常大。但这可能不是你关心的问题

roll_results = ([first_result] * 5 
                + [second_result] * 10 
                + [third_result] * 2
                + [fourth_result,
                   fifth_result,
                   sixth_result])

roll = random.randint(0, 20)
result = roll_results[roll]
选项2:使用a-这是一种有效的数学方法。它可以很好地扩展。但是,如果你不知道统计数据,也没有很明显地映射到用例,那么理解起来就更复杂了

from bisect import bisect_left

import numpy as np

options = ["a", "b", "c", "d", "e", "f"]
weights = np.array([5, 10, 2, 1, 1, 1])
pdf = weight/np.sum(weights)
cdf = np.cumsum(pdf)

def get_item(cdf, options):
    roll = np.random.random()
    idx = bisect_left(cdf, roll)  # This uses a binary search to find the point on the CDF (F) such that F(roll) == P(X <= roll)
    return options[idx]

有没有理由不使用简单的20元素列表?然后你只需要选择一个介于1和20之间的随机数。或者你只是想要一个函数,用加权概率选择一个随机项?@Dan主要是因为有很多这样的表,我需要加权概率,就像我上面提到的那样。还有数据重复问题,如果我需要更改任何内容,将导致我需要更改许多字典元素。我认为random.choice选项可能与字典中的权重元素一起工作,它解决了重复问题。到目前为止,我还没有意识到random.choice,所以这对我非常有用。我认为选项1可能有效,选项2是一个非常好的主意。由于我已经构建了(并将继续构建)这些表的数量,选项3实际上不起作用。同意-选项3也有更大的出错空间,而且维护起来也很麻烦。如果您必须对许多列表执行此操作,我建议使用选项2,并使用类或闭包将cdf计算与之打包。我将添加示例。@MeridarchGekkota添加了一些更完整的解决方案,使选项2可重复使用,以制作许多辊道