
本文详解如何在 python 实现的尼姆游戏中嵌套主循环,使玩家可在一局结束后选择是否重开一局,并统计用户胜/负场次。
本文详解如何在 python 实现的尼姆游戏中嵌套主循环,使玩家可在一局结束后选择是否重开一局,并统计用户胜/负场次。
要让尼姆游戏支持“重复游玩”,关键在于将整局游戏逻辑封装进一个外层循环中,并在每局结束时询问玩家意愿,同时维护用户胜负计数器。原代码中 while sum(sticks) > 0 仅控制单局流程,而我们需要的是跨局状态管理。
以下是重构后的完整实现要点(已整合原逻辑并增强可复用性):
✅ 正确结构:外层 while replay.lower() == 'y' 循环
将整个游戏初始化、对战流程和结果处理包裹在 replay 控制的循环内,确保变量(如 sticks、current_player)每局都重置:
import random
def print_move(current_player, row, stick_quantity):
if stick_quantity == 1:
print(f"{current_player} takes {stick_quantity} stick from row {row}")
else:
print(f"{current_player} takes {stick_quantity} sticks from row {row}")
# 初始化全局计分器
user_wins = 0
cpu_wins = 0
print("Welcome to Nim!")
name = input("Enter your name: ")
replay = 'y'
while replay.lower() == 'y':
# ? 每局重置游戏状态
sticks = [1, 3, 5, 7]
current_player = random.choice([name, "CPU"])
print(f"\nGame starts! {current_player} goes first.")
# 单局主循环
while sum(sticks) > 0:
# 显示当前棋盘
print("\nCurrent piles:")
for i, count in enumerate(sticks, 1):
print(f"Row {i}: {'|' * count}")
if current_player == name:
# 玩家回合(含输入校验)
while True:
try:
row = int(input(f"\n{name}, choose a row (1-{len(sticks)}): "))
stick_quantity = int(input("How many sticks to take? "))
if 1 <= row <= len(sticks) and 1 <= stick_quantity <= sticks[row-1]:
break
print("Invalid input: row out of range or too many sticks.")
except ValueError:
print("Please enter valid integers.")
sticks[row-1] -= stick_quantity
print_move(name, row, stick_quantity)
current_player = "CPU"
else:
# CPU回合(避免空列表异常)
available_rows = [i for i, s in enumerate(sticks) if s > 0]
if available_rows:
row_idx = random.choice(available_rows)
stick_quantity = random.randint(1, sticks[row_idx])
sticks[row_idx] -= stick_quantity
print_move("CPU", row_idx+1, stick_quantity)
current_player = name
else:
break # 防止CPU在无合法操作时崩溃
# ? 判定胜者(最后行动者输?还是赢?——按原逻辑:取走最后一根者胜)
winner = current_player # 注意:原代码中 winner 是 *未行动方*,因循环结束时 current_player 已切换
# 修正:实际最后取走者是上一轮的 current_player,因此胜者应为上一轮对手
winner = name if current_player == "CPU" else "CPU"
if winner == name:
user_wins += 1
print(f"\n? {name}, you win this round!")
else:
cpu_wins += 1
print(f"\n? CPU wins this round.")
# ? 询问是否再玩
replay = input("\nPlay again? (y/n): ").strip()
# ? 游戏结束,显示总战绩
print(f"\n{'='*40}")
print("GAME OVER — Final Score:")
print(f"{name}: {user_wins} win(s)")
print(f"CPU: {cpu_wins} win(s)")
if user_wins > cpu_wins:
print(f"? Overall winner: {name}")
elif cpu_wins > user_wins:
print("? Overall winner: CPU")
else:
print("? It's a tie!")
print(f"{'='*40}")⚠️ 关键注意事项:
- 状态重置必须彻底:每次进入 while replay == 'y' 时,需重新初始化 sticks、current_player 等所有游戏状态变量,否则会继承上局残留数据。
- 胜者判定逻辑需校准:原代码中 winner = current_player 存在逻辑错误——因为循环结束时 current_player 已切换为未行动方。正确做法是根据谁执行了最后一次有效操作来反推胜者(如示例中通过 current_player 的切换关系修正)。
- 输入鲁棒性:使用 .strip().lower() 处理 y/Y/yes 等变体;对 ValueError 和边界条件(如空行)做防御性检查。
- 用户体验优化:添加清晰的分隔线、表情符号和格式化输出,提升可读性。
通过以上结构,你的尼姆游戏即可实现无缝多局体验,并具备完整的胜负追踪能力——真正成为一个可交付的交互式Python小项目。


















