如何在Python中制作选择性随机数生成器?

1 投票
5 回答
2360 浏览
提问于 2025-04-16 03:06

这可能是个很基础的问题,但我作为一个完全的新手,觉得没关系。

简单来说,我想知道怎么在一个简单的游戏里做一个掉落物品的系统。也就是说,当你完成某个目标时,有机会获得一些物品,而这些物品的掉落几率是不一样的。如果有开源的Python游戏里有这个功能,请推荐给我。

我现在知道怎么做的是:从一个样本[A,B,C,D,E,F]中选择3个物品。

这很简单,但如果我想让样本中的某些物品被选中的几率更高,比如在样本[A,B,C,D,E,F]中选择3个物品,而且不能重复,A被选中的几率是30%,B是25%,C是20%,D是15%,E是5%,F是5%,那该怎么做呢?

或者,更好的是,我想选择的物品数量没有限制(或者有个范围限制,比如3到5个),但每个物品的被选中几率不同,而且不能重复,比如A是20%,B是20%,C是15%,D是10%,E是2%,F是1%。

希望这样说清楚了。

5 个回答

1

你把我搞糊涂了,当你把这个问题称为“非常初学者”的时候。其实这并没有看起来那么简单,具体要看你想要什么样的结果。如果你不介意有运气好的玩家能赢得所有物品,而运气差的玩家什么都得不到,BarsMonster的回答是个不错的选择。

如果你想每次都选定一定数量的物品,我建议你使用S.Lott的方法,先选一个物品,然后重复这个过程。如果你不想让同样的物品被选中多次,那就需要在选完一个物品后把它从loot中移除,然后在下一次选择之前重新构建choices。比如说(这只是个很粗略的伪代码):

items_won = random.randint(3, 5)
for i in range(items_won):
    item_won = s_lott_weighted_selection()
    inventory.add(item_won)
    loot.remove(item_won)
1

这是S.Lott提出的加权选择的另一种方法。

注意 - 这个代码没有经过测试。

import random

def weighted_selection(weights):    
    """returns an index corresponding to the weight of the item chosen"""
    total_sum = sum(weights)
    rnd = random.uniform(0, total_sum)
    cumulative_sum = 0
    for (idx, weight) in enumerate(weights):
        if rnd <= cumulative_sum + weight:
            return idx
        cumulative_sum += weight
    assert(0) # should never get here

weights = [30, 25, 20, 15, 5, 5]
# example of choosing 1 - will return value from 0 to 5
choice = weighted_selection(weights)

# example of choosing 3 such values without repeats
choices = []
for n in range(3):
    new_choice = weighted_selection(weights)
    del weights[new_choice]
    choices.append(new_choice)

你可能想在最后的“无重复选择”代码周围加一个保护措施,确保你选择的独特选项数量永远不会超过可用选项的数量。

1

这里有一个简单又省事的方法。

假设你有一组 (物品, 权重) 的配对。

loot = [ (A,20), (B,20), (C,15), (D,10), (E,2), (F,1) ]

注意,权重不需要加起来等于什么特定的数,只要是整数就可以。

首先需要做一个准备步骤。

choices = []
for item, weight in loot:
    choices.extend( [item]*weight )

现在只需要用 random.choice( choices ) 就行了。

撰写回答