• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            WisKeyのLullaby

            huangwei.pro 『我失去了一只臂膀』「就睜開(kāi)了一只眼睛」

              C++博客 :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
              12 Posts :: 0 Stories :: 23 Comments :: 0 Trackbacks

            公告

            “我該走哪條路?”
            “這取決于你要去哪里。”
            “我只想能到某個(gè)地方。”
            “只要你走的夠遠(yuǎn),你始終能到達(dá)那個(gè)地方。”

            Home: huangwei.pro
            E-Mail: sir.huangwei [at] gmail.com
            09.6 畢業(yè)于杭州電子科技大學(xué)
            進(jìn)入網(wǎng)易杭州研究院工作至今

            常用鏈接

            留言簿(1)

            我參與的團(tuán)隊(duì)

            搜索

            •  

            積分與排名

            • 積分 - 51415
            • 排名 - 443

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            http://huangwei.pro/2015-07/game-random/


            這段時(shí)間公司開(kāi)發(fā)的游戲上線測(cè)試,許多玩家在抽卡時(shí)抱怨臉黑,很難抽到所需要的卡牌,而又有一部分玩家反應(yīng)運(yùn)氣好能連著抽到紫卡,檢查了下隨機(jī)相關(guān)邏輯代碼,并沒(méi)有找出問(wèn)題所在,玩家運(yùn)氣好與壞只是覺(jué)得真有可能是概率原因。


            測(cè)試開(kāi)服了幾天之后,需要開(kāi)放某個(gè)限時(shí)抽卡活動(dòng),在內(nèi)部測(cè)試時(shí),我們發(fā)現(xiàn)玩家反應(yīng)的問(wèn)題在限時(shí)抽卡中格外明顯,尤其是其中最主要的一張稀有卡牌,猜測(cè)因?yàn)橄迺r(shí)抽卡庫(kù)配置的種類較少,然后就拿該活動(dòng)來(lái)檢查了下我們游戲隨機(jī)機(jī)制問(wèn)題。

            5%概率?20次出現(xiàn)一次?

            大部分游戲策劃使用權(quán)值來(lái)配置隨機(jī)概率,因?yàn)闄?quán)值有個(gè)好處就是可以在增加隨機(jī)物品時(shí),可以不對(duì)之前的配置進(jìn)行更改,比如:白卡 30,藍(lán)卡 10,紫卡 10,轉(zhuǎn)為概率即是:白卡 60%,藍(lán)卡 20%,紫卡 20%。

            而上述限時(shí)抽卡的例子中,我們的權(quán)值配置是5和95,模擬50000次隨機(jī)(使用系統(tǒng)隨機(jī)函數(shù),如C的rand函數(shù),Python的random庫(kù))得到如下結(jié)果:

            按權(quán)值隨機(jī)50000次

            上圖繪制的是權(quán)值為5的卡牌的隨機(jī)狀態(tài),紅色的圖是分布圖,X軸是出現(xiàn)的次數(shù),Y軸是相同卡牌再次出現(xiàn)的間隔。綠色的圖是分布概率圖,X軸是間隔數(shù),Y軸是概率。按策劃的想法,5%概率應(yīng)該等同于20次出現(xiàn)一次,那上圖很明顯并不滿足20次出現(xiàn)一次出現(xiàn)規(guī)則,實(shí)際間隔從近到遠(yuǎn)呈下坡形狀分布,就是說(shuō)相鄰的概率最大,間隔最大超過(guò)160,這與玩家所吐槽的抽卡體驗(yàn)是一致的。但50000次隨機(jī)總共出現(xiàn)了2508次,從統(tǒng)計(jì)的意義上來(lái)說(shuō)又是符合5%概率的。所以這個(gè)問(wèn)題,究其原因就是所謂的概率是統(tǒng)計(jì)意義上的還是分布意義上的問(wèn)題。

            最原始的實(shí)現(xiàn)

            我用列表里取元素的方式來(lái)模擬20次出現(xiàn)一次,為了方便比較異同,直接隨機(jī)的方式我也貼上相關(guān)代碼。

            pool = [0]*5 + [1]*95 result = [random.choice(a) for i in xrange(N)] 

            上面是直接隨機(jī)的方式,只保證5%概率

            pool = [] result = [] for i in xrange(N): if not pool: pool = [0]*1 + [1]*19 random.shuffle(pool) result.append(pool[-1]) del pool[-1] 

            上面是打亂列表,然后依次取元素的方式,保證20次出現(xiàn)一次,而5%概率則是隱含在內(nèi)的,生成效果如下圖。

            使用第二種實(shí)現(xiàn)的隨機(jī)分布

            該圖明顯跟第一個(gè)實(shí)現(xiàn)的圖不一樣,上圖表明了間隔基本上是落在[0, 40]的區(qū)間內(nèi),并且均勻分布在20那條藍(lán)色對(duì)稱線附近。這個(gè)才是最終想要的隨機(jī)的效果。紅色的線是正態(tài)分布曲線,是不是很相似?后面我會(huì)講到。

            眼尖的會(huì)發(fā)現(xiàn)在第一個(gè)實(shí)現(xiàn)中我用的pool是[0]*5 + [1]*95,而第二個(gè)實(shí)現(xiàn)中我用的是[0]*1 + [1]*19

            這里20次出現(xiàn)一次并不等同于100次出現(xiàn)五次,也是從分布的意義上來(lái)說(shuō)的,100次出現(xiàn)五次是存在5次連續(xù)出現(xiàn)的可能。

            針對(duì)策劃的配置,我們需要進(jìn)行預(yù)處理,怎么處理?GCD啊~,5和95的最大公約數(shù)是5,所以在第二個(gè)實(shí)現(xiàn)的代碼中我直接使用了1和19。

            但這里有個(gè)問(wèn)題,一般策劃配置的隨機(jī)庫(kù)中肯定有多個(gè)物品。權(quán)值如果配置的比較隨意的話,很可能就導(dǎo)致GCD為1,這樣想要實(shí)現(xiàn)XX次出現(xiàn)一次就不可行了。比如剛才的權(quán)值配置5和95,再加一個(gè)權(quán)值為11的話,就只能實(shí)現(xiàn)111次出現(xiàn)5次

            所以這兩種依賴列表的隨機(jī)方式并不適用,一是需要維護(hù)的列表內(nèi)存會(huì)比較大,二是對(duì)策劃配置方式有過(guò)多約束。

            更通用更優(yōu)美的實(shí)現(xiàn)

            20次出現(xiàn)一次是以20為標(biāo)準(zhǔn)周期,當(dāng)然不能每次都是間隔20出現(xiàn),這樣就太假了,根本沒(méi)有隨機(jī)感受可言,為了模擬隨機(jī)并可以控制一定的出現(xiàn)頻率,我選擇正態(tài)分布來(lái)進(jìn)行偽隨機(jī)分布生成,原因是分布會(huì)更自然一些。

            正態(tài)分布

            關(guān)于正態(tài)分布這里就不詳細(xì)描述了,只需關(guān)心分布的兩個(gè)參數(shù)即可,位置參數(shù)為μ、尺度參數(shù)為σ。根據(jù)正態(tài)分布,兩個(gè)標(biāo)準(zhǔn)差之內(nèi)的比率合起來(lái)為95%;三個(gè)標(biāo)準(zhǔn)差之內(nèi)的比率合起來(lái)為99%。

            根據(jù)正態(tài)分布,兩個(gè)標(biāo)準(zhǔn)差之內(nèi)的比率合起來(lái)為95%;三個(gè)標(biāo)準(zhǔn)差之內(nèi)的比率合起來(lái)為99%

            用上面的例子來(lái)定下參數(shù),μ=20,σ=20/3,這樣每次按正態(tài)分布隨機(jī),就能得到一個(gè)理想的隨機(jī)分布和概率區(qū)間。

            C語(yǔ)言標(biāo)準(zhǔn)函數(shù)庫(kù)中只有rand,如何生成符合正態(tài)分布的隨機(jī)數(shù)可以參見(jiàn)WiKi上的介紹。這里我直接使用Python中random庫(kù)中的normalvariate函數(shù),當(dāng)然gauss函數(shù)也是一樣的,官方文檔上說(shuō)gauss函數(shù)會(huì)快些,StackOverFlow上說(shuō)gauss是非線程安全函數(shù),所以會(huì)快。我自己簡(jiǎn)單測(cè)試了下,在單線程情況下,gauss是會(huì)快些,但只是快了一點(diǎn)點(diǎn)而已。

            首先,我直接生成權(quán)值為5的卡牌的間隔,檢驗(yàn)下正態(tài)分布的隨機(jī)效果。

            NN = int(N*0.05) mu, sigma = 20, 20/3. delta = [int(random.normalvariate(mu, sigma)) for i in xrange(NN)] 

            模擬正態(tài)分布的偽隨機(jī)

            這圖是不是比第二個(gè)實(shí)現(xiàn)的圖更好看一些,分布也更平滑一些呢。OK,接下來(lái)就是替換舊的隨機(jī)算法了。

            細(xì)節(jié)和優(yōu)化

            剛才說(shuō)了隨機(jī)庫(kù)中會(huì)有很多物品,都需要按照各自的權(quán)值隨機(jī),并各自出現(xiàn)頻率符合正態(tài)分布。下面我們來(lái)說(shuō)說(shuō)細(xì)節(jié)。

            wtp = [1.*x/sum(wt) for x in wt] result = [] p = [random.normalvariate(1./x, 1./x/3.) for x in wtp] for i in xrange(N): minp = 1.e9 minj = -1 for j, pp in enumerate(p): if pp < minp: minp = pp minj = j result.append(minj) for j, pp in enumerate(p): p[j] -= minp p[minj] = random.normalvariate(1./wtp[minj], 1./wtp[minj]/3.) 

            這里我使用了統(tǒng)一的隨機(jī)種子,隨機(jī)測(cè)試了500萬(wàn)次后,所得的結(jié)果與多個(gè)隨機(jī)種子差別不大。

            簡(jiǎn)單解釋下代碼:初始化對(duì)所有物品按權(quán)值進(jìn)行正態(tài)分布隨機(jī),每次取位置最小值的物品(也就是最先出現(xiàn)的),然后其它物品均減去該值,被取出的物品再單獨(dú)進(jìn)行一次正態(tài)分布隨機(jī),再次循環(huán)判斷位置最小值。

            這里,每次都需要對(duì)所有物品進(jìn)行求最小值和減法,都是需要遍歷的運(yùn)算,我們可以有如下優(yōu)化。

            例如:(1,3,4) -> 取1減1, (0,2,3) -> 隨機(jī)1, (1,2,3),其實(shí)我們只是為了保持各物品之間位置的相對(duì)順序即可,將對(duì)其它物品的減法變成對(duì)自己的加法,操作量級(jí)立馬從O(N)縮為O(1) 。

            如上面的例子:(1,3,4) -> 取1, (0,3,4) -> 隨機(jī)1加1, (2,3,4),這樣的操作不會(huì)改變物品序列的正確性。

            熟悉最小堆的朋友,將查找最小值優(yōu)化到O(1)應(yīng)該也沒(méi)啥問(wèn)題吧。

            wtp = [1.*x/sum(wt) for x in wt] result = [] p = [(random[i].normalvariate(1./x, 1./x/3.), i) for x in wtp] heapq.heapify(p) for i in xrange(N): minp, minj = heapq.heappop(p) result.append(minj) heapq.heappush(p, (random[minj].normalvariate(1./wtp[minj], 1./wtp[minj]/3.)+minp, minj)) 

            測(cè)試結(jié)果

            問(wèn)題分析和算法實(shí)現(xiàn)就到這了,替換進(jìn)我的游戲里看看什么效果,我已經(jīng)迫不及待了。

            物品測(cè)試權(quán)值序列[10, 30, 50, 110, 150, 200, 250, 500],隨機(jī)測(cè)試500萬(wàn)次。

            第一個(gè)隨機(jī)實(shí)現(xiàn) 
            第一個(gè)隨機(jī)實(shí)現(xiàn)

            第一個(gè)實(shí)現(xiàn)是只符合統(tǒng)計(jì)要求,不符合分布要求。

            第二個(gè)隨機(jī)實(shí)現(xiàn) 
            第二個(gè)隨機(jī)實(shí)現(xiàn)

            第二個(gè)實(shí)現(xiàn)中對(duì)權(quán)值序列進(jìn)行了GCD,可以看到只有綠色是符合分布要求的,而藍(lán)色和青色退化成第一種實(shí)現(xiàn)。

            基于正態(tài)分布的隨機(jī)實(shí)現(xiàn) 
            基于正態(tài)分布的隨機(jī)實(shí)現(xiàn)

            完美!

            玩家體驗(yàn)

            最好每個(gè)玩家有各自的隨機(jī)種子,否則會(huì)造成體驗(yàn)上的誤差。服從正態(tài)分布的全局隨機(jī)序列,不同玩家任意的取走序列中一段或者一些值,就可能導(dǎo)致對(duì)于每個(gè)玩家而言,各自取出的隨機(jī)序列不再服從正態(tài)分布。

            結(jié)束

            我只能感嘆Python的庫(kù)太強(qiáng)大了,matplotlib繪制出來(lái)的圖形也挺漂亮的,感興趣的童鞋可以查閱用Python做科學(xué)計(jì)算

            更多內(nèi)容請(qǐng)移步huangwei.pro

            posted on 2015-07-27 01:20 威士忌 閱讀(3416) 評(píng)論(4)  編輯 收藏 引用

            Feedback

            # re: 游戲中的隨機(jī)概率 2015-07-27 16:54 GameBoy
            C++ 有normal_distribution實(shí)現(xiàn)正態(tài)分布  回復(fù)  更多評(píng)論
              

            # re: 游戲中的隨機(jī)概率 2015-07-28 11:55 KaleoVon
            在游戲中做強(qiáng)化之類概率的時(shí)候,也遇到了這種問(wèn)題,好文章  回復(fù)  更多評(píng)論
              

            # re: 游戲中的隨機(jī)概率 2015-08-31 14:18 freeeyes
            非常不錯(cuò),主要是以誰(shuí)為1的問(wèn)題。好文章,記錄了。  回復(fù)  更多評(píng)論
              

            # re: 游戲中的隨機(jī)概率 2015-12-01 17:16 mmocake
            Python的庫(kù)確實(shí)強(qiáng)大 MARK下  回復(fù)  更多評(píng)論
              


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            99久久99这里只有免费费精品 | 99999久久久久久亚洲| 久久亚洲AV无码精品色午夜麻豆| 国内精品伊人久久久影院| 亚洲午夜久久久久久噜噜噜| 性欧美大战久久久久久久久| 97精品久久天干天天天按摩| 亚洲狠狠综合久久| 狠狠色丁香婷婷久久综合| 亚洲AV成人无码久久精品老人| 久久国产欧美日韩精品| 国产精品久久久久一区二区三区 | 久久99国产精品二区不卡| 91精品国产91久久| 99精品国产免费久久久久久下载| 久久亚洲AV成人出白浆无码国产 | 日日狠狠久久偷偷色综合96蜜桃 | 2020国产成人久久精品 | 久久久久九国产精品| 少妇人妻综合久久中文字幕 | 亚洲国产成人乱码精品女人久久久不卡 | 国产精品18久久久久久vr| 久久影院午夜理论片无码| 色欲久久久天天天综合网精品| 国产亚洲精午夜久久久久久| 久久精品国产免费观看| 成人a毛片久久免费播放| 日本WV一本一道久久香蕉| 91精品国产综合久久四虎久久无码一级| 欧美亚洲另类久久综合婷婷 | 亚洲国产精品无码久久久久久曰 | 久久精品亚洲AV久久久无码 | 色综合久久久久久久久五月| 精品99久久aaa一级毛片| 久久久无码一区二区三区| 久久受www免费人成_看片中文| 国产精品久久亚洲不卡动漫| 77777亚洲午夜久久多人| 日韩va亚洲va欧美va久久| 香蕉久久一区二区不卡无毒影院| 99久久国产宗和精品1上映|