You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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()

关键修复说明

  1. CPU行选择优化:先过滤出所有剩余火柴数大于0的行,只从这些行中随机选择,彻底避免选空行
  2. CPU取量限制:根据选中行的剩余火柴数,用random.randint(1, max_possible)生成合法取量,确保不会超过该行剩余数量
  3. 语法错误修复:移除了原始代码中input()语句末尾多余的点(.)
  4. 玩家输入校验:增加玩家输入的合法性检查,避免玩家输入无效行号或取量
  5. 游戏结束判定:当所有行火柴数为0时,结束游戏并判定当前回合的玩家失败(取最后一根火柴的玩家获胜)

内容的提问来源于stack exchange,提问作者Raphael Mahna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 09:25:55