Python函数内修改activePlayerMon变量后值恢复问题求助
宝可梦游戏精灵切换功能修复方案
问题描述
开发简易宝可梦游戏时,精灵切换功能异常:调用switchOption()函数时,调试可见activePlayerMon已切换,但退出函数后变量恢复为初始值。
代码问题分析
核心问题是变量作用域声明错误:
activePlayerMon和activeComputerMon是fight()函数的局部变量,而非全局变量- 嵌套函数
switchOption()中使用global声明,会让Python去全局作用域寻找这两个变量,而非外层fight()函数的作用域。这导致修改的是新创建的全局变量(而非原本的局部变量),所以外层fight()中的变量值始终没有变化
快速修复方案
把switchOption()里的global替换为nonlocal,这样就能正确修改外层fight()函数作用域中的变量:
def fight(playerlist, computerlist): print('\n',playerlist[1].name,'\n',playerlist[2].name,'\n',playerlist[3].name,'\n') initFight = int(input('Choose your starting Pokemon\n')) playerlist[int(initFight)].fightPrompt(computerlist[1]) activePlayerMon = playerlist[initFight] activeComputerMon = computerlist[1] def switchOption(determine_user): # 替换global为nonlocal,指向外层fight函数的变量 nonlocal activePlayerMon, activeComputerMon if determine_user == 1: print('\n',playerlist[1].name,'\n',playerlist[2].name,'\n',playerlist[3].name,'\n') changeMon = int(input('Choose who you\'d like to switch to')) activePlayerMon = playerlist[changeMon] elif determine_user == 0: changeMon = randint(1,3) activeComputerMon = computerlist[changeMon] while playerlist[1].HP != 0 and playerlist[2].HP != 0 and playerlist[3].HP != 0 or computerlist[1].HP != 0 and computerlist[2].HP != 0 and computerlist[3].HP != 0: print('\n',activePlayerMon.name,'- \n',activePlayerMon.HP,'\ ',activePlayerMon.MHP,'\n',activeComputerMon.name,'- \n',activeComputerMon.HP,'\ ',activeComputerMon.MHP,'\n') fightOption = int(input('Would you like to-\n 1. Fight\n 2. Heal\n 3. Switch\n')) if fightOption == 1: << attacking function call >> elif fightOption == 2: << healing function call >> elif fightOption == 3: switchOption(1)
模块化优化建议(更健壮的方案)
如果想让代码更易维护,建议用类封装战斗状态,彻底避免依赖嵌套作用域:
import random class Pokemon: def __init__(self, name, hp, mhp): self.name = name self.HP = hp self.MHP = mhp def fightPrompt(self, opponent): print(f"{self.name} 准备对战 {opponent.name}!") class Battle: def __init__(self, player_pokemons, computer_pokemons): self.player_pokemons = player_pokemons self.computer_pokemons = computer_pokemons self.active_player = None self.active_computer = None def init_battle(self): print('\n' + '\n'.join(p.name for p in self.player_pokemons[1:4])) init_idx = int(input('Choose your starting Pokemon\n')) self.active_player = self.player_pokemons[init_idx] self.active_computer = self.computer_pokemons[1] self.active_player.fightPrompt(self.active_computer) def switch_pokemon(self, is_player): if is_player: print('\n' + '\n'.join(p.name for p in self.player_pokemons[1:4])) change_idx = int(input('Choose who you\'d like to switch to')) self.active_player = self.player_pokemons[change_idx] else: change_idx = random.randint(1,3) self.active_computer = self.computer_pokemons[change_idx] def run(self): self.init_battle() # 修正战斗结束条件:只要玩家有一只存活且电脑有一只存活就继续 while any(p.HP > 0 for p in self.player_pokemons[1:4]) and any(p.HP > 0 for p in self.computer_pokemons[1:4]): print(f'\n{self.active_player.name} - \n{self.active_player.HP} / {self.active_player.MHP}\n{self.active_computer.name} - \n{self.active_computer.HP} / {self.active_computer.MHP}\n') fight_option = int(input('Would you like to-\n 1. Fight\n 2. Heal\n 3. Switch\n')) if fight_option == 1: # 调用攻击函数 pass elif fight_option == 2: # 调用治疗函数 pass elif fight_option == 3: self.switch_pokemon(is_player=True) # 使用示例 player_list = [None, Pokemon('皮卡丘', 100, 100), Pokemon('妙蛙种子', 90, 90), Pokemon('杰尼龟', 85, 85)] computer_list = [None, Pokemon('小火龙', 95, 95), Pokemon('绿毛虫', 50, 50), Pokemon('波波', 60, 60)] battle = Battle(player_list, computer_list) battle.run()
这个方案把战斗状态、切换逻辑都封装在Battle类中,变量状态管理更清晰,后续扩展功能也更方便。
内容的提问来源于stack exchange,提问作者Polish Newscaster
相关产品推荐
相关产品推荐

