抽奖算法-指定概率的随机
?
抽獎模型
普通概率模型
普通概率模型是最常用的一種模型,但是在游戲運營過程中的確發現很多小白玩家不能正確理解——他們認為中獎率 10% 的設定等同于抽 10 次肯定會中一次。這顯然是錯誤的,普通概率模型的中獎抽獎次數是基于正態分布的,而且每次抽獎的事件是獨立的,并不會因為你前面抽了 9 次沒中獎,第十次就一定能中獎。
雖然在大量的統計中,兩次中獎的平均間隔是 10 次,但是還有一個有趣的數據是連續 10 次都沒中獎的概率約為 (1-10%)^10 ~= 34.8% 可不小呢。
此外「標準差」是一個很有意思的數據,經過模擬統計,10% 中獎率得到的標準差為 9.62 ——也就是說絕大分部人經過 10 ± 9.62 次抽獎即能中獎,運氣再背抽 20 次也差不多能得到獎勵了。
這種概率模型能非常準確地實現策劃的需求,但是會惹來一些小白玩家的差評——為什么你說中獎率是 10% 但是我抽了 20 次還沒有中獎!然后給你打個一星。所以很多游戲運營商為了顧及玩家的體驗,會對普通概率模型進行修訂,增設一些保底抽獎次數,例如每第 10 次固定中獎(10,20,30...)
對于這種做法,我暫不于評價。但是讓我們看看如果硬生生地加入固定中獎的設定,會給數值帶來什么變化吧。
固定中獎模型
每次抽獎中獎率依舊為 10% ,但每第十次抽獎必中。
這時候玩家得到的抽獎體驗是:10 次抽獎肯定能中獎,而且不止中一次,爽暴了是不是。實際期望高達 19% 這遠遠超出策劃 10% 的預期。所以策劃琢磨著不能便宜了玩家,只能把中獎率調低。但是這會導致中獎集中在每 10 次附近,抽獎的樂趣幾近喪失。
這樣看來,固定中獎模型是否真的無藥可救?其實還是有可以優化的地方。
計數器模型
每次抽獎中獎率依舊為 10% ,若連續 9 次未中獎,下一次抽獎必中獎。
這個需求看起來和上面好像沒什么不同,但是保底的條件不再是每第 10 次,而是發生在每連續 9 次未中獎后。也就是說計數器會在每次中獎后清 0 重計。
?
隨機步長累加模型
也是一種保底中獎模型,只不過去掉了獨立隨機事件,并把計數增長改為隨機量,最終在累計超過閾值時得獎。這種模型如果有個較大的閾值和較小的步長下限,還可以起到讓玩家在頭幾次抽獎必然不中(大)獎的效果。另外在這種模型下,計數器甚至可以對玩家可見,讓看玩家看到進度和目標,感受到獎勵是可達的、近在眼前的。
?
?
?
?
抽獎算法
/// <summary> /// 抽獎 /// </summary> public class Prize {/// <summary>/// 獎品關鍵字/// </summary>public string Key { get; set; }/// <summary>/// 權重/數量/// </summary>public int Poll { get; set; }/// <summary>/// 中獎區間/// </summary>class Area{/// <summary>/// 獎品關鍵字/// </summary>public string Key { get; set; }/// <summary>/// 開始索引位置/// </summary>public int Start { get; set; }/// <summary>/// 截止索引位置/// </summary>public int Over { get; set; }}/// <summary>/// 隨機種子/// </summary>static Random Rand = new Random((int)DateTime.Now.Ticks);/// <summary>/// 輪盤抽獎,權重值(在輪盤中占的面積大小)為中獎幾率/// </summary>/// <param name="prizeList">禮品列表(如果不是百分百中獎則輪空需要加入到列表里面)</param>/// <returns></returns>public static string Roulette(List<Prize> prizeList){if (prizeList == null || prizeList.Count == 0) return string.Empty;if (prizeList.Any(x => x.Poll < 1)) throw new ArgumentOutOfRangeException("poll權重值不能小于1");if (prizeList.Count == 1) return prizeList[0].Key; //只有一種禮品Int32 total = prizeList.Sum(x => x.Poll); //權重和 if (total > 1000) throw new ArgumentOutOfRangeException("poll權重和不能大于1000"); //數組存儲空間的限制。最多一千種獎品(及每種獎品的權重值都是1)List<int> speed = new List<int>(); //隨機種子for (int i = 0; i < total; i++) speed.Add(i);int pos = 0;Dictionary<int, string> box = new Dictionary<int, string>();foreach (Prize p in prizeList){for (int c = 0; c < p.Poll; c++) //權重越大所占的面積份數就越多{pos = Prize.Rand.Next(speed.Count); //取隨機種子坐標box[speed[pos]] = p.Key; //亂序 禮品放入索引是speed[pos]的箱子里面speed.RemoveAt(pos); //移除已抽取的箱子索引號}}return box[Prize.Rand.Next(total)];}/// <summary>/// 獎盒抽獎,每個參與者對應一個獎盒,多少人參與就有多少獎盒/// </summary>/// <param name="prizeList">禮品列表</param>/// <param name="peopleCount">參與人數</param>/// <returns></returns>public static string LunkyBox(List<Prize> prizeList, int peopleCount){if (prizeList == null || prizeList.Count == 0) return string.Empty;if (prizeList.Any(x => x.Poll < 1)) throw new ArgumentOutOfRangeException("poll禮品數量不能小于1個");if (peopleCount < 1) throw new ArgumentOutOfRangeException("參數人數不能小于1人");if (prizeList.Count == 1 && peopleCount <= prizeList[0].Poll) return prizeList[0].Key; //只有一種禮品且禮品數量大于等于參與人數int pos = 0;List<Area> box = new List<Area>();foreach (Prize p in prizeList){box.Add(new Area() { Key = p.Key, Start = pos, Over = pos + p.Poll }); //把禮品放入獎盒區間pos = pos + p.Poll;}int total = prizeList.Sum(x => x.Poll); //禮品總數int speed = Math.Max(total, peopleCount); //取禮品總數和參數總人數中的最大值pos = Prize.Rand.Next(speed);Area a = box.FirstOrDefault(x => pos >= x.Start && pos < x.Over); //查找索引在獎盒中對應禮品的位置return a == null ? string.Empty : a.Key;}}/* List<Prize> prizes = new List<Prize>(); prizes.Add(new Prize() { Key = "電腦", Poll = 1 }); prizes.Add(new Prize() { Key = "機柜", Poll = 2 }); prizes.Add(new Prize() { Key = "鼠標", Poll = 3 });string lp1 = Prize.LunkyBox(prizes, 6); Console.WriteLine(lp1);prizes.Add(new Prize() { Key = "謝謝惠顧", Poll = 5 }); string lp2 = Prize.Roulette(prizes); Console.WriteLine(lp2); */?
?
參考
Return random `list` item by its `weight`
不同概率模型的抽獎體驗
抽獎算法
一個簡單抽獎算法的實現以及如何預防超中
轉載于:https://www.cnblogs.com/HQFZ/p/5945219.html
總結
以上是生活随笔為你收集整理的抽奖算法-指定概率的随机的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Logistic Regression逻
- 下一篇: docker对数据卷进行还原操作