最近一直沉迷原神无法自拔,每天花了好几个小时赚原石最后也捞不到几抽,一直体验不了抽卡的满足感。所以不如自己来设计一个抽卡机制模拟原神的抽卡让自己爽爽。
一:了解原神的抽卡机制
要模拟原神抽卡机制我们要先了解一下原神抽卡的概率和保底机制
原神UP池概率机制如下:
在 [1,73] 抽时, 每次出五星角色的概率为 0.6% , 在 [74,90] 抽每次抽卡概率比上次高 6% .
当获取到五星角色时, 有 50% 概率是UP角色, 若这次五星没有抽到UP角色, 下次五星角色必定是UP角色.
五星角色保底为 90 抽, 五星UP角色保底为 180 抽.
二:根据机制构建代码
在了解了原神抽卡机制后我们就开始构建代码了
首先导入必要的库并定义我们需要用到的变量
import random
qualified_five_star=["纳西妲","妮露"]
resident_five_star=["迪卢克","刻晴","莫娜","七七","琴"]
four_star_character=["久岐忍","多莉","莱依拉"]#定义包含卡池所有物品的列表
tsw_number=0#三星物品抽取的数量
fosc={}#所有四星物品
fsc={}#所有五星物品
接下来将五星角色构造成一个类,每次进行抽取都是在对五星角色类的实例方法进行引用
class fivestar():
def __init__(self):
self.probability=0.6/100
self.xiaodabaodi=0
self.baodichoushu=0
def wish(self,times):
self.baodichoushu+=1
#保底抽数大于73时概率增长
if self.baodichoushu>73:
self.probability+=6/100
if self.baodichoushu<90:
#如果满足条件(p:=random.random())<=self.probability抽中了,有50%概率是up角色
if (p:=random.random())<=self.probability and ((k:=random.choice([1,2]))==1 or self.xiaodabaodi==1):
self.xiaodabaodi=0 #属性xiaodabaodi用来记录小保底时是否是up角色,不是则为0,如果是0则下一次保底必为up角色
self.probability=0.6/100
self.baodichoushu=0
return random.choice(qualified_five_star)
elif p<=self.probability and k==2:
self.xiaodabaodi = 1
self.probability = 0.6/100
self.baodichoushu = 0
return random.choice(resident_five_star)
else:
return False
#保底抽数达到90时触发保底
elif self.baodichoushu==90:
if self.xiaodabaodi==1 or (k:=random.choice([1,2]))==1:
self.xiaodabaodi=0
self.probability=0.6/100
self.baodichoushu=0
return random.choice(qualified_five_star)
else:
self.xiaodabaodi = 1
self.probability = 0.6/100
self.baodichoushu = 0
return random.choice(resident_five_star)
同样的,构造四星物品类(其实就是改了一下概率和保底抽数)
class fourstar():
def __init__(self):
self.probability=5.1/100
self.baodichoushu=0
def wish(self,times):
self.baodichoushu+=1
#概率增长
if self.baodichoushu>5:
if self.probability>=1:
self.probability=1
else:
self.probability+=random.uniform(0.01/5,0.90/5)
if self.baodichoushu<10:
if (p:=random.random())<=self.probability and (k:=random.choice([1,2]))==1:
self.probability=5.1/100
self.baodichoushu=0
return random.choice(four_star_character)
elif p<=self.probability and k==2:
self.probability = 5.1/100
self.baodichoushu = 0
return 'four star weapon'
else:
return False
elif self.baodichoushu==10:
if (k:=random.choice([1,2]))==1:
self.probability=5.1/100
self.baodichoushu=0
return random.choice(four_star_character)
else:
self.probability = 5.1/100
self.baodichoushu = 0
return 'four star weapon'
然后再将两个类实例化,得到五星角色和四星角色的实例
a=fivestar()
b=fourstar()
最后利用循环模拟不停抽卡的过程并用try except语句防止输入无效内容,将每个抽到的角色存入字典,并在输出时调用。
try:
times = int(input("how many wish times"))
for t in range(1,times+1):
if (j:=a.wish(t))!=False:
fsc.update({t:j})
continue
elif (q:=b.wish(t))!=False:
fosc.update({t:q})
continue
else:
tsw_number+=1
for key,value in fsc.items():
print("你获得了五星角色\t{},在第{:0>5d}抽时获得".format(value,key))
for key,value in fosc.items():
print("你获得了四星角色/物品\t{},在第{:0>5d}抽时获得".format(value,key))
print('你获得了{:0>5d}件三星武器'.format(tsw_number))
except ValueError:
print("invalid input,please try again")
(注:因为抽到的角色可能重复,而重复的键会被字典吞掉,但抽数一直增长不会重复,所以这里用抽数作为键,角色名称作为值)
三:完整代码及运行结果
import random
qualified_five_star=["纳西妲","妮露"]
resident_five_star=["迪卢克","刻晴","莫娜","七七","琴"]
four_star_character=["久岐忍","多莉","莱依拉"]
tsw_number=0
fosc={}
fsc={}
class fivestar():
def __init__(self):
self.probability=0.6/100
self.xiaodabaodi=0
self.baodichoushu=0
def wish(self,times):
self.baodichoushu+=1
# 概率增长
if self.baodichoushu>73:
self.probability+=6/100
if self.baodichoushu<90:
if (p:=random.random())<=self.probability and ((k:=random.choice([1,2]))==1 or self.xiaodabaodi==1):
self.xiaodabaodi=0
self.probability=0.6/100
self.baodichoushu=0
return random.choice(qualified_five_star)
elif p<=self.probability and k==2:
self.xiaodabaodi = 1
self.probability = 0.6/100
self.baodichoushu = 0
return random.choice(resident_five_star)
else:
return False
elif self.baodichoushu==90:
if self.xiaodabaodi==1 or (k:=random.choice([1,2]))==1:
self.xiaodabaodi=0
self.probability=0.6/100
self.baodichoushu=0
return random.choice(qualified_five_star)
else:
self.xiaodabaodi = 1
self.probability = 0.6/100
self.baodichoushu = 0
return random.choice(resident_five_star)
class fourstar():
def __init__(self):
self.probability=5.1/100
self.baodichoushu=0
def wish(self,times):
self.baodichoushu+=1
#概率增长
if self.baodichoushu>5:
if self.probability>=1:
self.probability=1
else:
self.probability+=random.uniform(0.01/5,0.90/5)
if self.baodichoushu<10:
if (p:=random.random())<=self.probability and (k:=random.choice([1,2]))==1:
self.probability=5.1/100
self.baodichoushu=0
return random.choice(four_star_character)
elif p<=self.probability and k==2:
self.probability = 5.1/100
self.baodichoushu = 0
return 'four star weapon'
else:
return False
elif self.baodichoushu==10:
if (k:=random.choice([1,2]))==1:
self.probability=5.1/100
self.baodichoushu=0
return random.choice(four_star_character)
else:
self.probability = 5.1/100
self.baodichoushu = 0
return 'four star weapon'
a=fivestar()
b=fourstar()
try:
times = int(input("how many wish times"))
for t in range(1,times+1):
if (j:=a.wish(t))!=False:
fsc.update({t:j})
continue
elif (q:=b.wish(t))!=False:
fosc.update({t:q})
continue
else:
tsw_number+=1
for key,value in fsc.items():
print("你获得了五星角色\t{},在第{:0>5d}抽时获得".format(value,key))
for key,value in fosc.items():
print("你获得了四星角色/物品\t{},在第{:0>5d}抽时获得".format(value,key))
print('你获得了{:0>5d}件三星武器'.format(tsw_number))
except ValueError:
print("invalid input,please try again")
那么我们这就完成了原神抽卡机制的初步模拟,当然也只是玩玩的程度,真正游戏的抽卡算法远不止这么简单。我也还是个小白,请各位大佬批评指正!!!
文章引用:【知乎】一文说清楚原神抽卡机制, 概率, 期望等问题——Pandora Eartha