ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用Python从零实现宝可梦冒险模拟器:面向对象实战与回合制战斗

用Python从零实现宝可梦冒险模拟器:面向对象实战与回合制战斗 之前一直在整理宝可梦相关的数据结构和战斗模拟逻辑发现网上大多是零散的单点示例要么只讲某个精灵的数值建模要么只贴一段简单的对战代码缺少一套能串起来的完整项目。这篇文章就以“宝可梦百变怪与喵喵的冒险”这个主题为背景从零搭建一个可运行的宝可梦冒险模拟器带精灵图鉴、特性模拟、回合制战斗、冒险地图和存档系统既能作为 Python 面向对象编程的练手项目也能作为新手理解游戏状态机设计的一个参考。阅读本文后你将掌握如何设计宝可梦、技能、训练家等核心类。如何模拟百变怪“变身”和喵喵“聚宝功”这类经典机制。如何用文件存储和恢复冒险进度。如何编排一个简单的回合制战斗流程。如何排查项目运行中的常见问题。无论你是 Python 初学者还是想找一个综合实战案例的开发者这篇文章都适合你。下面我们直接进入正题。1. 项目背景与核心概念1.1 这是一个什么项目“宝可梦百变怪与喵喵的冒险”是一个基于命令行运行的文本冒险模拟器。它不依赖复杂图形界面而是通过Python 程序模拟出一只百变怪和一只喵喵组成的冒险小队在虚拟的宝可梦世界中探索、对战、收集图鉴、推进地图。百变怪的特色是“变身”能力可以在战斗中复制对手的外形和招式喵喵的特色则是“聚宝功”等招式以及它在动画中特有的说话、爱金币的性格特点。在实际代码中我们不需要完整复刻宝可梦官方游戏的数值系统而是抽取其中最具代表性的机制用可控的代码实现出来。1.2 项目要解决什么问题在实际学习编程时很多人会陷入“语法都懂但不会做项目”的困境。这个项目把多个知识点组合在一起类的继承与多态。字典、列表等数据结构的管理。随机数在游戏逻辑中的应用。文件读写实现存档。循环与状态机控制游戏主流程。同时宝可梦的题材本身带有清晰的对象模型训练家拥有宝可梦宝可梦拥有属性和技能技能有伤害和效果值。用这种题材来学习面向对象设计比单纯写员工管理系统更有画面感也更方便扩展。1.3 为什么选择百变怪和喵喵百变怪和喵喵是宝可梦系列里非常有辨识度的两只宝可梦。从程序设计的角度看它们也非常有代表性百变怪的“变身”机制天然适合演示“动态修改对象状态”和“复制对象属性”的代码思路。喵喵的“聚宝功”机制天然适合演示“战斗外经济系统”和“随机收益”。两者都能让项目在基础对战之外多出一些有趣的策略分支而不是单纯比较攻击力数值。因此本项目并不是把宝可梦题材生搬硬套到代码上而是恰好利用这些特性来展示面向对象设计中“状态变化”和“策略选择”的实战写法。2. 环境准备与项目结构2.1 运行环境说明本项目使用 Python 3 编写代码中不依赖任何第三方库仅使用标准库中的random、json、os等模块因此安装 Python 后就可以直接运行。版本需要根据你的项目实际情况调整本文示例以常见环境为例重点演示配置思路。推荐使用的 Python 版本是 3.8 及以上建议使用虚拟环境隔离项目依赖。验证 Python 环境是否可用python --version如果输出类似于Python 3.10.12说明环境正常。如果提示找不到命令可以尝试python3 --version2.2 项目目录结构为了让代码结构清晰我们将项目拆成多个模块。项目根目录为pokemon_adventure结构如下pokemon_adventure/ ├── main.py # 程序入口主流程控制 ├── models/ │ ├── __init__.py │ ├── pokemon.py # 宝可梦基类与具体宝可梦 │ ├── skill.py # 技能类 │ ├── trainer.py # 训练家类 │ └── map.py # 冒险地图类 ├── data/ │ └── save_data.json # 存档文件运行时自动生成 └── README.md # 项目说明如果一时看不明白整个结构也不用担心接下来我们会逐个文件讲解。创建目录的命令如下mkdir -p pokemon_adventure/models mkdir -p pokemon_adventure/data2.3 初始化 Python 包models目录需要有__init__.py文件Python 才能把它识别为一个包。在models/__init__.py中写入# 文件路径pokemon_adventure/models/__init__.py from .pokemon import Pokemon, Ditto, Meowth from .skill import Skill from .trainer import Trainer from .map import AdventureMap __all__ [Pokemon, Ditto, Meowth, Skill, Trainer, AdventureMap]这样在main.py中就可以通过from models import Pokemon的方式导入代码看起来更整洁。3. 核心数据结构设计在设计项目之前我们需要先定义清楚几个核心对象。整个项目的运行逻辑其实就是这几个对象之间的相互调用和状态变化。3.1 技能类 Skill技能是战斗的基础。每个技能至少应该包含名称、属性、基础威力、命中率可能还有附加效果说明。# 文件路径pokemon_adventure/models/skill.py class Skill: 宝可梦技能类 def __init__(self, name: str, skill_type: str, power: int, accuracy: float 1.0): self.name name self.skill_type skill_type self.power power self.accuracy accuracy def __repr__(self): return fSkill {self.name} (power{self.power}, type{self.skill_type})这里参数说明name技能名称例如“撞击”“聚宝功”。skill_type技能类型例如“普通”“火”“水”本项目暂不实现属性克制但保留字段方便扩展。power基础威力数值越大伤害越高。accuracy命中率1.0 表示必定命中0.8 表示有 80% 概率命中。3.2 宝可梦基类 Pokemon宝可梦是战斗中的主体。我们定义一个Pokemon基类包含通用属性和通用方法并在子类中重写特殊逻辑。# 文件路径pokemon_adventure/models/pokemon.py import random from .skill import Skill class Pokemon: 宝可梦基类 def __init__(self, name: str, level: int, hp: int, attack: int, defense: int, speed: int): self.name name self.level level self.max_hp hp self.hp hp self.attack attack self.defense defense self.speed speed self.skills [] def add_skill(self, skill: Skill): 添加技能 if len(self.skills) 4: self.skills.append(skill) else: print(f{self.name} 已经掌握了4个技能无法学习 {skill.name}) def is_alive(self) - bool: 是否存活 return self.hp 0 def take_damage(self, damage: int): 承受伤害 self.hp max(0, self.hp - damage) def normal_attack(self, target: Pokemon) - int: 普通攻击返回实际造成的伤害值 伤害简化公式攻击力 * 技能威力 / 防御力 * 随机系数 if not self.skills: return 0 skill random.choice(self.skills) # 命中判定 if random.random() skill.accuracy: print(f{self.name} 使用了 {skill.name}但是没有命中) return 0 multiplier random.uniform(0.85, 1.0) damage int((self.attack * skill.power / max(target.defense, 1)) * multiplier) target.take_damage(damage) print(f{self.name} 使用 {skill.name}对 {target.name} 造成 {damage} 点伤害) return damage def __repr__(self): return fPokemon {self.name} Lv.{self.level} HP{self.hp}/{self.max_hp}这里的伤害公式做了简化目的是让项目容易理解和扩展。真正宝可梦游戏中的伤害计算要复杂得多但对我们这个教学项目来说重点在于展示“攻击方通过技能对防守方造成伤害”这一流程。3.3 百变怪 Ditto百变怪最著名的特性就是“变身”在战斗开始时复制对手的能力值和技能。在代码中我们可以在对战开始时把百变怪自身的攻击、防御、速度和技能覆盖为对手的数据。# 文件路径pokemon_adventure/models/pokemon.py继续追加 class Ditto(Pokemon): 百变怪可以变身为对手 def __init__(self, level: int 20): # 百变怪自身的基础数值较低定位是“模仿者” super().__init__( name百变怪, levellevel, hp40 level * 2, attack30 level, defense30 level, speed40 level ) self.transformed False def transform(self, target: Pokemon): 变身为目标宝可梦复制对方的基础数值和技能 if self.transformed: print(百变怪已经变身过了无法再次变身。) return self.attack target.attack self.defense target.defense self.speed target.speed self.skills [Skill(s.name, s.skill_type, s.power, s.accuracy) for s in target.skills] self.transformed True print(f百变怪变身为 {target.name})这里有一个值得注意的点我们复制技能时用Skill(...)新建了技能对象而不是直接用target.skills的引用。这样做的好处是百变怪变身后的技能列表是独立对象后续扩展“技能 PP 值”时不会互相污染。3.4 喵喵 Meowth喵喵在动画中有明显的“贪财”属性所以我们给它加入一个名为“聚宝功”的特殊技能并且增加一个能量点数机制每次使用聚宝功成功命中后有概率获得额外金币这些金币可以用于后续的地图商店模块。# 文件路径pokemon_adventure/models/pokemon.py继续追加 class Meowth(Pokemon): 喵喵拥有聚宝功可以在战斗中获得金币 def __init__(self, level: int 20): super().__init__( name喵喵, levellevel, hp35 level * 2, attack35 level, defense30 level, speed50 level ) self.coins 0 def pay_day(self, target: Pokemon) - int: 聚宝功造成伤害并随机获得金币 pay_skill Skill(聚宝功, 普通, 40, 1.0) temp_damage self.normal_attack_with_skill(target, pay_skill) if temp_damage 0: earn random.randint(10, 30) self.coins earn print(f喵喵通过聚宝功获得了 {earn} 金币当前金币{self.coins}) return temp_damage def normal_attack_with_skill(self, target: Pokemon, skill: Skill) - int: 使用指定技能攻击返回伤害值 if random.random() skill.accuracy: print(f{self.name} 使用了 {skill.name}但是没有命中) return 0 multiplier random.uniform(0.85, 1.0) damage int((self.attack * skill.power / max(target.defense, 1)) * multiplier) target.take_damage(damage) print(f{self.name} 使用 {skill.name}对 {target.name} 造成 {damage} 点伤害) return damage这里为了展示“喵喵的聚宝功”我们专门写了一个normal_attack_with_skill方法。其实更好的做法是把基类中的normal_attack改成支持传入指定技能但为了照顾初学者的阅读难度我们把两条路径分开。3.5 训练家 Trainer训练家是玩家的替身负责携带宝可梦、管理背包和决定行动。# 文件路径pokemon_adventure/models/trainer.py from .pokemon import Pokemon class Trainer: 训练家类 def __init__(self, name: str): self.name name self.pokemons [] self.bag {伤药: 3, 精灵球: 5} def add_pokemon(self, pokemon: Pokemon): 添加宝可梦到队伍 if len(self.pokemons) 6: self.pokemons.append(pokemon) print(f{pokemon.name} 加入了队伍) else: print(队伍已满无法添加更多宝可梦。) def get_first_available_pokemon(self): 获取第一只还可以战斗的宝可梦 for p in self.pokemons: if p.is_alive(): return p return None def heal_all(self): 恢复所有宝可梦的 HP for p in self.pokemons: p.hp p.max_hp print(所有宝可梦的体力已完全恢复)训练家这里的bag字典演示了物品系统的基本结构。后续可以在战斗中调用bag[伤药]来恢复宝可梦状态。3.6 冒险地图 AdventureMap地图模块负责记录玩家位置、可用区域和随机事件。# 文件路径pokemon_adventure/models/map.py import random class AdventureMap: 冒险地图类 def __init__(self): self.locations [ 真新镇, 常青森林, 月见山, 枯叶市, 金黄市, 彩虹市 ] self.current_index 0 def show_location(self): 打印当前位置 print(f当前位置{self.locations[self.current_index]}) def move_forward(self): 向前移动 if self.current_index len(self.locations) - 1: self.current_index 1 print(f你来到了 {self.locations[self.current_index]}。) else: print(已经是冒险地图的终点前方暂时没有新区域了。) def random_event(self): 随机事件返回事件类型 events [battle, battle, rest, empty] result random.choice(events) if result rest: print(你发现了一处营地稍作休息队伍状态小幅恢复。) elif result empty: print(这一路上风平浪静什么事也没有发生。) return result地图模块把战斗、休息、安全无事几种事件通过随机选择来触发这样做的好处是主程序逻辑更加清晰。4. 完整实战从零搭建冒险程序到这里核心类都已经定义完成。接下来我们把它们组合起来形成一个可以运行的完整冒险程序。如果你需要动手练习建议先在本地创建好目录结构再按顺序复制代码。4.1 编写主程序入口 main.py主程序负责各个模块的协作是项目的“大脑”。我们用循环控制冒险流程用输入控制玩家操作。# 文件路径pokemon_adventure/main.py import json import os from models import Ditto, Meowth, Trainer, AdventureMap from models.skill import Skill def init_player(): 初始化玩家与初始宝可梦 name input(请输入你的训练家名字) if not name.strip(): name 小智 trainer Trainer(name) # 创建百变怪 ditto Ditto(level20) ditto.add_skill(Skill(撞击, 普通, 40, 1.0)) ditto.add_skill(Skill(变硬, 普通, 0, 1.0)) # 创建喵喵 meowth Meowth(level20) meowth.add_skill(Skill(抓, 普通, 40, 1.0)) meowth.add_skill(Skill(叫声, 普通, 0, 1.0)) trainer.add_pokemon(ditto) trainer.add_pokemon(meowth) return trainer def create_wild_pokemon(level: int): 根据等级生成一只野生宝可梦作为对手 candidates [ (小拉达, 40, 30, 50), (波波, 40, 30, 55), (绿毛虫, 35, 25, 45), (尼多兰, 45, 35, 50) ] import random name, atk, dfc, spd random.choice(candidates) wild type(WildPokemon, (object,), {})() wild.name name wild.level level wild.max_hp wild.hp 30 level * 2 wild.attack atk wild.defense dfc wild.speed spd wild.skills [ Skill(撞击, 普通, 35, 0.95), Skill(电光一闪, 普通, 40, 1.0) ] return wild def battle_flow(player: Trainer, wild): 简化版战斗流程 print(f\n野生的 {wild.name} 出现了) player_pokemon player.get_first_available_pokemon() if player_pokemon is None: print(队伍中没有可战斗的宝可梦你选择了逃跑。) return False print(f你派出了 {player_pokemon.name}。) # 百变怪特殊处理开场变身 if isinstance(player_pokemon, Ditto) and not player_pokemon.transformed: player_pokemon.transform(wild) while player_pokemon.is_alive() and wild.hp 0: print(f\n{player_pokemon.name} HP{player_pokemon.hp}/{player_pokemon.max_hp}) print(f野生 {wild.name} HP{wild.hp}) action input(请选择行动1.攻击 2.逃跑 - ).strip() if action 2: print(你成功逃跑了) return False # 玩家回合 player_pokemon.normal_attack(wild) if wild.hp 0: print(f野生的 {wild.name} 倒下了) return True # 野生宝可梦回合 attack_skill wild.skills[0] # 为了简化直接用随机技能攻击逻辑 import random skill random.choice(wild.skills) damage int((wild.attack * skill.power / max(player_pokemon.defense, 1)) * random.uniform(0.85, 1.0)) player_pokemon.take_damage(damage) print(f野生的 {wild.name} 使用 {skill.name}对 {player_pokemon.name} 造成 {damage} 点伤害) if not player_pokemon.is_alive(): print(f{player_pokemon.name} 失去了战斗能力) return False return False def game_main(): 主游戏循环 print( 宝可梦百变怪与喵喵的冒险 ) print(欢迎来到宝可梦世界) trainer init_player() data_file data/save_data.json if os.path.exists(data_file): load_choice input(检测到存档文件是否读取存档(y/n) - ).strip().lower() if load_choice y: if load_game(trainer, data_file): print(存档读取成功) else: print(存档读取失败将开始新游戏。) adventure_map AdventureMap() adventure_map.show_location() running True while running: print(\n当前冒险区域, adventure_map.locations[adventure_map.current_index]) print(1. 继续前进) print(2. 查看队伍状态) print(3. 休息恢复) print(4. 保存并退出) cmd input(请输入指令).strip() if cmd 1: event adventure_map.random_event() if event battle: wild create_wild_pokemon(level15 adventure_map.current_index * 5) battle_flow(trainer, wild) adventure_map.move_forward() elif cmd 2: for p in trainer.pokemons: print(p) elif cmd 3: trainer.heal_all() elif cmd 4: save_game(trainer, adventure_map, data_file) print(游戏已保存期待你下次冒险) running False else: print(无效的指令请输入1-4之间的数字。) print(感谢游玩) def save_game(trainer: Trainer, adventure_map: AdventureMap, filepath: str): 保存游戏存档 save_data { trainer_name: trainer.name, pokemons: [ { name: p.name, level: p.level, hp: p.hp, max_hp: p.max_hp, attack: p.attack, defense: p.defense, speed: p.speed, coins: getattr(p, coins, 0) } for p in trainer.pokemons ], location_index: adventure_map.current_index } os.makedirs(os.path.dirname(filepath), exist_okTrue) with open(filepath, w, encodingutf-8) as f: json.dump(save_data, f, ensure_asciiFalse, indent2) def load_game(trainer: Trainer, filepath: str) - bool: 读取游戏存档 if not os.path.exists(filepath): return False try: with open(filepath, r, encodingutf-8) as f: data json.load(f) trainer.name data.get(trainer_name, trainer.name) # 简化处理重新构建宝可梦 trainer.pokemons.clear() for p in data.get(pokemons, []): name p[name] level p[level] if name 百变怪: new_p Ditto(level) else: new_p Meowth(level) new_p.hp p.get(hp, new_p.max_hp) new_p.max_hp p.get(max_hp, new_p.max_hp) if hasattr(new_p, coins): new_p.coins p.get(coins, 0) trainer.pokemons.append(new_p) return True except Exception as e: print(f读取存档失败{e}) return False if __name__ __main__: game_main()这份代码比较长但逻辑并不复杂。我们把它拆开看init_player创建训练家和两只初始宝可梦并配置技能。create_wild_pokemon动态生成一只野生宝可梦用type()动态创建一个简单对象避免再单独写一个类。battle_flow战斗循环先判断百变怪是否需要变身然后进入回合制战斗。game_main游戏主循环通过数字指令让玩家选择不同动作。save_game/load_game用 JSON 文件保存训练家、宝可梦和地图进度。4.2 运行与验证在项目根目录执行以下命令python main.py运行后会看到类似输出 宝可梦百变怪与喵喵的冒险 欢迎来到宝可梦世界 请输入你的训练家名字小刚 小拉达 加入了队伍 喵喵 加入了队伍 当前位置真新镇当选择“1. 继续前进”时可能触发战斗野生的 波波 出现了 你派出了 百变怪。 百变怪变身为 波波 百变怪 HP80/80 野生 波波 HP70/70 请选择行动1.攻击 2.逃跑 - 1 百变怪 使用 撞击对 波波 造成 23 点伤害 野生的 波波 使用 电光一闪对 百变怪 造成 15 点伤害如果选择“4. 保存并退出”会在data目录生成save_data.json下次启动时可以选择读取存档。4.3 运行结果说明从这个项目中你可以看到几个关键设计百变怪没有一开始就使用自己的技能战斗而是在战斗开始时立刻变身这吻合它在动画中的经典表现。喵喵虽然有聚宝功但在简化版战斗流程中还没有被单独调用。你可以在battle_flow里增加一个判断如果出战宝可梦是喵喵就把“攻击”选项改为“抓 / 聚宝功”两个选项。存档逻辑使用 JSON 格式便于人工查看和修改也方便后续扩展存档版本管理。5. 扩展功能让项目更完整上面是一个最小可运行版本但距离“完整冒险游戏”还有不小距离。我们可以在此基础上增加几个常见模块。5.1 技能 PP 值技能不能无限使用否则游戏缺少资源管理策略。可以给Skill类增加max_pp和current_pp字段每次使用技能时减少 PPPP 为 0 时只能使用普通攻击。class Skill: def __init__(self, name, skill_type, power, accuracy1.0, max_pp10): self.name name self.skill_type skill_type self.power power self.accuracy accuracy self.max_pp max_pp self.current_pp max_pp def use_skill(self): if self.current_pp 0: return False self.current_pp - 1 return True5.2 商店系统有了喵喵的聚宝功金币就有了用武之地。可以在冒险地图中加入“商店”事件玩家可以用金币购买伤药和精灵球。def shop_flow(trainer: Trainer): print(欢迎光临宝可梦商店) print(1. 伤药50金币恢复50HP) print(2. 精灵球100金币用于捕捉宝可梦) choice input(请输入购买编号或其他键离开) if choice 1: if trainer.bag.get(金币, 0) 50: trainer.bag[金币] - 50 trainer.bag[伤药] trainer.bag.get(伤药, 0) 1 print(购买成功) else: print(金币不足。)注意这里需要先在训练家类中增加金币字段或者在喵喵对象中维护金币再在商店结算时统一计算。5.3 宝可梦捕捉宝可梦游戏不能只有对战还需要有捕捉系统。在战斗胜利后玩家可以使用精灵球尝试捕捉野生宝可梦成功率可以根据宝可梦剩余 HP 和精灵球数量动态计算。def catch_pokemon(wild, trainer: Trainer) - bool: if trainer.bag.get(精灵球, 0) 0: print(没有精灵球了) return False trainer.bag[精灵球] - 1 success_rate max(0.1, 1.0 - wild.hp / wild.max_hp * 0.8) import random if random.random() success_rate: print(f恭喜成功捕捉 {wild.name}) trainer.add_pokemon(wild) return True else: print(很遗憾精灵球摇晃了一下野生宝可梦挣脱了) return False5.4 属性克制系统宝可梦的核心玩法之一是属性克制。我们可以增加一个简单的克制表在伤害计算时修改倍率。TYPE_CHART { (火, 草): 2.0, (草, 水): 2.0, (水, 火): 2.0, # 可以继续扩展 } def calc_type_multiplier(attack_type: str, target_type: str) - float: return TYPE_CHART.get((attack_type, target_type), 1.0)然后在normal_attack的伤害计算中把乘进去就可以。这属于扩展方向本文不再展开。6. 常见问题与排查思路在实际运行这个项目时初学者经常遇到几类问题。下面以表格形式列出方便快速排查。问题现象常见原因解决思路ModuleNotFoundError: No module named models当前执行目录不在项目根目录在pokemon_adventure目录下执行python main.pyJSONDecodeError或存档读取失败data/save_data.json内容损坏删除data/save_data.json文件后重新开始游戏输入数字后程序无反应输入了中文全角字符或多余空格确保输入1-4并回车不要带空格百变怪变身后 HP 变成对手的数值百变怪变身复制了hp字段在transform中不要覆盖hp只复制攻击、防御、速度和技能TypeError: NoneType object is not iterable队伍中没有可战斗的宝可梦检查get_first_available_pokemon返回是否为None提前处理逃跑逻辑喵喵的金币没有保存存档函数没有处理coins字段在save_game中加入coins序列化在load_game中读取下面单独说明几个容易踩坑的位置。6.1 目录结构导致导入失败如果你在models目录下直接运行某个文件比如python models/pokemon.py会出现相对导入失败的问题。原因很简单Python 执行脚本时会把当前脚本所在目录加入sys.path此时models包结构并不完整。解决方案始终在项目根目录pokemon_adventure下运行或者在main.py中手动添加项目根目录到sys.path。6.2 存档文件路径不一致开发时 Windows 的路径分隔符是\Linux 是/如果直接拼接字符串可能会出现找不到文件的问题。本文示例使用了os.path.dirname(filepath)来创建目录并且使用data/save_data.json这种相对路径能够一定程度规避差异。但如果你在 IDE 中运行工作目录可能与项目目录不一致。可以在main.py顶部添加import os import sys BASE_DIR os.path.dirname(os.path.abspath(__file__)) os.chdir(BASE_DIR)强制把工作目录切换到项目根目录。6.3 战斗后 HP 为负数在take_damage方法中我们使用了max(0, self.hp - damage)所以正常情况下 HP 不会变成负数。但如果在其他地方直接操作pokemon.hp - damage就可能出现负数影响后续显示和判断。建议所有伤害都通过take_damage方法统一处理。6.4 百变怪重复变身如果战斗循环中每次回合都调用transform百变怪会反复复制对手数值导致技能列表越来越庞杂。因此我们在transform方法中增加了self.transformed标志位来控制只变身一次。7. 最佳实践与工程建议这个项目虽然是一个教学示例但代码组织方式可以提炼出不少通用工程经验。如果你以后要开发更复杂的游戏项目或业务系统下面几个建议同样适用。7.1 用类封装状态变化游戏中的角色状态非常多直接操作字典容易造成字段拼写错误和状态不一致。用类来管理状态把状态的修改都收敛到方法内部可以减少出错概率。比如在Pokemon类中take_damage负责统一修改 HPis_alive负责判断存活状态。外部代码不需要关心hp字段的具体值只需要调用方法即可。7.2 数据与逻辑分离把宝可梦的数值、技能配置与战斗逻辑分开。如果后续要调整数值不需要修改代码只需要修改数据文件。这一点在大型项目中尤其重要。可以准备一个data/pokemon_data.json里面存放不同宝可梦的基础数值和技能再用一个工厂函数根据名字创建宝可梦对象def create_pokemon_by_name(name: str, level: int): config POKEMON_DATA[name] return Pokemon( namename, levellevel, hpconfig[hp], attackconfig[attack], defenseconfig[defense], speedconfig[speed] )7.3 存档要包含版本号存档文件写死字段名在项目迭代时会产生不兼容问题。建议在存档中增加version字段{ version: 1.0, trainer_name: 小刚, pokemons: [], location_index: 0 }读取时先检查版本再决定如何解析。这样后续增加新功能时可以安全地处理旧存档。7.4 战斗逻辑与 UI 逻辑分离本文中的print和input直接写在战斗逻辑中优点是简单直观缺点是不容易改成图形界面或网络版。更好的做法是让战斗逻辑返回结果由外部 UI 层负责展示。例如normal_attack方法只返回一个攻击结果字典result { success: True, skill_name: 撞击, damage: 23, target_name: 波波 }然后在主程序中统一格式化输出。7.5 健壮性处理在读取用户输入时尽可能处理异常情况输入非数字字符时会触发ValueError。输入空字符串时可能导致逻辑错误。存档文件损坏时可能导致程序崩溃。建议使用try-except包裹关键输入解析逻辑比如while True: try: cmd int(input(请输入指令).strip()) if cmd in range(1, 5): break print(请输入1到4之间的数字。) except ValueError: print(请输入合法数字。)8. 总结与后续学习方向本文从零搭建了一个名为“宝可梦百变怪与喵喵的冒险”的命令行冒险模拟器覆盖了类设计、战斗流程、随机事件、存档读档等核心功能。通过这个项目你可以看到如何把宝可梦题材中的经典设定转化为可运行的程序逻辑尤其是百变怪变身和喵喵聚宝功这两个特殊机制。如果你想把项目继续做下去可以尝试以下方向在战斗中增加属性克制、异常状态和技能 PP 值。为每个地图区域设计独立的野生宝可梦分布表。把 CLI 程序改造成 Web 应用使用 Flask 或 FastAPI 提供 API 接口。引入数据库存储玩家数据和精灵数据。增加多语言支持将输出文本统一管理。无论你选择哪个方向都建议先跑通现有代码理解每个模块的职责边界再逐步修改或替换。动手改代码的过程才是真正提升编程能力的过程。希望这篇文章能给你带来启发也欢迎你在实际开发中扩展出更有趣的玩法。
返回列表