带权随机在游戏开发中重度使用,各种抽奖和爆装备等.
运营根据需要来配置各个物品出现的概率.
今天要说的这个带权随机算法思想很简单,就是"把所有物品根据其权重构成一个个区间,权重大的区间大.可以想象成一个饼图. 然后,扔骰子,看落在哪个区间,"
举个栗子,有个年终抽奖,物品是iphone/ipad/itouch.
主办方配置的权重是[('iphone', 10), ('ipad', 40), ('itouch', 50)].
用一行代码即可说明其思想,即random.choice(['iphone']*10 + ['ipad']*40 + ['itouch']*50).
下面,我们写成一个通用函数.
#coding=utf-8
import random
def weighted_random(items):
total = sum(w for _,w in items)
n = random.uniform(0, total)#在饼图扔骰子
for x, w in items:#遍历找出骰子所在的区间
if n
物品越多,二分查找提升的性能越明显.
#coding=utf-8
class WeightRandom:
def __init__(self, items):
weights = [w for _,w in items]
self.goods = [x for x,_ in items]
self.total = sum(weights)
self.acc = list(self.accumulate(weights))
def accumulate(self, weights):#累和.如accumulate([10,40,50])->[10,50,100]
cur = 0
for w in weights:
cur = cur+w
yield cur
def __call__(self):
return self.goods[bisect.bisect_right(self.acc , random.uniform(0, self.total))]
wr = WeightRandom([('iphone', 10), ('ipad', 40), ('itouch', 50)])
print wr()