角色扮演、RPG、回合制游戏、文字版、无界面。
说明文档内容附在文末
要组成一个大整体,首先要有各种实体,这在大学里面叫什么分析来着,
ER图
?反正就是那么个东西,工欲善其事必先利其器,先分析就对了,只有结构清晰了,才能下笔如有神。
每个实体写成一个类,这叫 封装 ,面向对象的过程中是一个非常好的习惯。后续添加属性或者方法都很容易定位。
E-R图
代码实现
从ER图可以看到冒险者拥有几种属性:名字name,最大血量maxHP,当前血量hp,是否存活alive,是否眩晕stunned,是否处于格挡状态blocking。
同时,冒险者可以equip装备:武器,盾牌,护甲。
同时,冒险者还具有物品栏。
将这些属性写在init里,需要用户初始化的东西通过传参的形式传递用户需求。无须用户设计的就直接写在代码里面即可,就不用通过传参的方式了,防止过于冗余。
class Adventurer: # 名字name,最大血量maxHP,当前血量hp,生存状态alive,格挡blocking,控制stunned, def __init__(self, name, weapon, shield, armour, inventory, maxHP=100): self.name = name self.maxHP = maxHP self.hp = maxHP self.alive = 'true' self.stunned = 'false' self.blocking = 'false' # 初始化装备 self.weapon = weapon # 初始化武器设置 self.shield = shield self.armour = armour # 初始化物品栏 self.inventory = inventory # showHero:输出冒险者的面板 def showHero(self): print('名字:', self.name) self.showStatus() self.showEquipment() self.showInventory() def isAlive(self): if self.hp <= 0: self.alive = 'false' return "false" else: self.alive = 'true' return "true" def showStatus(self): print('状态:') print('最大生命值:', self.maxHP, '\t当前血量:', self.hp, '\talive:', self.alive) print('stunned:', self.stunned, '\tblocking:', self.blocking) def showEquipment(self): print('装备:') print(f"weapon:\tname={self.weapon.name};\tdamage={self.weapon.damage};\t\tweight={self.weapon.weight};") print( f"shield:\tname={self.shield.name};\tarmourRating={self.shield.armourRating};\tweight={self.shield.weight};\tpercentage={self.shield.percentage}") print(f"armour:\tname={self.armour.name};\tarmourRating={self.armour.armourRating};\tweight={self.armour.weight}") def showInventory(self): print('物品栏:') num = len(self.inventory.items) if num == 0: print("空的。") else: for i in range(num): item = self.inventory.items[i] print(f"item{i + 1}:\t{item.name}") def getWeight(self): return self.weapon.weight+self.armour.weight+self.shield.weight
根据后面的需求,我们应该能够展示冒险者的信息,所以构造一个showhero()方法,本来我是写在一起的,但是,后面也有分开展示的需求,如果每次都全部展示就太过于冗余啦,所以我把每个showhero分成三个部分:show状态,show装备,show物品栏。分别通过三个方法实现。
isAlive判断存货状态和getweight计算身上装备的重量。这些都是后来功能需要又添加的,这就体现出来把bean分离出单个文档的好处了,
(2) 背包Inventory
代码实现
原需求的背包是要一个6格的数组放置,但我不喜欢,这样不利于我以后的扩充,且在代码上不美观,感觉不够高级,所以我选择了可变数组作为背包属性。没有设置类或者结构体,直接用两个属性来表示,一个表示空位,一个表示元素。
背包理应具有两个方法:放进去物品,丢掉物品,展示背包栏。
放物品要考虑放满的情况,说明书要求置换,但我觉得先丢后放会更简单,更适合我这种结构。逻辑清晰,看代码就行了。class Inventory: def __init__(self): self.empty = 6 self.items = [] def getItem(self, item): if self.empty == 0: print("背包放满了,不能再放了,你需要从以下物品中输入序号(-1表示不替换)替换一件物品:") self.showBag() while 1: i = int(input("想要扔掉物品的序号(-1返回上一级表示你不换了):")) if i == "-1": # 上一级 break else: ack = input("你确认要换这件物品?(Y or N)") if ack == "Y": self.dropItem(i-1) else: print("已取消更换,请重新选择") continue self.items.append(item) self.empty -= 1 def dropItem(self, i): self.items.pop(i - 1) self.empty += 1 def showBag(self): for i in range(len(self.items)): item = self.items[i] print(f"item{i + 1}:{item.name}")
(3) 物品Item
代码实现
物品分为两种,药水和装备,一开始对python中的类不熟悉,考虑分开去做,但是最后都是要放在物品栏里面,所以没有好的想法,还是需要是一个类别,所以敲定必须是类,就直接搜了类继承相关的知识,通过继承实现,确实好用。class Item: def __init__(self, name): self.name = name
① 药水potion
代码实现
继承物品类item,根据需求,一个名字就够了,通过名字判断功用。class Potions(Item): # 创建药水类 def __init__(self, name): self.name = name
② 装备equipments
武器E-R图
盾牌E-R图
护甲E-R图
继承物品类Item,根据需求,武器有三个属性,盾牌四个属性,护甲三个属性,设置就完事了。
class Equipments(Item): # 创建武器类 class Weapon: def __init__(self, name, damage, weight): self.name = name self.damage = damage self.weight = weight # 创建盾牌类 class Shield: def __init__(self, name, armourRating, percentage, weight): self.name = name self.armourRating = armourRating self.percentage = percentage self.weight = weight # 创建盔甲类 class Armour: def __init__(self, name, armourRating, weight): self.name = name self.armourRating = armourRating self.weight = weight
附加文档也提供了一些装备的属性作为参考:
2.2 活动方法
(1) 初始化参数 init
① 初始化物品列表 getItemList()
从附加文档的参考装备中挑选一部分作为系统物品库,放入ItemList列表中存待用。
def getItemsList(): w1 = Equipments.Weapon('Redsword', 15, 1) s1 = Equipments.Shield('Redshield', 10, 1.5, 0.1) a1 = Equipments.Armour('Redarmour', 10, 2) w2 = Equipments.Weapon('Orangesword', 15, 1) s2 = Equipments.Shield('Orangeshield', 15, 2, 0.15) a2 = Equipments.Armour('Orangearmour', 15, 2.5) w3 = Equipments.Weapon('Yellowsword', 20, 1.5) s3 = Equipments.Shield('Yellowshield', 20, 2.5, 0.2) a3 = Equipments.Armour('Yellowarmour', 10, 2) w4 = Equipments.Weapon('Greensword', 40, 2.5) s4 = Equipments.Shield('Greenshield', 30, 3, 0.25) a4 = Equipments.Armour('Greenarmour', 30, 3.5) w5 = Equipments.Weapon('Cyansword', 50, 3) s5 = Equipments.Shield('Cyanshield', 40, 3.5, 0.3) a5 = Equipments.Armour('Cyanarmour', 40, 4) w6 = Equipments.Weapon('Bluesword', 60, 3.5) s6 = Equipments.Shield('Blueshield', 50, 4, 0.35) a6 = Equipments.Armour('Bluearmour', 50, 4.5) potion1 = Potions("healthPotion") potion2 = Potions("damagePotion") itemsList = [w1, w2, w3, w4, w5, w6, s1, s2, s3, s4, s5, s6, a1, a2, a3, a4, a5, a6, potion1, potion2] return itemsList
② 初始化勇士 Initadventurer()
带着名字就能创建一个勇士,勇士初始装备设置为新手套装,hp你看着改
def initAdventurer(name): w1 = Equipments.Weapon('新手刀', 10, 1) s1 = Equipments.Shield('新手盾', 2, 0.3, 1) a1 = Equipments.Armour('新手甲', 3, 1) potion1 = Potions("healthPotion") potion2 = Potions("damagePotion") myInventory = Inventory() myInventory.getItem(potion1) myInventory.getItem(potion2) adventurer = Adventurer(name, w1, s1, a1, myInventory, 100) return adventurer
(2) 战斗过程 battle
① 前三波初始化弱敌 initEnemy()
def initEnemy(enemyNum): # 后续可以考虑随机怪兽的装备和初始血量 enemyName = f"怪物{enemyNum}号" w1 = Equipments.Weapon('新手刀', 10, 1) s1 = Equipments.Shield('新手盾', 2, 0.3, 1) a1 = Equipments.Armour('新手甲', 3, 1) enemy = Adventurer(enemyName, w1, s1, a1, Inventory(), 50) return enemy
② 随机加强敌人 RandomEnemy()
随机化的,取个随机数从物品库里面随机取就行,和后面奖励机制一样
def randomEnemy(enemyNum): enemyName = f"怪物{enemyNum}号" wNum = random.randint(0, 5) sNum = random.randint(6, 11) aNum = random.randint(12, 17) randomHP = random.randint(40+6*enemyNum, 80+6*enemyNum) # 这里用enemyNum系数加成 enemy = Adventurer(enemyName, itemsList[wNum], itemsList[sNum], itemsList[aNum], Inventory(), randomHP) return enemy
③ 判断先手 回合战斗
if adv.getWeight() <= enemy.getWeight(): # 谁轻谁先手,一样你先手 while adv.isAlive() == "true" and enemy.isAlive() == "true": # 都活着就继续干 enemySub, advAdd, advSub, enemyAdd = 0, 0, 0, 0 enemySub, advAdd = actions.action(adv, enemy) # 冒险者打怪兽 if enemySub == -99 and advAdd == -99: return advSub, enemyAdd = actions.enemyAction(enemy, adv) # 怪兽打冒险者 settleRound(adv, enemy, enemySub, advAdd, advSub, enemyAdd) # 结算这一回合 else: while adv.isAlive() == "true" and enemy.isAlive() == "true": # 都活着就继续干 enemySub, advAdd, advSub, enemyAdd = 0, 0, 0, 0 advSub, enemyAdd = actions.enemyAction(enemy, adv) # 怪兽打冒险者 enemySub, advAdd = actions.action(adv, enemy) # 冒险者打怪兽 if enemySub == -99 and advAdd == -99: return settleRound(adv, enemy, enemySub, advAdd, advSub, enemyAdd) # 结算这一回合 if enemy.alive == 'false': print("===========================牛批,恭喜你战胜了怪兽===================================================") win = 1
a) 勇士行为action
def action(adv, enemy): eSub, aAdd = 0, 0 if adv.stunned == 'true': print("你被对面用盾牌格挡眩晕了,将跳过这回合") adv.stunned = 'false' return eSub, aAdd print("你有如下选择:") print("1.攻击attack") print("2.格挡block") print("3.使用物品use an item") print("4.逃跑run away") while 1: choice = input("请输入你的选择:") # switch在python3.10的版本之前只能通过字典实现,此处不努力了。 if choice == "1": eSub = attack(adv, enemy) elif choice == "2": aAdd = defend(adv, enemy) elif choice == "3": usePotion(adv, enemy) elif choice == "4": runAway() return -99, -99 else: print("输入指令无效,请重新输入:") continue break return eSub, aAdd
攻击attack
def attack(attacker=initAdventurer("无衣"), victim=randomEnemy(0)): attacker.blocking = 'false' eSub = attacker.weapon.damage - victim.armour.armourRating return eSub
格挡defend
def defend(attacker=initAdventurer("无衣"), victim=randomEnemy(0)): attacker.blocking = "true" # 设置为格挡,直到冒险者选择攻击或者使用物品或者冒险者受到伤害。 aAdd = attacker.shield.armourRating # 设置一个自由值(random number)在0到1之间,如果这个值等于盾牌眩晕对手的几率(percentage),设置对手的被控制状态(stunned)为true,对手必须跳过这一回合。 safePer = random.random() # 产生随机浮点数,小于等于概率就是晕了 if safePer <= attacker.shield.percentage: print("============格挡成功并眩晕了=========") victim.stunned = "true" else: print("==============格挡失败,不眩晕===========") victim.stunned = "false" return aAdd
用药usePotion
def usePotion(adv=initAdventurer("无衣"), enemy=randomEnemy(0)): adv.blocking = 'false' adv.showInventory() while 1: dex = input("请输入序号选择你要使用的物品(没有药的话用-1后退),战斗状态只能用药品,希望你不要不识好歹:") if dex == "-1": # 没有药就让他重新选择干嘛,不然就死循环了 action(adv, enemy) break else: dex = int(dex) item = adv.inventory.items[dex - 1] if "Potion" in item.name: # 如果是药品,就用 adv.inventory.items.pop(dex - 1) # 把物品从背包取出来 if item.name == "healthPotion": adv.hp += 200 if adv.hp > adv.maxHP: adv.hp = adv.maxHP if item.name == "damagePotion": enemy.hp -= 50 if enemy.hp <= 0: enemy.alive = "false" break else: print("重新选!只能使用药品")
逃跑runAway
def runAway(): print("不要气馁,再试试能不能抽到较弱的怪兽,实在不行就自杀吧。")
b) 怪物行为enemyAction
怪物不能用药和逃跑,所以只有攻击和格挡
def enemyAction(enemy, adv): aSub, eAdd = 0, 0 if enemy.stunned == 'true': print("怪兽被你用盾牌格挡眩晕了,将跳过这回合") enemy.stunned = 'false' return aSub, eAdd ran = random.randint(1, 2) if ran == 1: print("=======怪兽选择进攻======") aSub = attack(enemy, adv) if ran == 2: print("=======怪兽选择格挡=====") eAdd = defend(enemy, adv) return aSub, eAdd
④ 结算回合
a) 结算勇士
# 结算勇士 if enemy.blocking == 'false': # 怪兽不格挡,才会攻击,才需要统计血量 if adv.blocking == 'true': if advSub > advAdd: # 格挡且对面攻击护甲之后掉的血比盾牌挡的多 adv.hp = adv.hp - advSub + advAdd elif advSub != 0: adv.hp -= 1 else: if advSub > 0: adv.hp = adv.hp - advSub elif advSub != 0: # 对面攻击没我护甲高,掉1 且怪兽不是格挡 adv.hp -= 1 else: # 怪兽格挡,不用管勇士血量了
b) 结算怪物
# 结算怪物 if adv.blocking == 'false': # 勇士不格挡,才会攻击,才更新怪兽血量 if enemy.blocking == 'true' : if enemySub > enemyAdd: # 对面攻击护甲之后掉的血比盾牌挡的多 enemy.hp = enemy.hp - enemySub + enemyAdd elif enemySub != 0: # 对面攻击护甲之后掉的血比盾牌挡的少 enemy.hp -= 1 else: if enemySub > 0: enemy.hp = enemy.hp - enemySub elif enemySub != 0: # 我攻击没对面护甲高,掉1 enemy.hp -= 1 else: # 我格挡了,怪兽无所谓
c) 展示状态并更新
# 刷新状态 adv.showStatus() enemy.showStatus() adv.blocking = 'false' enemy.blocking = 'false' if adv.hp <= 0: adv.alive = 'false' if enemy.hp <= 0: enemy.alive = 'false'
(3) 清扫战场与装备管理 InventorManagement
def inventoryManagement(adv, itemsList): global enemyNum print("===========================即将迎接下一个怪兽,请做好准备===================================================") empty0 = adv.inventory.empty while 1: print("你有如下选择:") print("1.挑选胜利奖品pick up items") print("2.丢弃物品栏物品drop held items") print("3.装备物品栏物品equip held items") print("4.继续战斗fight next enemy") choice = input("请输入你的胜利选择(-1表示退出):") # switch在python3.10的版本之前只能通过字典实现,此处不努力了。 if choice == "1": if win == 1: if empty0 - adv.inventory.empty < 3: actions.pickUpItem(adv, itemsList) else: print("你已经挑选了三个奖品了,请不要利用漏洞多选哦~") else: print("\n----------------你击败了怪兽吗就想领奖励?逃跑可是没有战利品的------------------\n") elif choice == "2": actions.dropItem(adv) elif choice == "3": actions.equipItem(adv) elif choice == "4": enemyNum += 1 battle(adv) elif choice == '-1': break else: print("输入指令无效,请重新输入:") continue
① 挑选战利品 pickUpItem()
def pickUpItem(adv, itemsList): wNum = random.randint(0, 5) sNum = random.randint(6, 11) aNum = random.randint(12, 17) potionNum = random.randint(18, 19) winList = [itemsList[wNum], itemsList[sNum], itemsList[aNum], itemsList[potionNum]] # print(winList) for i in range(len(winList)): item = winList[i] print(f"item{i + 1}:{item.name}") for i in range(1, 4): dex = input("请输入序号选择你要的物品(-1返回上一级表示你不要物品,将直接开始战斗):") # =======================有个bug,如果这里选1个2个出去了,其实就可以无限刷装备。============= # 已修复:在pickUp的入口处加了个判断 if dex == "-1": # 上一级 break elif len(re.findall("\d", dex)) == 0: # 如果不是数字 print("输入指令无效,请重新输入:") continue else: ack = input("你确认要这件物品?(Y or N):") if ack == "Y": dex = int(dex) item = winList[dex - 1] adv.inventory.getItem(item) # 把物品从背包取出来 # adv.inventory.showBag() else: print("已取消捡起,请重新选择") continue
② 丢弃物品 DropItem()
def dropItem(adv=initAdventurer(" ")): adv.showInventory() while 1: dex = input("请输入序号选择你要丢弃的物品(-1返回上一级):") if dex == "-1": # 上一级 break else: ack = input("你确认要丢这件物品?(Y or N)") if ack == "Y": dex = int(dex) adv.inventory.items.pop(dex - 1) # 把物品从背包取出来 else: print("已取消丢弃,请重新选择") continue
③ 装备物品 equipItem()
def equipItem(adv): adv.showInventory() while 1: dex = input("请输入序号选择你要装备的物品(没有装备的话用-1后退),不能用药品,希望你不要不识好歹:") if dex == "-1": # 退出换装,不然就死循环了 print("退出换装") break else: dex = int(dex) item = adv.inventory.items[dex - 1] if "Potion" in item.name: # 如果是药品 print("重新选!只能使用装备") elif "sword" in item.name: # 如果是武器 # adv.inventory.items.pop(dex - 1) # 把物品从背包取出来 adv.inventory.dropItem(dex-1) # 把物品从背包取出来 adv.inventory.getItem(adv.weapon) # 把装备放进背包 adv.weapon = item # 把取出的装备换上 adv.showInventory() continue elif "shield" in item.name: # 如果是盾 # adv.inventory.items.pop(dex - 1) # 把物品从背包取出来 adv.inventory.dropItem(dex-1) # 把物品从背包取出来 adv.inventory.getItem(adv.weapon) # 把装备放进背包 adv.shield = item # 把取出的装备换上 adv.showInventory() continue elif "armour" in item.name: # 如果是护甲 # adv.inventory.items.pop(dex - 1) # 把物品从背包取出来 adv.inventory.dropItem(dex-1) # 把物品从背包取出来 adv.inventory.getItem(adv.weapon) # 把装备放进背包 adv.armour = item # 把取出的装备换上 adv.showInventory() continue else: print("这是bug,可能是我给装备改名字了")
④ 继续战斗 battle()
elif choice == "4": enemyNum += 1 battle(adv)
战斗结束条件
while adventurer.alive == "true":
3 主程序中main函数流程:
if __name__ == '__main__': # test() # 初始化一些参数 enemyNum = 0 itemsList = getItemsList() # 创建勇士 name = input("欢迎来到冒险岛,请为勇士创建一个名字:") adventurer = initAdventurer(name) adventurer.showHero() print() print("欢迎来到新世界,努力打倒敌人变得更强吧,勇士,请踏上你的征程!") print("*****************************************************************") print() while adventurer.alive == "true": enemyNum += 1 battle(adventurer) inventoryManagement(adventurer, itemsList)
https://github.com/jz51/adventurer
武器: 攻击力 重量
Redsword 15 1
Orangesword 20 1.5
Yellowsword 30 2
Greensword 40 2.5
Cyansword 50 3
Bluesword 60 3.5
Purplesword 70 4
Lightsword 80 4.5
Darksword 90 5
Excalibur 100 1盾牌: 防御值 重量 眩晕值
Redshield 10 1.5 0.1
Orangeshield 15 2 0.15
Yellowshield 20 2.5 0.2
Greenshield 30 3 0.25
Cyanshield 40 3.5 0.3
Blueshield 50 4 0.35
Purpleshield 60 4.5 0.4
Lightshield 70 5 0.45
Darkshield 80 5.5 0.5
Mirrorshield 90 6 0.6盔甲: 防御值 重量
欢迎来到神秘岛:trade_mark:文字冒险游戏! 在异国情调的场景中移动并通过键入您的动作与它们进行交互:始终是动词,后接名词。 例如:“往北”,“往南”或“爬山”。 祝您探索顺利! 小心点 我的Python学习过程的一部分。 我想先和你谈谈一个项目一般是怎么完成的。更具体的说,程序员是如何思考和解决问题的呢?我认为其中一个很重要的能力是【问题拆解】。问题拆解,指的是在做一件事或面对一个问题的时候,将其拆解成多个步骤或多个层次,逐步执行和解决问题,直至达到最终效果。我会将完成一个项目的流程总结为以下三步:明确项目目标,是指我们希望程序达成什么目的,实现什么功能,从而帮我们将项目拆解成不同的单元;而一个妥当的拆解方案,难度适度递增,能帮我们逐步顺利执行,最终完成项目。这三个步骤可以说是环环相扣的。 python文字冒险游戏狼人之夜源代码,拥有6大结局和22大成就。道具对你来说,必不可少,而通关的旅途,更是出人意料!你,究竟能不能,在这月圆之夜,生存下去,拯救村庄?在这里,你是一个杰出的屠狼师,令狼人们闻风丧胆!月圆之夜,你是选择踏上征程,抑或是待在家里? 目录序言背景思路代码及解析跋文 最近都工作比较忙,还在备考【系统集成项目管理工程师】,所以一直没时间更新了,今天先分享分享之前开发过的文字游戏,前一段时间也一直想更新这款游戏,增加剧情啊,以及玩法啊等等,也是一直没时间,等考试结束了,准备着手开始开发。 一直以来还蛮喜欢玩文字游戏的,但是手机上的游戏要不就需要氪金,要不就是得刷刷刷,太累了。当时正好在学习Python,一不做二不休,干脆就自己开发一个咯。然后经过一段时间的设计,开发,测试,并有了现在这个【文字修仙】。 目前版本的界面如下: AIDungeon2Read more about AIDungeon2 and how it was built here.Play the mobile app version of the game by following the links herePlay the game online by following this link herePlay the game in Colab... 该书三四五六章分别介绍用户输入、条件语句、函数、列表,直接跳到第七章:循环,因为例程包含了前几章的技术:func 玩 {库存 = ['匕首','金币(5)','面包棍']println("逃出生天!")loop {输入 = 获取命令()if ['n', 'N'].__contains__(输入) {println("往北!")} elif ['s', 'S'].__contains__(输入) {...
Redarmour 10 2
Orangearmour 15 2.5
Yellowarmour 20 3
Greenarmour 30 3.5
Cyanarmour 40 4
Bluearmour 50 4.5
Purplearmour 60 5
Lightarmour 70 5.5
Darkarmour 80 6
Goldenarmour 100 8