上一篇文章主要记录了学习python类与对象时的应用,但是最终运行起来太麻烦了而且还有很多功能没有能够成功搭建,因此这篇文章主要记录一下自己对旧代码的完善。
目标:
这次把精灵的基础属性直接定义到精灵主体当中,要不每次都得通过函数给精灵属性,同时函数生成的属性没有办法直接地调用到战斗功能当中去。
遇到的问题:我设计的精灵主体部分包含"火土属性"功能,但是生命攻击等值又受"火土属性"的影响,解决这部分浪费了时间
首先在定义处加上了combat_attribute
def __init__(self,name=None,skill=None,attribute=None,combat_attribute=None)
**添加功能:**当赋予精灵火属性后给定一些基础数值,通过修改add_attribute函数,通过检测不同的输入,从而调用不同的函数,进一步得到不同的属性:
def add_attribute(self): self.attribute = input('请在火、水、土中选择生成属性:')if self.attribute == '火':selfbat_attribute = self.fire_combat_attribute()elif self.attribute == '水':selfbat_attribute = self.water_combat_attribute()elif self.attribute == '土':selfbat_attribute = self.land_combat_attribute()def fire_combat_attribute(self):Value_life = self.Value_life - random.randint(10,30)Value_attack = self.Value_attack + random.randint(5, 10)Value_defense = self.Value_defense - random.randint(2, 3)Value_speed = self.Value_speed + random.randint(2, 4)return {'value_life': Value_life, 'value_attack': Value_attack, 'value_defense': Value_defense, 'value_speed': Value_speed}
==在这部分判定技能方面浪费了时间:==因为要判定技能影响了什么属性以及技能数值,对比好长时间发现还是re字符串是最方便的如下:
text = random.choice(list(Spirit1.skill.values()))
match = re.search(r'(增加|加|增|提升|生|恢复|提高)(D+)?(d+).*(..)$', text)up(4) == '攻击':up(4) == '防御':up(4) == '生命':pass
首先取得精灵技能中一个随机技能的说明,然后通过re将自己需要的值提取到group中,然后再进行调用,在这里能力有限,只能保证技能描述最后是’攻击’、‘防御’、'生命’才可以,否则没办法进行下一步,之能限定输入了。接下来就是将他们放入到对战代码中:
ef Spirit_vs(Spirit1,Spirit2): #这里输入的两个就是精灵主体#{'value_life': Value_life, 'value_attack': Value_attack, 'value_defense': Value_defense, 'value_speed': Value_speed}count = 0 #回合数turn = 0 #life_1 = Spirit1bat_attribute['value_life']attack_1 = Spirit1bat_attribute['value_attack']defense_1 = Spirit1bat_attribute['value_defense']speed_1 = Spirit1bat_attribute['value_speed']life_2 = Spirit2bat_attribute['value_life']attack_2 = Spirit2bat_attribute['value_attack']defense_2 = Spirit2bat_attribute['value_defense']speed_2 = Spirit2bat_attribute['value_speed']while life_1 > 0 and life_2 > 0 : #第一个元素为生命,当生命<=0时便会退出循环count += 1 #查看回合数if speed_1 > speed_2 : #速度判断谁先出手 这里是1先出手text = random.choice(list(Spirit1.skill.values()))pattern = re.search(r'(..)$')if pattern == "伤害" :number_damage_1 = int(re.search(r'd+', text).group())else :match = re.search(r'(增加|加|增|提升|生|恢复|提高)(D+)?(d+).*(..)$', text)up(4) == '攻击':attack_1 += up(3)up(4) == '防御':defense_1 += up(3)up(4) == '生命':life_1 += up(3)life_2 -= attack_1 - defense_2 + number_damage_1if life_2 <= 0 :breaktext = random.choice(list(Spirit2.skill.values()))pattern = re.search(r'(..)$')if pattern == "伤害":number_damage_2 = int(re.search(r'd+', text).group())else:match = re.search(r'(增加|加|增|提升|生|恢复|提高)(D+)?(d+).*(..)$', text)up(4) == '攻击':attack_2 += up(3)up(4) == '防御':defense_2 += up(3)up(4) == '生命':life_2 += up(3)life_1 -= attack_2 - defense_1 + number_damage_2
在这里考虑到只需要输入精灵就可以战斗因此只做了两个类作为输入,但不方便的是不能直接调用Spirit1bat_attribute[‘value_life’]这些属性,因为如果战斗中这些数值发生了变化,会影响战斗完之后精灵的属性,因此在一开始进行了一个赋值过程,将值给到life_1等变量,上面的代码是在精灵1先出手的代码。2的代码几乎一样全是重复的,也没想到好方法进行优化因此先这样用着。第一次写的有很多错误完整能运行的在末尾
精灵定义与对战功能调试没问题了,接下来就是设计输入与输出,这部分想的是把已经编辑过的精灵名字和技能储存在文件当中,每次运行程序的时候都能看一下,同时可以直接选择编辑过的精灵,然后只要赋予他们一个属性就可以战斗了,首先是要创建一个这个文件在这里我将新建的精灵名字和技能全部储存在txt中,并且可以分行保存,同时给他们加上一个序号让我们可以再选择精灵时可以直接选择:
def create_spirit(): #创建新精灵函数if not ists(''): #检测储存文件是否存在with open('','w') as f:passwith open('','r',encoding='utf-8') as file_row:row_content = adlines()row = len(row_content) #读取已经存在多少行文本with open('', 'a', encoding='utf-8') as f:target = Spirit()target.add_name()target.add_skill()f.write('{}.'.format(row))f.write(json.dumps(target.name, ensure_ascii=False)) # 设置ensure_ascii属性否则默认输出编码格式的字符f.write(',')f.write(json.dumps(target.skill, ensure_ascii=False))f.write(';')f.write('r') # windows中txt文本默认换行是r 也可以使用os.linesep来进行换行
之后在创建一个读取的功能,能够通过读取txt返回一个精灵:
def choose_spirit(a): #通过读取序号返回对应的精灵类with open('','r',encoding='utf-8') as f:content = f.read().split(';')for i in content:if a in i[:2]:print(i)data_1 = i.split(',')name_1 = data_1[0].strip('"')#移除多余的字符data_2 = name_1.split('.')#将前面的序号去掉name_2 = data_2[1].strip('"')skill = eval(data_1[1].strip()) #这部分只适用于储存一个技能技能在2或以上咋办?spirit = Spirit(name_2,skill)return spirit
在这部分出了个大问题: 我在调试的时候只是用Spirit创建的精灵,他们只有一个技能,因此一开始没发现问题,当我用VIP_Spirit进行创建的时候精灵有两个技能,就没有办法利用上述代码进行拆分了,因此想了一下能不能创建类似json文件的格式,这样容易创建和读取。
解决方法1: 在网上找了找发现直接利用列表合并然后利用eval创建为字典就可以了。
i = '0."小鱼人",{"跳跃": "造成50点伤害", "汲水": "恢复自身100点生命"}'
data_1 = i.split(',')
data_2 = ','.join(data_1[1:])
print(type(data_2))
my_dict = eval(data_2)
print(type(my_dict))
这部分我就做的有点蠢了,全是一步一步的因为没想到怎样嵌套函数进行优化,这里就不放了因为没有意义,将他们与其他代码直接放到最后了。
在程序运行没有错误之后输出实在是太单调了,不符合我这种回合制玩家的心理,想着得加一个日志,起码让我知道战斗实在进行的,因此又去修改日志函数,只要简单地在战斗过程中将这些输入加进去就可以解决了:
print(f"{Spirit1.name} used {skill1_random}:{text} ")
print(f"{Spirit2.name} used {skill2_random}:{text} ")
print(f"回合 {count}:")print(f"{Spirit1.name}: life={life_1}, attack={attack_1}, defense={defense_1}, speed={speed_1}")print(f"{Spirit2.name}: life={life_2}, attack={attack_2}, defense={defense_2}, speed={speed_2}")
同时发现了一个重大错误: 从日志输出以后才会发现当精灵1的攻击小于精灵2的防御力时攻击就会给精灵2回血,这部分没有设计好是一个失误,但是如果做平衡又要改很多东西,毕竟我是为了练习语法才写这个的因此主体运行没有错误就能接受。
整体代码
import random
import re
import os
import json
class Spirit(object): #父类__doc__ = "Spirit创建"__name__= "类的名字"__author__ = "silverbullet"skill_special = {'淬火':'增加自身50点攻击','汲水':'恢复自身100点生命','炼体':'增加自身2点防御'}Value_life = 500Value_attack = 20Value_defense = 5Value_speed = 10def __init__(self,name=None,skill=None,attribute=None,combat_attribute=None): #可以在创建 Spirit 对象时不提供这些参数的值,而是使用默认值self.name = nameself.skill = dict(skill) if skill else {}self.attribute = attributeselfbat_attribute = combat_attribute #{'value_life':None,'value_attack':None,'value_defense':None,'value_speed':None}def check(self):print(' spirit name is {} n spirit skill is {} n spirit attribute is {}'.format(self.name,self.skill,self.attribute))def add_name(self):self.name = input('请输入精灵名称:')def add_skill(self):skill_name = input('请输入技能名称:')skill_effect = input('请输入技能效果(设置技能效果时请以"伤害"、"生命"、"攻击"、"防御"这些词做最后两个字符n''同时如果技能增加某种属性请以这种形式表示:"提升精灵30点攻击"):')skill_storage = {skill_name: skill_effect}self.skill.update(skill_storage)def add_attribute(self): #实现在类中可以根据输入值改变内部其他值self.attribute = input('请在火、水、土中选择生成属性:')if self.attribute == '火':selfbat_attribute = self.fire_combat_attribute()elif self.attribute == '水':selfbat_attribute = self.water_combat_attribute()elif self.attribute == '土':selfbat_attribute = self.land_combat_attribute()def fire_combat_attribute(self):Value_life = self.Value_life - random.randint(10,30)Value_attack = self.Value_attack + random.randint(5, 10)Value_defense = self.Value_defense - random.randint(2, 3)Value_speed = self.Value_speed + random.randint(2, 4)return {'value_life': Value_life, 'value_attack': Value_attack, 'value_defense': Value_defense, 'value_speed': Value_speed}def water_combat_attribute(self):Value_life = self.Value_lifeValue_attack = self.Value_attackValue_defense = self.Value_defenseValue_speed = self.Value_speedreturn {'value_life': Value_life, 'value_attack': Value_attack, 'value_defense': Value_defense, 'value_speed': Value_speed}def land_combat_attribute(self):Value_life = self.Value_life + random.randint(10, 30)Value_attack = self.Value_attack - random.randint(5, 10)Value_defense = self.Value_defense + random.randint(2, 3)Value_speed = self.Value_speed - random.randint(2, 4)return {'value_life': Value_life, 'value_attack': Value_attack, 'value_defense': Value_defense,'value_speed': Value_speed}@classmethoddef getspecial_skill(cls): #选择一个随机的特殊技能skill_add = random.choice(list(cls.skill_special.items()))skill_add_key,skill_add_value = skill_addskill_dict = {skill_add_key:skill_add_value}return skill_dictclass VIP_Spirit(Spirit): #VIP创建def __init__(self,name=None,skill=None,attribute=None):super().__init__(name,skill,attribute)def add_name(self):super().add_name()def add_skill(self):super().add_skill()self.skill.special_skill())#实现添加父类中定义的特殊技能def add_attribute(self):super().add_attribute()class VIP_non_Spirit(Spirit): #非VIP创建def __init__(self,name=None,skill=None,attribute=None):super().__init__(name,skill,attribute)def add_name(self):super().add_name()def add_skill(self):super().add_skill()def add_attribute(self):super().add_attribute()def Spirit_vs(Spirit1,Spirit2): #这里输入的两个就是精灵主体#{'value_life': Value_life, 'value_attack': Value_attack, 'value_defense': Value_defense, 'value_speed': Value_speed}count = 0 #回合数turn = 0 #life_1 = Spirit1bat_attribute['value_life']attack_1 = Spirit1bat_attribute['value_attack']defense_1 = Spirit1bat_attribute['value_defense']speed_1 = Spirit1bat_attribute['value_speed']life_2 = Spirit2bat_attribute['value_life']attack_2 = Spirit2bat_attribute['value_attack']defense_2 = Spirit2bat_attribute['value_defense']speed_2 = Spirit2bat_attribute['value_speed']while life_1 > 0 and life_2 > 0 : #第一个元素为生命,当生命<=0时便会退出循环count += 1 #查看回合数number_damage_1 = 0number_damage_2 = 0#清除上一回合技能伤害if speed_1 >= speed_2 : #速度判断谁先出手 这里是1先出手 速度相同的情况下1也先出手skill1_random = random.choice(list(Spirit1.skill.keys()))text = Spirit1.skill[skill1_random]print(f"{Spirit1.name} used {skill1_random}:{text} ")pattern = re.search(r'(..)$',text)up() == '伤害':number_damage_1 = int(re.search(r'd+', text).group())else :match = re.search(r'(增加|加|增|提升|生|恢复|提高)(D+)?(d+).*(..)$', text)up(4) == '攻击':attack_1 += up(3))up(4) == '防御':defense_1 += up(3))up(4) == '生命':life_1 += up(3))life_2 -= attack_1 - defense_2 + number_damage_1if life_2 <= 0 :breakskill2_random = random.choice(list(Spirit2.skill.keys()))text = Spirit2.skill[skill2_random]print(f"{Spirit2.name} used {skill2_random}:{text} ")pattern = re.search(r'(..)$',text)up() == '伤害':number_damage_2 = int(re.search(r'd+', text).group())else:match = re.search(r'(增加|加|增|提升|生|恢复|提高)(D+)?(d+).*(..)$', text)up(4) == '攻击':attack_2 += up(3))up(4) == '防御':defense_2 += up(3))up(4) == '生命':life_2 += up(3))life_1 -= attack_2 - defense_1 + number_damage_2else: #2先出手skill2_random = random.choice(list(Spirit2.skill.keys()))text = Spirit2.skill[skill2_random]print(f"{Spirit2.name} used {skill2_random}:{text} ")pattern = re.search(r'(..)$',text)up() == "伤害":number_damage_2 = int(re.search(r'd+', text).group())else:match = re.search(r'(增加|加|增|提升|生|恢复|提高)(D+)?(d+).*(..)$', text)up(4) == '攻击':attack_2 += up(3))up(4) == '防御':defense_2 += up(3))up(4) == '生命':life_2 += up(3))life_1 -= attack_2 - defense_1 + number_damage_2if life_1 <= 0:breakskill1_random = random.choice(list(Spirit1.skill.keys()))text = Spirit1.skill[skill1_random]print(f"{Spirit1.name} used {skill1_random}:{text} ")pattern = re.search(r'(..)$',text)up() == "伤害":number_damage_1 = int(re.search(r'd+', text).group())else:match = re.search(r'(增加|加|增|提升|生|恢复|提高)(D+)?(d+).*(..)$', text)up(4) == '攻击':attack_1 += up(3))up(4) == '防御':defense_1 += up(3))up(4) == '生命':life_1 += up(3))life_2 -= attack_1 - defense_2 + number_damage_1print(f"回合 {count}:")print(f"{Spirit1.name}: life={life_1}, attack={attack_1}, defense={defense_1}, speed={speed_1}")print(f"{Spirit2.name}: life={life_2}, attack={attack_2}, defense={defense_2}, speed={speed_2}")if life_1 > 0 :print("{}获胜!".format(Spirit1.name))else:print("{}获胜!".format(Spirit2.name))return countdef create_spirit(): #创建新精灵函数if not ists(''): #检测储存文件是否存在with open('','w') as f:passwith open('','r',encoding='utf-8') as file_row:row_content = adlines()row = len(row_content) #读取已经存在多少行文本with open('', 'a', encoding='utf-8') as f:target = VIP_Spirit()target.add_name()target.add_skill()f.write('{}.'.format(row))f.write(json.dumps(target.name, ensure_ascii=False)) # 设置ensure_ascii属性否则默认输出编码格式的字符f.write(',')f.write(json.dumps(target.skill, ensure_ascii=False))f.write(';')f.write('r') # windows中txt文本默认换行是r 也可以使用os.linesep来进行换行
def choose_spirit(a): #通过读取序号返回对应的精灵类with open('','r',encoding='utf-8') as f:content = f.read().split(';')for i in content:if a in i[:2]:print(i)data_1 = i.split(',')name_1 = data_1[0].strip('"')#移除多余的字符data_2 = name_1.split('.')#将前面的序号去掉name_2 = data_2[1].strip('"')data_1_1 = ','.join(data_1[1:])skill = eval(data_1_1)spirit = Spirit(name_2,skill)return spirit
def read_spirit():if not ists(''): #检测储存文件是否存在with open('','w') as f:passprint("查看已保存精灵:")with open('', 'r', encoding='utf-8') as f:content = f.read()print(content)def choose_vs(): #选择精灵进行游戏serial_number_1 = input("请选择要对战的精灵1的序号:")target_1 = choose_spirit(serial_number_1)target_1.add_attribute()serial_number_2 = input("请选择要对战的精灵2的序号:")target_2 = choose_spirit(serial_number_2)target_2.add_attribute()Spirit_vs(target_1, target_2)
def menu(): #编辑头文字部分print("ttttt1.查看精灵已储存精灵信息")print("ttttt2.选择精灵进行游戏")print("ttttt3.添加新精灵")print("ttttt4.退出游戏")if __name__ == '__main__':button_1 = 1button_2 = 1while button_1 :menu()choice = int(input('请选择'))if choice in [1, 2, 3, 4]:if choice == 1:read_spirit()choice = int(input('1.返回主界面 2.开始精灵对战n请选择下一步:'))if choice == 1:continueelif choice == 2:read_spirit()choose_vs()choice = int(input("1.返回主界面 2.退出游戏n请选择下一步"))if choice == 1:continueelif choice == 2:button_1 = 0continueelif choice == 2:read_spirit()choose_vs()choice = int(input("1.返回主界面 2.退出游戏n请选择下一步"))if choice == 1:continueelif choice == 2:button_1 = 0continueelif choice == 3:button_2 = 1while button_2: #内循环加一个判定create_spirit()read_spirit()choice = int(input('1.开始精灵对战 2.返回主界面 3.退出游戏 4.继续添加n请选择下一步'))if choice == 1:read_spirit()choose_vs()choice = int(input("1.返回主界面 2.退出游戏n请选择下一步"))if choice == 1:breakelif choice == 2:button_1 = 0breakelif choice == 2:breakelif choice == 3:button_1 = 0breakelif choice == 4:continueelif choice == 4:button_1 = 0continue
注意事项: 1.每次选择完精灵之后要会提示设置属性请在“火”、“土”、“水”中选择,因为代码中只有赋予属性才会给定相应的基础属性。
2.技能方面:设置技能效果时请以“生命”、“攻击”、“防御”、“伤害”进行结尾,在这里我用的是re搜寻,并且只设计了接受增加这些伤害,不会出现减少的情况。
3.没有设置清除txt文本的功能,如果是第一次使用请先新建精灵。
可修改部分: 1.修改基础属性在"10-13"行代码
2.修改赋予’火’属性后所带来的不同属性在‘39-56’,或直接搜索fire_combat_attribute,对应的函数在这里。
3.修改战斗中防御过高带来的回血bug在’85’或搜索Spirit_vs(Spirit1,Spirit2),对应的函数在这里。
4.修改创建精灵是否为VIP在’185’行或搜索target = VIP_Spirit(),默认为vip创建可以多一个技能。
本文发布于:2024-02-03 04:24:48,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170690548648634.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |