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

Tkinter井字棋获胜判定失效与标记自动消失问题求助

问题修复与代码优化

问题1:标记自动消失的原因及解决

代码中存在一段不必要的自动清除逻辑:当记录步数的array长度超过5时,会自动清除最早的标记并重置对应按钮。这是导致标记莫名消失的根本原因,井字棋无需自动移除旧标记,直接删除这段冗余逻辑即可。

问题2:获胜判定异常的原因及解决

原代码仅检查了standings的前3项(三行的和),完全忽略了列(索引3-5)和对角线(索引6-7)的获胜组合。需将判定循环范围改为range(8),覆盖所有8种获胜可能。同时,弹出获胜窗口后需禁用所有按钮避免无效操作,且改用Toplevel创建弹窗(而非新的Tk()实例,防止多主窗口冲突)。


修复后的完整代码

from tkinter import *

frm = []; btn = []; who = True
playArea = []
standings = []                   # 存储各行、列、对角线的和

def play(n):
    global who
    # 标记当前位置
    btn[n].config(text='X' if who else '0', state=DISABLED)
    playArea[n] = 1 if who else -1
    
    # 更新所有获胜组合的和
    standings[0] = playArea[0] + playArea[1] + playArea[2]  # 第一行
    standings[1] = playArea[3] + playArea[4] + playArea[5]  # 第二行
    standings[2] = playArea[6] + playArea[7] + playArea[8]  # 第三行
    standings[3] = playArea[0] + playArea[3] + playArea[6]  # 第一列
    standings[4] = playArea[1] + playArea[4] + playArea[7]  # 第二列
    standings[5] = playArea[2] + playArea[5] + playArea[8]  # 第三列
    standings[6] = playArea[0] + playArea[4] + playArea[8]  # 主对角线
    standings[7] = playArea[2] + playArea[4] + playArea[6]  # 副对角线

    # 检查所有获胜组合
    for s in standings:
        if s == 3:
            show_win_message('Player X Won!', 'Player X has won! Congrats!')
            disable_all_buttons()
            return
        elif s == -3:
            show_win_message('Player 0 Won!', 'Player 0 has won! Congrats!')
            disable_all_buttons()
            return
    
    # 切换玩家
    who = not who

def show_win_message(title, message):
    # 使用Toplevel创建弹窗,避免多主窗口问题
    win = Toplevel()
    win.title(title)
    win.geometry('350x175')
    lbl = Label(win, text=message)
    lbl.place(x=50, y=70)  # 调整位置避免超出窗口

def disable_all_buttons():
    # 禁用所有棋盘按钮,防止继续操作
    for button in btn:
        button.config(state=DISABLED)

# 初始化棋盘
for i in range(3):
    frm.append(Frame())
    frm[i].pack(expand=YES, fill=BOTH)
    for j in range(3):
        btn.append(Button(frm[i], text=' ', font=('mono', 20, 'bold'), width=3, height=2))
        btn[i*3+j].config(command=lambda n=i*3+j: play(n))
        btn[i*3+j].pack(expand=YES, fill=BOTH, side=LEFT, padx=1, pady=1)
        playArea.append(0)
        standings.append(0)

mainloop()

关键修改点说明

  1. 移除自动清除标记逻辑:删除了array相关的所有代码,包括check_array_length函数、标记清除逻辑,确保所有下过的标记保留到游戏结束。
  2. 完善获胜判定:将判定循环改为遍历所有8个standings元素,覆盖行、列、对角线的所有获胜情况。
  3. 优化弹窗实现:用Toplevel替代Tk()创建获胜弹窗,避免多主窗口导致的异常;新增disable_all_buttons函数,获胜后禁用所有按钮,防止无效操作。
  4. 代码结构优化:将弹窗和禁用按钮逻辑封装为独立函数,提升代码可读性和可维护性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 06:36:10