概率抽奖

本文探讨了在游戏掉落系统中,如何高效地根据概率生成物品,对比了一般算法、离散算法和AliasMethod算法的优缺点及实现方式。通过实例展示了如何将算法应用于抽奖系统,包括概率处理、随机数生成和空间复杂度的考量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

例如游戏中打败一个boss,会掉落下面其中一个物品,而每个物品都有一定概率: 1. 靴子 20% 2. 披风 25% 3. 饰品 10% 4. 双手剑 5% 5. 金币袋 40% 现在的问题就是如何根据概率掉落一个物品给玩家。

一. 一般算法:生成一个列表,分成几个区间,例如列表长度100,1-20是靴子的区间,21-45是披风的区间等,然后随机从100取出一个数,看落在哪个区间。算法时间复杂度:预处理O(MN),随机数生成O(1),空间复杂度O(MN),其中N代表物品种类,M则由最低概率决定。

二、离散算法:也就是上面的改进,竟然1-20都是靴子,21-45都是披风,那抽象成小于等于20的是靴子,大于20且小于等于45是披风,就变成几个点[20,45,55,60,100],然后也是从1到99随机取一个数R,按顺序在这些点进行比较,知道找到第一个比R大的数的下标,比一般算法减少占用空间,还可以采用二分法找出R,这样,预处理O(N),随机数生成O(logN),空间复杂度O(N)。 请点击查看详细:http://www.cnblogs.com/miloyip/archive/2010/04/21/1717109.html

三、Alias Method Alias Method就不太好理解,实现很巧妙,推荐先看看这篇文章:http://www.keithschwarz.com/darts-dice-coins/ 大致意思:把N种可能性拼装成一个方形(整体),分成N列,每列高度为1且最多两种可能性,可能性抽象为某种颜色,即每列最多有两种颜色,且第n列中必有第n种可能性,这里将第n种可能性称为原色。 想象抛出一个硬币,会落在其中一列,并且是落在列上的一种颜色。这样就得到两个数组:一个记录落在原色的概率是多少,记为Prob数组,另一个记录列上非原色的颜色名称,记为Alias数组,若该列只有原色则记为null。

之前的例子,为了便于演示换成分数 1. 靴子 20% -> 1/4 2. 披风 25% -> 1/5 3. 饰品 10% -> 1/10 4. 双手剑 5% -> 1/20 5. 金币袋 40% -> 2/5 然后每个都乘以5(使每列高度为1),再拼凑成方形 拼凑原则:每次都从大于等于1的方块分出一小块,与小于1的方块合成高度为1

由上图方形可得到两个数组: Prob: [3/4, 1/4, 1/2, 1/4, 1] Alias: [4, 4, 0, 1, null] (记录非原色的下标)

之后就根据Prob和Alias获取其中一个物品 随机产生一列C,再随机产生一个数R,通过与Prob[C]比较,R较大则返回C,反之返回Alias[C]。

Alias Method 复杂度:预处理O(NlogN),随机数生成O(1),空间复杂度O(2N)


//抽奖            
            IList<PrizeList> Info = new List<PrizeList>();
            //获取所有奖品,并带上概率(以100万计)
            Info = Server.GetPrizeList("800019");
            //生成随机数
            int Key = new Random().Next(1, 999999);
            //设置概率起始累计
            int Flag = 0;
            //暂存抽中的奖品ID
            int draID = 0;
            //假设;Iphone6S:10;移动20M流量包:99990;金币20:500000;电影票:200000;充电宝:100000;现金红包:100000
            //累计概率如下:10,100000,600000,800000,900000,1000000
            foreach (PrizeList item in Info)
            {
                Flag = Flag + item.概率;
                //如果该奖品已抽完,跳过该产品
                if (item.AlreadyWinning == item.TotalFrequency) { continue; }
                if (Flag > Key)
                {
                    draID = item.ID;
                    break;
                }
            }




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值