使用python基本函数实现简易的《原神》抽卡系统

前言

最近迷上了《原神》这款游戏,其中的抽卡系统也是很让人上瘾,尤其是1.3版本更新中魈的up池的开启,不知不觉氪金数额已近千元。看着瘪瘪的腰包,我想:为什么不自己写一个抽卡系统,爽个够?
说干就干

基本思路

原神的抽卡系统可以建立在单抽的基础上,主要有单抽和十连这两种选项。抛开其概率的设定不说,卡池分别包含五星角色(因为是模拟的魈up池所以没有五星武器)、四星角色、四星武器和三星武器。五星和四星又分别有保底政策。在抽卡函数之外,还需要一定的交互界面,比如查询、充值等选项。
大致思路如上,以下为具体做法

抽卡基本函数

先来个这个:

import random

抽卡概率设定

此处我使用的是random函数,由于也不是很懂设置概率的操作,直接就用生成随机数,再判断随机数的区间,只要把区间范围圈定,可以简单地设置抽卡的概率。代码如下:

def single():
    """不保底时的抽奖"""
    i = random.randint(1, 10001)#生成10000个整数
    if i in range(1, 61):#五星中奖概率为0.6%
        a = random.randint(0, 5)
        star = st5[a]
        stat.num_5 = 0
    elif i in range(61, 316):#四星角色概率为2.55%
        cha = random.randint(0, len(cha_4)-1)
        star = cha_4[cha]
        stat.num_4 = 0
    elif i in range(316, 571):#四星武器概率为2.55%
        wea = random.randint(0, len(weapon_4)-1)
        star = weapon_4[wea]
        stat.num_4 = 0
    elif i in range(571, 10001):#其余为三星
        star = '三星'
    else:
    #不知道为什么,实际操作中总是会生成写奇奇怪怪的
    #东西,为了不影响原函数,这里else直接忽视
        return None
    if star == up:
        stat.num_5 = 0
        stat.up_num = 0
    add(star)#这个函数会在后面解释

卡池

为了不影响阅读,还是把卡池内容贴上吧

"""卡池内容(未设置四星up角色)"""
up = '魈'
st5 = [up, up, up, up, up, '刻晴', '莫娜', '七七', '迪卢克', '琴']
cha_4 = ['安柏', '丽莎', '凯亚', '芭芭拉', '雷泽', '菲谢尔', '班尼特', '诺艾尔', '菲谢尔', '砂糖',
         '迪奥娜', '北斗', '凝光', '香菱', '行秋', '重云', '辛焱']
weapon_4 = ['弓藏', '祭礼弓', '绝弦', '西风猎弓', '昭心', '祭礼残章', '流浪乐章', '西风秘典', '西风长枪',
            '雨裁', '匣里灭辰', '祭礼大剑', '钟剑', '西风大剑', '匣里龙吟', '祭礼剑', '笛剑', '西风剑', '岩盔丘丘王']
st4 = weapon_4 + cha_4
get = []#这是每次抽奖后存储抽出内容的列表
have = []#这是存储总抽出内容的列表

保底策略

写程序的时候,这个是让我比较头疼的地方。一开始我想用简单的if-else,未果后尝试while,最后才想起来正解:引入跟踪游戏数据的类

class Stats:
    """跟踪游戏统计信息"""
    def __init__(self):
        self.total = 0#记录总抽卡次数(似乎没用到)
        self.up_num = 0#记录up保底次数(180发保底)
        self.num_4 = 0#记录四星保底次数(10发保底)
        self.num_5 = 0#记录五星保底次数(90发保底)
        self.stone = 0#这个用于充值系统,记录原石数

本来需要考虑到“抽到五星后,下一个五星必为up角色这一政策,但是嗯…我的方法的执行效果似乎是一样的
利用这个统计信息,每抽一次卡,如果没有出现期望的物品,对应数据就会+1,从而累积起来,到达保底数时,触发保底政策。
保底函数如下

def check_up():
    """检查保底"""
    if stat.up_num < 179:#检查up角色保底
        if stat.num_5 < 89:#检查五星保底
            if stat.num_4 < 9:#检查四星保底
                single()#如果没到保底,就正常抽卡
            else:
            #如果到保底了,就直接送出期望物品
                o_4 = random.randint(0, len(st4) - 1)
                star = st4[o_4]
                add(star)
                stat.num_4 = 0
        else:#同理,不赘述了
            o_5 = random.randint(0, len(st5) - 1)
            star = st5[o_5]
            add(star)
            stat.num_5 = 0
    else:
        star = up
        add(star)
        stat.up_num = 0

但还是有一点小小的问题:假如,这一抽既是五星保底的第九十发,也是四星保底的第十发,此时到底该出五星还是四星。不是很清楚米哈游如何解决这个问题,抽奖文案中也没有提及。我就偷个懒不考虑了,直接设置优先级:up>五星>四星,嘿嘿
另外,关于对运行数据的累计,那个函数会在下一节提到。也不难想不是

抽卡结束做什么

也就是上面提到的function:add()
这个函数会在每次抽卡后执行,不管是触发保底还是正常抽卡,主要做记录结果的工作
代码如下:

def add(star):
    """每次抽卡完毕的常规操作"""
    record(star)#记录保底数据
    get.append(star)#将抽到的物品加入单次显示
    have.append(star)#将抽到的内容加入背包
    stat.total += 1#抽奖次数记录+1(真的没用到)

record()函数负责记录保底数据,代码如下:

def record(star):
    """记录数据变化"""
    if star != '魈':#抽不到就加一
        stat.up_num += 1
    if star not in st4:
        stat.num_4 += 1
    if star not in st5:
        stat.num_5 += 1

统计背包

抽完卡后,背包have列表还是比较凌乱的,我对其借用了个统计,制成字典以更条理地显示所获物品

def remember():
    """统计抽卡内容"""
    value_cnt = {}#将中奖添加到列表里
    for h in have:
        value_cnt[h] = value_cnt.get(h, 0) + 1
    print(value_cnt)

抽奖操作

这里分为单抽和十连,由于每次抽奖都需要在get列表中显示抽奖结果,两种函数均需在调用时清空get[]
单抽函数代码如下:

def extract():
    """单抽"""
    if stat.stone >= 160:#这里添加了个判断原石
        del get[:]
        check_up()
        stat.stone -= 160
        print(get)
    else:#充值系统我放在交互程序的文件里了
        print('您的原石不足,请充值!')

十连函数如下:

def ten():
    """十连函数"""
    if stat.stone >= 1600:
        del get[:]
        for num in range(0, 10):#操作十次
            check_up()
        stat.stone -= 1600
        print(get)
    else:
        print('您的原石不足,请充值!')

至此,抽卡系统已制作完成,下面是交互系统的制作

交互系统

这一部分比较简单,就是各种逻辑判断,运行时也只是在python终端里通过用户输入来实现,相对而言较为简陋。
需要引入的库:

import main#也就是上面那个抽奖系统
from time import sleep

首先是开始运行的显示

print('正在加载配置文件...')
sleep(1)#嘿嘿,加点儿正式感
print('欢迎使用《原神》模拟抽卡系统,随时输入q以退出')
while True:
    print('请输入对应字母以进入相应功能:\n[A]开始祈愿\t[B]祈愿记录\t[C]充值\t[q]退出')
    msg = input('')

开始祈愿

话不多说,上代码

    if msg.title() == 'A':
        yi = input('请选择:\n[A]祈愿1次\t[B]祈愿10次\n')
        if yi.title() == 'A':
            sleep(1)#sleep,营造氛围嘛
            main.extract()
            sleep(0.5)
            continue
        elif yi.title() == 'B':
            sleep(1)
            main.ten()
            sleep(0.5)
            continue
        elif yi.title() == 'q':
            break
        else:
            print('请输入正确的选项!')
            sleep(1)
            continue

祈愿记录

    if msg.title() == 'B':
        num = len(main.have)
        print('您已进行' + str(num) + '次祈愿')
        print('其中有:')
        main.remember()#显示背包的统计
        sleep(1.5)
        continue

充值系统

用了冗长的判断,好丑

    if msg.title() == 'C':
        print('您当前原石余额为:' + str(main.stat.stone))
        chose = input('请选择充值金额:\n[A]6元(加赠60原石)\t[B]30元(加赠300原石)\t[C]98元(加赠980原石)'
                      '\n[D]198元(加赠1980原石)\t[E]328元(加赠3280原石)\t[F]648元(加赠6480原石)\n[G]返回\n')
        if chose.title() == 'A':
            main.stat.stone += 120
        elif chose.title() == 'B':
            main.stat.stone += 600
        elif chose.title() == 'C':
            main.stat.stone += 1960
        elif chose.title() == 'D':
            main.stat.stone += 3960
        elif chose.title() == 'E':
            main.stat.stone += 6480
        elif chose.title() == 'F':
            main.stat.stone += 12960
        elif chose.title() == 'G':
            continue
        elif chose == 'q':
            break
        else:
            print('请输入正确的选项!')
            continue
        print('充值成功!当前余额为:' + str(main.stat.stone))
        sleep(1.5)
        continue

退出

#while...
    if msg == 'q':
        break
print('感谢您使用模拟抽卡系统,祝您游戏愉快!')
sleep(1.5)

结语

这个抽卡系统还不是很完善,交互界面也比较丑陋,只能说是做了最底层的逻辑。这也是我在学了一个月python后第一次独立的项目实训,确实从中感到了编程的乐趣。
如果有什么对代码有补充的地方,欢迎在评论区交流。喜欢的话,也请点个小小的赞
此项目已上传GitHub,地址:https://github.com/juer-joker/Genshin

  • 16
    点赞
  • 122
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值