Python井字棋开发:函数内修改外部变量值的持久化问题
井字棋变量持久化及逻辑修正方案
问题根源
answers1未声明全局:你在player_turn函数内重新创建了局部的answers1,外部的全局answers1完全没被更新,导致判定逻辑一直用初始的[0,0,0,0,0]。count变量无法累计回合:每次调用player_turn时,count都会被重置为0再加1,永远等于1,只有answer1会被赋值,其他answer变量始终是初始值0。- 获胜判定逻辑错误:
or的优先级低于==,原代码的条件写法实际是判断(win1common) or (win2common) ... or (win8common ==3),只要有一个非0值就会触发"X win",逻辑完全错误。
修复后的代码
line1 = (" 1 | 2 | 3 ") line2 = ("----|----|----") line3 = (" 4 | 5 | 6 ") line4 = ("----|----|----") line5 = (" 7 | 8 | 9 ") lines = [line1, line2, line3, line4, line5] # 用列表存储玩家落子,比单个变量更简洁 player_moves = [] for word in lines: print(word) # 全局回合计数器,记录当前是第几次落子 turn_count = 0 def player_turn(): global line1, line3, line5, turn_count, player_moves turn_count += 1 player_input = int(input("请输入落子位置(1-9): ")) # 用字典映射位置到对应的行和数字,减少冗余代码 position_map = { 1: (line1, '1'), 2: (line1, '2'), 3: (line1, '3'), 4: (line3, '4'), 5: (line3, '5'), 6: (line3, '6'), 7: (line5, '7'), 8: (line5, '8'), 9: (line5, '9'), } target_line, target_num = position_map[player_input] # 根据位置更新对应的行 if target_line is line1: global line1 line1 = line1.replace(target_num, 'X') elif target_line is line3: global line3 line3 = line3.replace(target_num, 'X') elif target_line is line5: global line5 line5 = line5.replace(target_num, 'X') # 记录玩家的落子 if turn_count <= len(player_moves): player_moves[turn_count-1] = player_input else: player_moves.append(player_input) # 更新棋盘并打印 updated_lines = [line1, line2, line3, line4, line5] for word in updated_lines: print(word) def check_win(): win_combinations = [ [1,2,3], [4,5,6], [7,8,9], # 横向 [1,4,7], [2,5,8], [3,6,9], # 纵向 [1,5,9], [3,5,7] # 对角线 ] # 检查是否有任意一个获胜组合完全包含在玩家落子中 for combo in win_combinations: if set(combo).issubset(set(player_moves)): print("X win") return True # 如果没赢,且棋盘已满则平局,否则继续 if len(player_moves) == 9: print("平局") return True print("游戏继续") return False # 游戏主循环 for _ in range(9): player_turn() if check_win(): break print(f"当前玩家落子记录: {player_moves}")
关键修改说明
- 全局变量声明:把
player_moves和turn_count加入player_turn的global声明,确保函数内修改的是全局变量。 - 简化落子记录:用列表
player_moves代替单个answer变量,更简洁易维护,直接追加或修改元素即可。 - 修正回合计数:把
turn_count放在函数外部作为全局变量,每次调用player_turn时累加,正确记录回合数。 - 优化获胜判定:用
set(combo).issubset(set(player_moves))直接判断获胜组合是否完全包含在玩家落子中,逻辑清晰且正确。 - 减少代码冗余:用字典映射位置和对应的行,避免重复的if判断,提升代码可读性。
内容的提问来源于stack exchange,提问作者user19748230
相关产品推荐
相关产品推荐

