如何实现Python Nim游戏中CPU合理取火柴的逻辑?
修复Nim游戏中CPU的不合理取火柴逻辑
原始代码
import random def print_move(current_player, row, stick_quantity): current_player = current_player print(f"{current_player} takes {stick_quantity} sticks from {row} row") sticks = [1, 3, 5, 7] def nims(): for count, stick in enumerate(sticks): print(count+1, stick * "|") print("Welcome to Nim!") name = input("Enter name: ") current_player = random.choice([name, "CPU"]) print('game is starting', (current_player), 'will be going first') while True: if current_player == name: row = int(input("Which row would you like to take sticks from? ")). stick_quantity = int(input("How many sticks would you like to take? ")). sticks[row - 1] -= stick_quantity print_move(current_player, row, stick_quantity) if current_player == name: current_player = "CPU" else: current_player = name elif current_player == "CPU": row = random.choice([1,2,3,4]) stick_quantity = random.choice([1,2,3,4,5,6,7]) sticks[row - 1] -= stick_quantity print_move(current_player, row, stick_quantity) if current_player == "CPU": current_player = name else: current_player = "CPU" nims()
存在的问题
当前CPU逻辑会随机选择行和取火柴数量,会出现两种不合理情况:
- 选中已经没有火柴的行取火柴
- 取的火柴数量超过该行剩余的火柴数
修复后的代码
import random def print_move(current_player, row, stick_quantity): print(f"{current_player} takes {stick_quantity} sticks from {row} row") sticks = [1, 3, 5, 7] def nims(): for count, stick in enumerate(sticks): print(count+1, stick * "|") print("Welcome to Nim!") name = input("Enter name: ") current_player = random.choice([name, "CPU"]) print('game is starting', current_player, 'will be going first') while True: # 检查游戏是否结束(所有行无火柴) if all(s == 0 for s in sticks): print(f"Game over! {current_player} loses!") break if current_player == name: # 玩家输入合法性检查,避免无效操作 while True: try: row = int(input("Which row would you like to take sticks from? ")) if row < 1 or row > len(sticks): print(f"Invalid row! Choose between 1 and {len(sticks)}.") continue if sticks[row - 1] == 0: print("This row has no sticks left! Pick another one.") continue stick_quantity = int(input("How many sticks would you like to take? ")) if stick_quantity < 1 or stick_quantity > sticks[row - 1]: print(f"Invalid quantity! Take between 1 and {sticks[row-1]} sticks.") continue break except ValueError: print("Please enter a valid number.") sticks[row - 1] -= stick_quantity print_move(current_player, row, stick_quantity) current_player = "CPU" elif current_player == "CPU": # CPU仅从有火柴的行中选择 available_rows = [i+1 for i, s in enumerate(sticks) if s > 0] row = random.choice(available_rows) # 根据该行剩余火柴数,随机取合理数量 max_possible = sticks[row - 1] stick_quantity = random.randint(1, max_possible) sticks[row - 1] -= stick_quantity print_move(current_player, row, stick_quantity) current_player = name nims()
关键修复说明
- CPU行选择优化:先过滤出所有剩余火柴数大于0的行,只从这些行中随机选择,彻底避免选空行
- CPU取量限制:根据选中行的剩余火柴数,用
random.randint(1, max_possible)生成合法取量,确保不会超过该行剩余数量 - 语法错误修复:移除了原始代码中
input()语句末尾多余的点(.) - 玩家输入校验:增加玩家输入的合法性检查,避免玩家输入无效行号或取量
- 游戏结束判定:当所有行火柴数为0时,结束游戏并判定当前回合的玩家失败(取最后一根火柴的玩家获胜)
内容的提问来源于stack exchange,提问作者Raphael Mahna
相关产品推荐
相关产品推荐

