如何用Python找到阴阳师妖怪屋的最佳探索队伍!强不强?

168 阅读10分钟

程序由来

最初想要写这个小程序是因为,9月份那段时间我在玩妖怪屋。

因为刚开始抽卡,要啥啥没有,所以探索队伍也只是放了几个自己记得有关联的式神。

在网上有找到完整版的羁绊,但是怎么根据羁绊找到最佳的式神组合就成问题了。

当时我是通过手动算出来的结果,后来想到自己刚刚把python基础啃完,也许可以试试用python来实现。
万一后续改进的不错能放上简历呢?

于是就有了这个程序。

整体思路

  1. 获取使用者的式神录
  2. 找到可以组成的羁绊
  3. 组合上述的羁绊
  4. 根据条件(8人,buff最大)找到最优解

当时的想法:

一是羁绊是游戏中设定好的。可以通过先对各个羁绊的属性进行定义,然后确认是否有羁绊中的式神存在于使用者式神录中。

二是把各个羁绊组合的人数和增强buff算出来,然后排除不符合要求的情况。

编写过程

先按照思路把整个程序写出来,然后不断的把一些内容改成函数,把一些输出不规范会导致的错误一一解决,接着阅读整个程序的代码,并对注释进行改写。

今天比较仓促,详细的过程不知道后续有没有机会补上,请让我先放上完整代码。

写程序的过程中,我还在论坛里找了很多方法用在程序里,以保证程序是按照我的思路实现的。

包括通过集合去重,确认A是否属于B,通过combinations对羁绊进行组合,以及通过re替换非中文字等等。

在此谢谢各位大佬的奉献。

完整代码

onmyoji(主程序)

"""
本项目是基于阴阳师妖怪屋的探索玩法编写的。
目的是让使用者能够快速根据拥有的式神,组合出能让增强buff最大化的8人组合。
探索玩法可派遣8位式神进行不断探索。
不同式神可组成不同羁绊,羁绊在游戏中是固定的,式神组成羁绊可获得增强buff,即额外探索奖励。

本项目使用方法,只需规范输入内容,并进行分隔,在完成输入后以N或n结尾即可。
该项目结果只会出现第一个增强buff最大的组合,请知悉。

本项目计算过程:
1.获取使用者的式神录,进行处理后获得单个式神的集合,保存至使用者变量type中。
2.根据这些式神从式神字典中找到可以组成的羁绊,保存其在字典中位置至使用者变量loc中。
3.将不同羁绊可组成的组合(后续称为羁绊组合),占用人数,增强buff放在一个字典中,保存至使用者变量total中。
4.对total中每个可组成羁绊组合,进行对比,占用人数合规(8位),且增强等级最大的组合保存至best中,并输出。
"""

import function as fu
import dictionary as dic
import shiki as sk

#将我拥有的式神设为一个空的集合,方便后续添加式神
shiki_you = sk.Shiki(set(()))

#建立一个集合包括所有羁绊组合的式神
"""
白狼,茨木童子,大天狗,独眼小僧,鬼使白,鬼使黑,蝴蝶精,九命猫,酒吞童子,傀儡师,
镰鼬,孟婆,犬神,山兔,少羽大天狗,桃花妖,天邪鬼赤,天邪鬼黄,天邪鬼绿,天邪鬼青,铁鼠,
巫蛊师,雪女,阎魔,妖刀姬,樱花妖,萤草
"""
shiki_all = dic.shiki_all

#通过使用者录入,获取使用者的式神录
while True:
    #获取使用者输入的式神
    #输入中如果有汉字或N,n以外的字符,都replace为,号,并进行分隔。当输入为N或n时,结束输入。
    shiki = input('Would you like to tell me your shiki name? please use \',\' to split.')
    #对输入内容进行处理,判断input的内容是不是为N或n,即对方有否完成输入过程。N为完成输入。
    if fu.check_go_on(shiki):
        break
    #对输入内容进行处理,保证输入内容合规后,更新至使用者的式神录
    fu.input_shiki(shiki, shiki_you)

#通过计算获得可组成的最大增强buff的羁绊组合
#可以更改组队人数设定限制,即将fu.get_max_buff(shiki_you)的默认参数n进行改动
fu.get_max_buff(shiki_you)

shiki

from itertools import combinations

class Shiki():
    #type是指拥有的式神,loc是指羁绊在diction2的位置,包括0,
    #comb是指各羁绊能组合成的组合,使用loc来表示羁绊所处位置
    #total是集合了羁绊组合,组合占用人数和增强buff的字典
    def __init__(self,type):
        self.type = type
        self.loc = []
        self.total = {}
        self.best_max = 0
        self.best = {}

    #获取所有羁绊可以组成的组合,请注意当i=1时,羁绊可组成的组合只有一个
    #而元组中只包含一个元素时,需要在元素后面添加逗号,否则括号会被当作运算符使用
    def combine(self):
        '''根据n获得列表中的所有可能组合(n个元素为一组)'''
        temp_list2 = []
        end_list = []
        for i in range(len(self.loc)):
            for c in combinations(self.loc,i):
                temp_list2.append(c)
                #print(i,c,len(c))
        temp_list2.append(tuple(self.loc))
        #temp_list2 = sorted(list(set(temp_list2)))
        return temp_list2

dictionary

(不得不承认这个diction。。真的有点丑)

#diction是一个列表,把每一个羁绊的各属性都单独放在一个字典中
import shiki as sk

#将所有羁绊组合的属性放入一个字典中,并将所有羁绊组合的字典放入一个列表中
"""
羁绊组合字典属性说明
    namet:羁绊简称
    tram_per:羁绊所包含的式神
    person:羁绊占用人数
    level:羁绊获得的buff值
    name:羁绊名称
"""
#diction是一个列表,把各属性key和各羁绊的对应属性值value放在一个字典中,其中value属性值也是一个列表
diction = [
    {'namet':['tram1','tram2','tram3','tram4','tram5','tram6','tram7''tram8',
                      'tram9','tram10','tram11','tram12','tram13','tram14','tram15','tram16']},
    {'tram_per':[{'樱花妖','桃花妖'},{'酒吞童子','茨木童子'},{'山兔','孟婆'},{'鬼使黑','鬼使白'},
                       {'镰鼬','铁鼠'},{'少羽大天狗','大天狗'},{'鬼使黑','鬼使白','阎魔'},{'白狼','妖刀姬','萤草'},
                       {'白狼','妖刀姬'},{'傀儡师','阎魔'},{'独眼小僧','蝴蝶精'},
                       {'天邪鬼黄','天邪鬼赤','天邪鬼青','天邪鬼绿'},{'大天狗','雪女'},{'萤草','白狼'},{'九命猫','犬神'},
                       {'蝴蝶精','巫蛊师'}]},
    {'person':[2,2,2,2,2,2,3,3,2,2,2,4,2,2,2,2]},
    {'level':[2,4,2,2,2,4,3,4,3,3,2,2,3,2,2,2]},
    {'name':['whereisspring','drinkthewine','runningfrogandpan','whiteandblack','repeathappily','fromthesky',
             'bosspleasesay','girlshouldbestrong','girlgroup','onedaytravelatthree','Icanchant','F4','FORjustice',
             'myidol','catordog','monstercatchingbutterfly']}
            ]

shiki_all = sk.Shiki({'白狼','茨木童子','大天狗','独眼小僧','鬼使白','鬼使黑','蝴蝶精','九命猫','酒吞童子','傀儡师',
             '镰鼬','孟婆','犬神','山兔','少羽大天狗','桃花妖','天邪鬼赤','天邪鬼黄','天邪鬼绿','天邪鬼青',
             '铁鼠','巫蛊师','雪女','阎魔','妖刀姬','樱花妖','萤草'})

function

import dictionary as dic
import re

#判断input的内容是不是为N或n,即对方不愿意继续分享其拥有的式神名称
def check_go_on(shiki):
    Out = False
    if shiki == 'N' or shiki == 'n':
        Out = True
    return Out

#对输入内容进行处理,确认其符合要求
def check_list(shiki):
    #将输入内容中所有非中文部分都替换为','
    mark = re.compile(r'[^\u4e00-\u9fa5]')
    a = re.sub(mark, ',', shiki)
    #根据分隔符',',对输入内容进行分隔去重
    shiki = list(set(a.split(',')))
    #对输入内容的每一个文字内容进行判定,确认其是否为式神录中的式神名称。
    for a in shiki.copy():
        #如是,继续判断下一个;
        if {a}.issubset(dic.shiki_all.type):
            continue
        #如不是,删掉该部分。
        else:
            shiki.remove(a)
    #返回处理过的输入内容,当前内容应不包含任何不存在于式神录的文字及符号
    return shiki

#
def input_shiki(shiki,shiki_you):
    #将输入的式神列表改为集合,方便进行判定和去重
    shiki = {i for i in list(check_list(shiki))}
    #将输入的式神列表放入使用者的式神录中
    shiki_you.type.update(shiki)
    return

#获取使用者式神可组成的所有羁绊,并保存羁绊在字典中的位置至变量loc
def get_dic(shiki_you):
    #确认使用者式神录是否能够组成diction中的羁绊
    for i in dic.diction[1]['tram_per']:
        #如果使用者式神录存在可组成羁绊的式神,保存该羁绊在字典中的指针
        #因为该指针可便于获取该羁绊在diction其他字典中的对应值
        if i.issubset(shiki_you.type):
            shiki_you.loc.append(dic.diction[1]['tram_per'].index(i))
    return shiki_you

#记录羁绊组合的各项属性值
def comp_buff_assign(shiki_you,type_shiki,buff,memberc):
    shiki_you.total['pers'].append(len(type_shiki))
    shiki_you.total['team'].append(type_shiki)
    shiki_you.total['level'].append(buff)
    shiki_you.total['usecomb'].append(memberc)
    return

#对每个羁绊组合的占用人数,增强buff等相关信息都进行获取和录入
def comp_buff(shiki_you,n):
    #对于每一个羁绊组合都进行计算
    for i in shiki_you.total['comb']:
        buff = 0
        type_shiki = set(())
        memberc = []
        #当羁绊的组合方式为空,可对各项属性值进行初始定义
        if len(i) == 0:
            comp_buff_assign(shiki_you, type_shiki, buff, memberc)
            continue
        #每个羁绊组合进行x(拥有羁绊数量)次的重复,以计算每种羁绊组合的属性
        for x in range(len(i)):
            # y用于获取羁绊组合在diction中的所处位置
            y = int(i[x])
            # type_shiki用于获取羁绊组合要占用的人数,并自动去重
            # memberc是获取使用到的羁绊,buff为增强buff的数值
            type_shiki.update(dic.diction[1]['tram_per'][y])
            memberc.append(dic.diction[1]['tram_per'][y])
            buff += dic.diction[3]['level'][y]
        #记录羁绊组合占用人数不大于设定的羁绊组合
        if len(type_shiki) <= n:
            comp_buff_assign(shiki_you, type_shiki, buff, memberc)
    return shiki_you

#输出可组成的增强buff最大的羁绊组合信息
def print_best(shiki_you,best):
    print('\n根据您现有的式神,当前可获得最大增强buff的羁绊组合信息如下:')
    print('最大Buff值:', shiki_you.best_max)
    print('组合占用人数:', len(shiki_you.best))
    print('使用到的羁绊:', shiki_you.total['usecomb'][best])
    print('使用到的式神:',shiki_you.best)

    print('\nBases on your shikis, we can provide below group details which can make you get maximum benefit:')
    print('Buff Level:', shiki_you.best_max)
    print('Number of Shiki:', len(shiki_you.best))
    print('Combination Used:', shiki_you.total['usecomb'][best])
    print('Shiki Used:',shiki_you.best)

# 对每个羁绊组合的增强buff进行比较,获得buff最大值的羁绊组合,保存在使用者的变量best,best_max中
def compare_buff(shiki_you):
    best=0
    # 开始对每组的数据进行比较,先设定一个保存最大值的变量
    shiki_you.best_max = shiki_you.total['level'][0]
    # shiki_you.total = {羁绊组合'comb':shiki_you.comb,
    # 占用人数'pers':[],'team':[],增强等级'level':[],'usecomb':[]}
    for i in range(len(shiki_you.total['level'])):
        if shiki_you.best_max < shiki_you.total['level'][i]:
            shiki_you.best_max = shiki_you.total['level'][i]
            shiki_you.best = shiki_you.total['team'][i]
            best = i
    print_best(shiki_you,best)
    return shiki_you

#通过计算获得可组成的最大增强buff的羁绊组合
def get_max_buff(shiki_you,n=8):
    # 获取使用者式神可组成的所有羁绊,并保存羁绊在字典中的位置至变量loc
    get_dic(shiki_you)

    # 将可组成的所有羁绊进行自由组合,并定义部分初始变量并保存相关信息在total字典中。
    """
    comb保存自由组合成的羁绊组合(在字典中的位置)
    pers保存每种羁绊组合的占用人数
    team保存每种羁绊组合所使用到的式神
    level保存每种羁绊组合可获得的buff增强值
    usecomb保存每种羁绊组合所使用到的羁绊
    """
    shiki_you.total = {'comb': shiki_you.combine(), 'pers': [], 'team': [], 'level': [], 'usecomb': []}

    # 对每个羁绊组合的占用人数,增强buff等相关信息都进行获取和录入
    comp_buff(shiki_you,n)

    # 对每个羁绊组合的增强buff进行比较,获得buff最大值的羁绊组合,输出并保存在使用者的变量best,best_max中
    compare_buff(shiki_you)

这个程序真的是改了又改,虽然不够复杂,没有好看的界面,甚至包含废话。但是说不定下一个程序用途就更加广泛了呢!

如果各位有改进方法或者好的教程,请抛给我!谢谢!

PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取

python免费学习资料以及群交流解答点击即可加入