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

Python实现井字棋时获胜条件变量未生效问题排查

井字棋程序循环无法退出问题排查

初始可正常运行版本

纯编程初学者基于《Automate the Boring Stuff》习题编写文本版井字棋程序时,最初版本可正常运行,代码如下:

theBoard = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ',
            'mid-L': ' ', 'mid-M': ' ', 'mid-R': ' ',
            'low-L': ' ', 'low-M': ' ', 'low-R': ' '}

def printBoard(board): #function to print board
    print(board['top-L'] + '|' + board['top-M'] + '|' + board['top-R'])
    print('-+-+-')
    print(board['mid-L'] + '|' + board['mid-M'] + '|' + board['mid-R'])
    print('-+-+-')
    print(board['low-L'] + '|' + board['low-M'] + '|' + board['low-R'])

print('''
Hi! This is my tic-tac-toe text based game. 
To make your move, write where you want to play:

top-L   top-M   top-R
mid-L   mid-M   mid-R
low-L   low-M   low-R 

''')

turn= 'X' #starting
while True:
    printBoard(theBoard)
    print(f'Turn for {turn}. Where will you play?')
    try:
        move = input()
        if theBoard[move] == ' ':
            theBoard[move] = turn
            if turn == 'X':
                turn = 'O'
            else:
                turn = 'X'
        else:
            print('That move is not possible!')
            continue
    except KeyError:
        print('''Wrong input.
To make your move, write where you want to play:

top-L   top-M   top-R
mid-L   mid-M   mid-R
low-L   low-M   low-R 

''')
        continue
    if ((theBoard['top-L']==theBoard['top-M']==theBoard['top-R']) and theBoard['top-L']!=' ')\
        or ((theBoard['mid-L']==theBoard['mid-M']==theBoard['mid-R']) and theBoard['mid-R']!=' ')\
        or ((theBoard['low-L']==theBoard['low-M']==theBoard['low-R']) and theBoard['low-L']!=' ')\
        or ((theBoard['top-L']==theBoard['mid-M']==theBoard['low-R']) and theBoard['top-L']!=' ')\
        or ((theBoard['low-L']==theBoard['mid-M']==theBoard['top-R']) and theBoard['low-L']!=' ')\
        or ((theBoard['top-L']==theBoard['mid-L']==theBoard['low-L']) and theBoard['top-L']!=' ')\
        or ((theBoard['top-M']==theBoard['mid-M']==theBoard['low-M']) and theBoard['top-M']!=' ')\
        or ((theBoard['top-R']==theBoard['mid-R']==theBoard['low-R']) and theBoard['top-R']!=' '):
        break

if turn == 'X':
    turn = 'O'
else:
    turn = 'X'
print(f'Good Job {turn}, you won!')

优化后出现的问题

初始版本运行正常,后续参考代码评审建议做优化:了解到代码中直接书写'X'、'O'属于魔术字符串,会降低代码整洁度,因此将其提取为单独变量;随后尝试把所有获胜判定逻辑存入名为conditions的变量中,但修改后玩家达成获胜落子时,程序无法跳出游戏循环。修改后的代码如下:

theBoard = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ',
            'mid-L': ' ', 'mid-M': ' ', 'mid-R': ' ',
            'low-L': ' ', 'low-M': ' ', 'low-R': ' '}

def printBoard(board):
    print(board['top-L'] + '|' + board['top-M'] + '|' + board['top-R'])
    print('-+-+-')
    print(board['mid-L'] + '|' + board['mid-M'] + '|' + board['mid-R'])
    print('-+-+-')
    print(board['low-L'] + '|' + board['low-M'] + '|' + board['low-R'])


conditions = (((theBoard['top-L'] == theBoard['top-M'] == theBoard['top-R']) and theBoard['top-L'] != ' ') \
or ((theBoard['mid-L'] == theBoard['mid-M'] == theBoard['mid-R']) and theBoard['mid-R'] != ' ') \
or ((theBoard['low-L'] == theBoard['low-M'] == theBoard['low-R']) and theBoard['low-L'] != ' ') \
or ((theBoard['top-L'] == theBoard['mid-M'] == theBoard['low-R']) and theBoard['top-L'] != ' ') \
or ((theBoard['low-L'] == theBoard['mid-M'] == theBoard['top-R']) and theBoard['low-L'] != ' ') \
or ((theBoard['top-L'] == theBoard['mid-L'] == theBoard['low-L']) and theBoard['top-L'] != ' ') \
or ((theBoard['top-M'] == theBoard['mid-M'] == theBoard['low-M']) and theBoard['top-M'] != ' ') \
or ((theBoard['top-R'] == theBoard['mid-R'] == theBoard['low-R']) and theBoard['top-R'] != ' '))

print('''
Hi! This is my tic-tac-toe text based game. 
To make your move, write where you want to play:

top-L   top-M   top-R
mid-L   mid-M   mid-R
low-L   low-M   low-R 

''')

playerX = 'X'
playerO = 'O'
turn= playerX
while True:
    printBoard(theBoard)
    print(f'Turn for {turn}. Where will you play?')
    try:
        move = input()
        if theBoard[move] == ' ':
            theBoard[move] = turn
            if turn == playerX:
                turn = player0
            else:
                turn = playerX
        else:
            print('That move is not possible!')
            continue
    except KeyError:
        print('''Wrong input.
To make your move, write where you want to play:

top-L   top-M   top-R
mid-L   mid-M   mid-R
low-L   low-M   low-R 

''')
        continue
    if conditions == True:
        printBoard(theBoard)
        break

if turn == playerX:
    turn = player0
else:
    turn = playerX
print(f'Good Job {turn}, you won!')

问题原因

修改后的代码存在两个核心bug:

  • 获胜条件计算时机错误:conditions变量是在游戏循环启动前赋值的,这行代码运行时棋盘所有位置都是空格,因此conditions从初始化开始就固定为布尔值False。后续落子更新棋盘时,这个变量不会自动重新计算结果,循环中判断if conditions == True永远不成立,自然无法触发break退出循环。
  • 变量名拼写错误:定义玩家标识时写的是playerO(末尾是大写字母O),但切换回合、判定获胜者的代码里全部写成了player0(末尾是数字0),拼写不一致会触发NameError,即便修复获胜逻辑,程序跑到切换O玩家回合时也会直接崩溃。

修复方案

  1. 不要提前把获胜判定的计算结果存为固定变量,将获胜逻辑封装为独立函数,每次落子后调用函数,实时读取当前棋盘状态计算是否满足获胜条件:
def check_win(board):
    return (
        ((board['top-L']==board['top-M']==board['top-R']) and board['top-L']!=' ')
        or ((board['mid-L']==board['mid-M']==board['mid-R']) and board['mid-R']!=' ')
        or ((board['low-L']==board['low-M']==board['low-R']) and board['low-L']!=' ')
        or ((board['top-L']==board['mid-M']==board['low-R']) and board['top-L']!=' ')
        or ((board['low-L']==board['mid-M']==board['top-R']) and board['low-L']!=' ')
        or ((board['top-L']==board['mid-L']==board['low-L']) and board['top-L']!=' ')
        or ((board['top-M']==board['mid-M']==board['low-M']) and board['top-M']!=' ')
        or ((board['top-R']==board['mid-R']==board['low-R']) and board['top-R']!=' ')
    )

循环内的获胜判断直接替换为if check_win(theBoard):即可。
2. 全局查找替换所有写错的player0为playerO,保证变量名前后一致。


内容的提问来源于stack exchange,提问作者Miguel Rodrigues

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 21:39:15