
本文详解如何在python实现的尼姆游戏中嵌套主循环,支持用户选择重复对局,并自动统计玩家胜/负场次,避免逻辑错位与状态残留问题。
本文详解如何在python实现的尼姆游戏中嵌套主循环,支持用户选择重复对局,并自动统计玩家胜/负场次,避免逻辑错位与状态残留问题。
要让尼姆游戏真正具备可重玩性,不能仅在单局逻辑内简单加一层 while,而需重构程序结构:将整局游戏封装为函数,并在外层用主循环控制是否重启,同时维护跨局的计分状态。
以下是优化后的完整实现方案(关键改动已高亮说明):
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}")
def display_sticks(sticks):
"""清晰显示当前每行火柴数(带行号和竖线)"""
for i, count in enumerate(sticks, 1):
print(f"{i}: {'|' * count}")
def get_player_move(sticks, name):
"""安全获取玩家输入,含完整校验"""
while True:
try:
row = int(input(f"\n{name}, which row? (1-{len(sticks)}): "))
if not (1 0]
if not non_empty_rows:
return None, None
row_idx = random.choice(non_empty_rows)
row = row_idx + 1
stick_quantity = random.randint(1, sticks[row_idx])
return row, stick_quantity
def play_one_game(name):
"""执行一局完整游戏,返回获胜者(name 或 'CPU')"""
sticks = [1, 3, 5, 7]
current_player = random.choice([name, "CPU"])
print(f"\n--- New Game ---\n{current_player} goes first!")
while sum(sticks) > 0:
display_sticks(sticks)
if current_player == name:
row, stick_quantity = get_player_move(sticks, name)
sticks[row - 1] -= stick_quantity
print_move(current_player, row, stick_quantity)
current_player = "CPU"
else:
row, stick_quantity = get_cpu_move(sticks)
if row is None: # 理论上不会发生,防错
break
sticks[row - 1] -= stick_quantity
print_move(current_player, row, stick_quantity)
current_player = name
# 胜者是上一轮之后的 current_player(因取走最后一根者获胜,轮到对方时已无子可取)
winner = "CPU" if current_player == name else name
print(f"\n? Winner is {winner}!")
return winner
# === 主程序入口:支持重复游玩 + 计分 ===
if __name__ == "__main__":
print("Welcome to Nim!")
name = input("Enter your name: ").strip() or "Player"
# 初始化计分器
wins = 0
losses = 0
replay = 'y'
while replay.lower() == 'y':
winner = play_one_game(name)
if winner == name:
wins += 1
else:
losses += 1
# 询问是否再玩
replay = input("\nPlay again? (y/n): ").strip()
# 游戏结束总结
print(f"\n{'='*40}")
print(f"? Final Score for {name}:")
print(f"✅ Wins: {wins}")
print(f"❌ Losses: {losses}")
if wins > losses:
print("? You're the ultimate Nim master!")
elif losses > wins:
print("? CPU remains undefeated... for now.")
else:
print("⚖️ It's a perfect tie!")
print(f"{'='*40}")
关键设计要点说明:
- 函数化封装:play_one_game() 将单局逻辑完全隔离,确保每次重启时 sticks、current_player 等状态从零初始化,避免变量污染。
- 计分持久化:wins/losses 在主循环外定义,跨局累加;replay.lower() == 'y' 支持大小写输入。
-
健壮性增强:
- get_player_move() 增加空行检查与范围提示;
- display_sticks() 提升可读性(明确标注 row X:);
- CPU逻辑加入 non_empty_rows 防错,杜绝 IndexError。
- 胜负判定修正:原代码中 winner = current_player 存在逻辑错误(取走最后一根者应为胜者,而此时轮到对方),本实现通过轮换时机精准判断。
✅ 测试建议:运行后连续输入 y 多次,验证计分是否准确累加;输入 Y、yes、n、空格等边界值,确认程序鲁棒性。
通过这种结构化重构,你的尼姆游戏不仅实现了“再玩一次”的核心需求,更具备了生产级代码的可维护性与用户体验。










