《用Python實現(xiàn)原神中算法》文字版
? ? ? ?第一次在B站上發(fā)文章,可能排版什么的,不是很好看,也希望大家多多包涵。
? ? ? ?由于?上周發(fā)的視頻?內(nèi)容較難,看到很多同學(xué)在 評論區(qū) 和 彈幕 里面說想要這個視頻的文字版,所以想了想,還是給大家寫出來了,主要是代碼的內(nèi)容以及詳細(xì)的注釋,當(dāng)然也希望大家自己去實現(xiàn)一下代碼,不要光聽我說,聽見了沒?聽見了。
? ? ? ?早上四點起來寫的,比較倉促,有什么寫錯的地方,也請在評論區(qū)指出,或者有什么問題,也可以在評論區(qū)提問,我看到后都會進行回復(fù)。本文主要包含四個內(nèi)容:
抽卡算法、狀態(tài)機圖、香菱火圈、拓?fù)渑判?/span>

抽卡算法

? ? ??? 當(dāng)然,我實現(xiàn)的只是一個最簡單的版本,原神怎么實現(xiàn)的,我不可能知道,只是給出一個大概的算法框架,給對這方面有疑惑的朋友一點靈感,你也可以自己去設(shè)計這方面的算法。
1、抽一次

第 3 行,定義一個?chou?函數(shù),cishu代表目前是上一次五星限定角色抽完以后的第幾次抽卡,wai代表這期間歪了幾次,取值為?[0,?1]。
第 4 - 5?行,如果次數(shù)小于等于 73 次,概率為 0.6%,這里統(tǒng)一乘上了?100。
第?6 - 7?行,如果次數(shù)等于第 90 次,概率為 100%,說明必定出五星。
第 9 行,是一個一次函數(shù),代表從 73 抽以后,每抽一次,出五星的概率增加 6%。
第?10 - 11?行,如果隨機出來的概率,不在邊界概率 p,那么代表不是五星,可能是一些辣雞的武器,返回?2。
第 12 - 13 行,否則,一定出五星,這時候如果歪過一次,則這次一定不歪,返回 0。
第 14 行,如果沒有歪過,那么 50% 是歪,50% 不歪,返回 0 和 1 中隨機的一個數(shù)即可。
2、十連三金需要的抽卡次數(shù)

第 21 行,shilian 代表已經(jīng)十連的次數(shù),初始化為 0。
第 22 行,cishu 代表第幾抽。
第 23 行,wai 代表歪過幾次。
第 26 行,x 代表本次十連中有多少個五星角色。
第 27 - 28 行,連續(xù)抽 10 次。
第 29 - 32 行,代表抽到了五星限定角色,則次數(shù)和歪的次數(shù)都要重置。
第 33 - 36 行,代表歪了,則歪的次數(shù)加一,次數(shù)重置。
第 38 行,代表抽到奇奇怪怪的東西,次數(shù)+1。
第 39 行,如果有 3 個五星角色,則輸出是第幾次 十連 的時候達到的這個盛況。?

狀態(tài)機圖

? ? ? ?這里主要涉及到的知識點是圖的概念,并且講到的是一個狀態(tài)機,利用鄰接矩陣來存儲圖,并且通過隨機函數(shù)進行狀態(tài)轉(zhuǎn)移,從而實現(xiàn)隨機序列的生成。
1、C語言實現(xiàn)

第 4 - 9 行,定義的是一個C語言中的二維數(shù)組,其中第 i 行 第 j 列的數(shù)值,代表了第 i 號節(jié)點和第 j 號節(jié)點的有向關(guān)系,當(dāng)且僅當(dāng) adj[i][j] 為 1 時,第 i 號節(jié)點 能夠走到?第 j 號節(jié)點。
第 11 - 13 行,定義了一個函數(shù),用于輸出第 aniId 號節(jié)點的值。
第 17 行,pos 代表當(dāng)前處于哪個節(jié)點。
第 18 行,定義一個死循環(huán),讓程序可以無限進行輸出。
第 19 號,隨機生成下一個節(jié)點的編號 x。
第 20 - 22?行,如果 adj[pos][x] 為 0,代表 pos 不能直接走到 x,那么 x 需要重新隨機?,所以這里采用了 while 循環(huán)的方式;如果?adj[pos][x] 為 1,代表 pos 可以直接走到 x 這個節(jié)點,則跳出循環(huán)。
第 23?行,輸出 x 這個節(jié)點(播放 x 號動畫)。
第 24 行,將 x 賦值給 pos,代表一次迭代,下次就是從 x 開始往后隨機。
2、Python實現(xiàn)

第 2 行,引入 random,用于做隨機數(shù)生成。
第 4 - 9 行,定義一個 Python 2維列表,含義和 C語言 類似。只不過C語言用的是花括號,Python用的是方括號。
第 11 - 12 行,定義了一個函數(shù),用于輸出第 aniId 號節(jié)點的值。
第 16 行,類似 C語言中的 main 函數(shù)。
第 17 行,pos 代表當(dāng)前處于哪個節(jié)點。
第 18 行,定義一個死循環(huán),讓程序可以無限進行輸出。
第 19?號,隨機生成下一個節(jié)點的編號 x。
第 20 - 21?行,如果?adj[pos][x] 為 0,代表 pos 不能直接走到 x,那么 x 需要重新隨機?,所以這里采用了 while 循環(huán)的方式;如果?adj[pos][x] 為 1,代表 pos 可以直接走到 x 這個節(jié)點,則跳出循環(huán)。
第?23?行,輸出 x 這個節(jié)點(播放 x 號動畫)。
第 24 行,將 x 賦值給 pos,代表一次迭代,下次就是從 x 開始往后隨機。
大體上,和C語言的語句結(jié)構(gòu),還是非常相似的。

香菱火圈


第 6 行,獲取標(biāo)準(zhǔn)輸出的句柄。
第 7 行,記錄一個時間 t。
第 8 行,定義一個循環(huán)。
第 9 行,定義火圈的位置。
第 10 行,定義香菱的位置。
第 11 行,定義火圈的半徑為 R。
第 12 行,利用余弦函數(shù),計算香菱火圈的 x 坐標(biāo),由于光標(biāo)的 y 軸是 x 軸的兩倍,所以這里火圈的 x 軸半徑是 2R。
第 13 行,利用正弦函數(shù),計算香菱火圈的 y 坐標(biāo)。
第 14 行,清空屏幕,避免火圈殘留。
第 15? - 16 行,設(shè)置光標(biāo)當(dāng)前位置,并且打印 "香菱"。
第 17 - 18 行,設(shè)置火圈當(dāng)前位置,并且打印 "火圈"。
第 19 - 20 行,F(xiàn)ALSE 代表將光標(biāo)進行隱藏。

拓?fù)渑判?/span>

1、建圖的過程

首先,定義鄰接矩陣,代表有向圖的點和邊的關(guān)系。
visited 數(shù)組代表當(dāng)前這個節(jié)點是否被訪問過。
degree數(shù)組代表當(dāng)前這個節(jié)點的入度(有多少條邊指向它)。
遍歷任意兩個點,如果 adj[i][j] 為 1,則給 j 的入度 加 1。
2、拓?fù)渑判虻倪^程

整個過程就是迭代去找 尚未被訪問?且?入度為 0?的點,存儲到 u 中:

如果找不到則跳出循環(huán),否則標(biāo)記 已訪問:

然后將它轉(zhuǎn)換成字母后進行輸出:

最后將 u 對應(yīng)所有出邊的 端點 的入度減一,此所謂刪邊的操作:

重復(fù)迭代,這個拓?fù)渑判虻倪^程就完成了。

? ? ? ?好啦,如果你想學(xué)習(xí)更多算法,可以?關(guān)注公眾號:夜深人靜寫算法,回復(fù) 666 ,獲取 算法學(xué)習(xí)路線。有什么相關(guān)問題,也可以從公眾號找到我的聯(lián)系方式進行咨詢,或者從這個鏈接直達(無法放站外鏈接,所以需要自己復(fù)制粘貼到瀏覽器打開):https://ufbva3m5zn.feishu.cn/docs/doccnIQ95UPr5yabjQg2bFHl79f#
