用Python简单模拟《原神》抽卡系统

本文详细讲解了如何基于Python实现一个《原神》风格的抽卡系统,涉及概率计算、保底机制和结果展示。
摘要由CSDN通过智能技术生成

原始代码参考自另一位博主的文章:

用Python简单模拟《原神》抽卡系统_抽卡系统怎么做出来的-CSDN博客

在其代码上修复了一些概率的小问题,以及增加了显示效果和统计。

效果如下

直接贴上code

"""
要求:180抽大保底,90抽小保底
10抽必出4星
90抽必出5星  抽到的时候up和常驻各占50%
P = {
0.006                       i<=73
0.006 + 0.06(i - 73)        74<=i<=89
1                           i=90
}
五星中奖概率为0.6%
四星概率为5.1%
其余的三星概率是96.85%
大保底小报底各占50%
"""
import os
import random
from collections import Counter
import colorama
from colorama import Fore, Back, Style

# 初始化抽卡的概率
def rate_initialization():
    rate_list.clear()
    rate_list.extend(['蓝' for temp in range(9430)])
    rate_list.extend(['紫' for temp in range(510)])
    rate_list.extend(['金' for temp in range(60)])
    random.shuffle(rate_list)

# 74抽之后增加概率
def rate_update(already_times):
    rate_threshold = 73
    rate_dict = Counter(rate_list)
    if already_times >= rate_threshold:
        expected_fiveStar_num = 60 + 600 * (already_times + 1 - rate_threshold)
        if expected_fiveStar_num > rate_dict['金']:
            for _ in range(expected_fiveStar_num-rate_dict['金']):
                if '蓝' in rate_list:
                    rate_list.remove('蓝')
                elif '紫' in rate_list:
                    rate_list.remove('紫')
                else:
                    return
                rate_list.append('金')
            random.shuffle(rate_list)

# 大保底还是小保底
def get_isGuarantees():
    try:
        with open('recording\\isGuarantees.txt', 'r', encoding='utf-8') as file:
            if file.read() == 'true':
                isGuarantees = True 
            else:
                isGuarantees = False
    except BaseException:
        with open('recording\\isGuarantees.txt', 'w+', encoding='utf-8') as file:
            file.write('false')
        with open('recording\\isGuarantees.txt', 'r', encoding='utf-8') as file:
            if file.read() == 'true':
                isGuarantees = True
            else:
                isGuarantees = False
    return isGuarantees

# 根据是否大保底,出金
def guarantees():
    isGuarantees = get_isGuarantees()

    if isGuarantees:
        with open('recording\\isGuarantees.txt', 'w+', encoding='utf-8') as file:
            file.write('false')
        return True
    else:
        res = random.choice(['up', 'resident'])
        if res == 'up':
            with open('recording\\isGuarantees.txt', 'w+', encoding='utf-8') as file:
                file.write('false')
            return True
        else:
            with open('recording\\isGuarantees.txt', 'w+', encoding='utf-8') as file:
                file.write('true')
            return False


# 创建一个文件夹在同一个目录下
def mkdir(path):
    folder = os.path.exists(path)
    if not folder:  # 判断文件夹是否存在
        os.makedirs(path)  # 不存在就新建一个


# 抽卡次数记录
def record_times(number):
    with open('recording\\times.txt', 'w+', encoding='utf-8') as file:
        file.write(str(number))


# 抽卡次数读取
def read_times():
    try:
        with open('recording\\times.txt', 'r', encoding='utf-8') as file:
            number = int(file.read())
            return number
    except BaseException:
        with open('recording\\times.txt', 'w+', encoding='utf-8') as file:
            file.write('0')
        return 0

# 记录紫色保底,10抽必出紫色
def record_rare(number):
    with open('recording\\rare.txt', 'w+', encoding='utf-8') as file:
        file.write(str(number))


# 读取紫色保底
def read_rare():
    try:
        with open('recording\\rare.txt', 'r', encoding='utf-8') as file:
            return int(file.read())
    except BaseException:
        with open('recording\\rare.txt', 'w+', encoding='utf-8') as file:
            file.write('0')
            return 0

# 写入抽卡记录
def recode_gacha(result):
    with open('抽卡记录.txt', 'r', encoding='utf-8') as file:
        record_list = file.read()
        if len(record_list) >= 300:
            with open('抽卡记录.txt', 'a+', encoding='utf-8') as writeFile:
                pass
            file.write(result)
        else:
            with open('抽卡记录.txt', 'a+', encoding='utf-8') as writeFile:
                pass


mkdir('卡池')
mkdir('recording')
while True:
    try:
        with open('卡池\\up.txt', 'r', encoding='utf-8') as tempFile:
            up = tempFile.read()
        with open('卡池\\fiveStar.txt', 'r', encoding='utf-8') as tempFile:
            fiveStar = tempFile.read().split(sep=' ')
            random.shuffle(fiveStar)
        with open('卡池\\fourStar_up.txt', 'r', encoding='utf-8') as tempFile:
            fourStar_up = tempFile.read().split(sep=' ')
            random.shuffle(fourStar_up)
        with open('卡池\\fourStar.txt', 'r', encoding='utf-8') as tempFile:
            fourStar = tempFile.read().split(sep=' ')
            fourStar = [item for item in fourStar if item not in fourStar_up]
            random.shuffle(fourStar)
        with open('卡池\\threeStar.txt', 'r', encoding='utf-8') as tempFile:
            threeStar = tempFile.read().split(sep=' ')
            random.shuffle(threeStar)
        break
    except BaseException:
        print('你好,欢迎使用本模拟器,我在上面帮你创建了几文件夹,在里面填入卡池的东西就好了,用空格隔开')
        with open('卡池\\up.txt', 'w+', encoding='utf-8'):
            pass
        with open('卡池\\fiveStar.txt', 'w+', encoding='utf-8'):
            pass
        with open('卡池\\fourStar.txt', 'w+', encoding='utf-8'):
            pass
        with open('卡池\\threeStar.txt', 'w+', encoding='utf-8'):
            pass
        input('填好了就回个车')

colorama.init()
rate_list = list()
rate_initialization()
get_rare_roles = []
total_num = 0
fourStar_isGuarantees = False
while True:

    already_times = read_times()
    already_rare = read_rare()

    print("\n -> 小保底已垫了%d抽" % already_times)
    isGuarantees = get_isGuarantees()
    if isGuarantees:
        print(" -> 大保底在手,不慌~")
    else:
        print(" -> 没大保底,祝您出金不歪~")
    print("已抽卡%d次" % total_num)

    try:
        input_content = input('\n请输入抽数,退出请输入q\n请输入:')
        if input_content == 'q':
            print("\n抽卡统计:")
            print("本次总计抽卡%d次" % total_num)
            print("出(4星/5星)角色情况:")
            counts = dict(Counter(get_rare_roles))
            print(counts)
            exit(0)
        else:
            count = int(input_content)
            total_num += count
    except ValueError:
        print('你这输入的啥玩意')
        continue

    round = []
    for _ in range(count // 10):
        round.append(10)
    if count % 10:
        round.append(count % 10)

    for draws in round:
        fiveStar_num = 0
        fourStar_num = 0
        res_list = [[], [], []] # 第一个放金,第二个放紫,第三个放蓝
        flag_up = False
        for _ in range(draws):
            rate_update(already_times)
            if (already_times==89 and already_rare==8 ) or already_rare >= 9:
                # 连续9 发没出紫,必出紫
                character_rank = '紫'
            else:
                character_rank = random.choice(rate_list)

            already_times += 1
        
            if character_rank == '蓝':
                role = random.choice(threeStar)
                res_list[2].append(f"{Fore.BLUE}{role}{Style.RESET_ALL}")

                already_rare += 1

            elif character_rank == '紫':
                fourStar_role = random.choice(fourStar)

                if fourStar_isGuarantees: # 四星角色小保底:如果上一个出的不是up四星,下一次必出
                    role = random.choice(fourStar_up)
                    fourStar_isGuarantees = False
                else:
                    fourStar_isGuarantees = random.choice([True, False])
                    if fourStar_isGuarantees:
                        role = random.choice(fourStar)
                    else:
                        role = random.choice(fourStar_up)

                get_rare_roles.append(role)
                res_list[1].append(f"{Fore.MAGENTA}{role}{Style.RESET_ALL}")

                fourStar_num += 1
                already_rare = 0

            elif character_rank == '金':
                rate_initialization()
                if guarantees():
                    role = up
                    flag_up = True
                else:
                    role = random.choice(fiveStar)
                get_rare_roles.insert(0, role)

                res_list[0].append(f"{Fore.YELLOW}{role}{Style.RESET_ALL}")

                fiveStar_num += 1
                already_rare += 1
                already_times = 0 # 垫卡次数清零

        record_times(already_times)
        record_rare(already_rare)

        print("\n%d连抽出货情况:" % draws)
        print('==================================================')

        if fiveStar_num > 1:
            print("恭喜!%d连%d金!" %(draws, fiveStar_num))
        elif fiveStar_num == 1:
            if flag_up:
                print("出货啦~")
            else:
                print("金色传...可惜歪了")
        elif fourStar_num > 0:
            print("%d紫" % fourStar_num)

        print(f' '.join(list(map(lambda x: f' '.join(x), res_list))))

        print('==================================================')
        print(" ")

UP角色

up.txt

就写一个限定角色就行,如:纳西妲

五星常驻

fiveStar.txt

刻晴 莫娜 七七 迪卢克 琴 迪希雅 提纳里

四星角色物品

fourStar.txt

香菱 行秋 班尼特 菲谢尔 鹿野院平藏 罗莎莉亚 芭芭拉 砂糖 凝光 柯莱 雷泽 重云 诺艾尔 云堇 五郎 九条裟罗 久岐忍 烟绯 辛焱 迪奥娜 早柚 北斗 托马 宗室大剑 祭礼大剑 西风大剑 黑岩斩刀 钟剑 白影剑 千岩古剑 西风剑 祭礼剑 笛剑 暗巷闪光 祭礼弓 破魔之弓 西风猎弓 绝弦 昭心 万国诸海图 西风秘典 流浪乐章 祭礼残章 千岩长枪 西风长枪

四星UP角色,一般是3个

夏洛蒂 北斗 柯莱

三星武器

threeStar.txt

就写了个蓝色,有兴趣的可以自己写一下

(记得在卡池里放东西,也就是上门这些txt文件)

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,我可以帮你实现一个简单原神抽卡程序。假设你需要实现常驻池和角色池两种类型的抽卡,你可以按照以下步骤来完成: 1. 定义卡池 首先你需要定义两个类来表示常驻池和角色池。每个卡池应该有自己的名称、抽卡概率以及对应的角色/物品列表等属性。 ``` class Pool: def __init__(self, name, prob_list, item_list): self.name = name self.prob_list = prob_list # 抽卡概率列表,与item_list一一对应 self.item_list = item_list # 抽卡物品列表 class PermanentPool(Pool): def __init__(self): name = '常驻池' prob_list = [0.6, 0.34, 0.06] # 三星、四星、五星概率 item_list = ['三星角色A', '四星角色A', '五星角色A', ...] # 池中所有角色/物品列表 super().__init__(name, prob_list, item_list) class CharacterPool(Pool): def __init__(self): name = '角色池' prob_list = [0.006, 0.051, 0.093, 0.5, 0.35] # 五星角色、四星角色、四星武器、三星武器、三星角色概率 item_list = ['五星角色A', '五星角色B', '四星角色A', '四星角色B', ...] # 池中所有角色/物品列表 super().__init__(name, prob_list, item_list) ``` 2. 实现抽卡逻辑 接下来你需要实现抽卡的逻辑。你可以定义一个 `draw` 函数来模拟一次抽卡操作,该函数应该接受一个卡池对象作为参数,并返回一个随机的角色/物品。 ``` import random def draw(pool): rand_num = random.random() # 生成一个0到1之间的随机数 prob_sum = 0 for i in range(len(pool.prob_list)): prob_sum += pool.prob_list[i] if rand_num < prob_sum: return pool.item_list[i] return pool.item_list[-1] # 如果未匹配到任何一个概率,则返回最后一个物品 ``` 3. 进行抽卡 现在你可以进行抽卡了。你可以定义一个 `Gacha` 类来表示一个玩家,该类应该有自己的名称和已有的物品列表等属性。 ``` class Gacha: def __init__(self, name): self.name = name self.items = [] def draw_once(self, pool): item = draw(pool) self.items.append(item) print(f'{self.name}抽到了{item}') def draw_ten_times(self, pool): for i in range(10): self.draw_once(pool) ``` 现在你可以创建一个玩家对象并开始抽卡了: ``` p_pool = PermanentPool() c_pool = CharacterPool() player1 = Gacha('玩家1') player1.draw_once(p_pool) # 抽一次常驻池 player1.draw_ten_times(c_pool) # 抽十次角色池 ``` 以上就是一个简单原神抽卡程序的实现。当然,如果你想让程序更加完善,你可以添加更多的功能,例如保底机制、十连保底等等。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值