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

如何实现Tkinter Canvas中数独初始单元格不可编辑?

修复数独游戏的单元格编辑权限问题

当前代码的核心问题是编辑权限判断逻辑错误,导致初始带有数值的单元格也能被修改。以下是修复后的完整代码,以及关键修改说明:

from sudoku import Sudoku
from tkinter import *

root = Tk()
root.title('Sudoku')
root.geometry('378x378')
root.resizable(0, 0)

canvas = Canvas(root)
canvas.pack(fill=BOTH, expand=True)

def draw_board():
    canvas.create_line(42, 0, 42, 378, width=2, fill='lightgray')
    canvas.create_line(84, 0, 84, 378, width=2, fill='lightgray')
    
    canvas.create_line(168, 0, 168, 378, width=2, fill='lightgray')
    canvas.create_line(210, 0, 210, 378, width=2, fill='lightgray')
    
    canvas.create_line(294, 0, 294, 378, width=2, fill='lightgray')
    canvas.create_line(336, 0, 336, 378, width=2, fill='lightgray')

    canvas.create_line(0, 42, 378, 42, width=2, fill='lightgray')
    canvas.create_line(0, 84, 378, 84, width=2, fill='lightgray')

    canvas.create_line(0, 168, 378, 168, width=2, fill='lightgray')
    canvas.create_line(0, 210, 378, 210, width=2, fill='lightgray')

    canvas.create_line(0, 294, 378, 294, width=2, fill='lightgray')
    canvas.create_line(0, 336, 378, 336, width=2, fill='lightgray')

    canvas.create_line(126, 0, 126, 378, width=4, fill='black')
    canvas.create_line(252, 0, 252, 378, width=4, fill='black')
    canvas.create_line(0, 126, 378, 126, width=4, fill='black')
    canvas.create_line(0, 252, 378, 252, width=4, fill='black')

cell_values = {}

def draw_nums():
    global puzzle
    for y_cord, row in enumerate(puzzle):
        for x_cord, num in enumerate(row):
            x_pos = 20 + x_cord * 42
            y_pos = 20 + y_cord * 42
            cell = chr(ord('a') + x_cord) + str(y_cord + 1)
            if num is None:
                canvas.create_text(x_pos, y_pos, text="", fill='gray', font=('Arial', 35, 'bold'), tags=(f"text_{cell}", "editable"))
            else:
                canvas.create_text(x_pos, y_pos, text=str(num), fill='black', font=('Arial', 35, 'bold'), tags=(f"text_{cell}", "uneditable"))
            cell_values[cell] = num

puzzle = Sudoku(3).difficulty(0.8)
puzzle = puzzle.board

def draw_ans(event):
    cell = detect_pos(event)
    if not cell:
        return
    # 检查单元格是否不可编辑
    if "uneditable" in canvas.gettags(f"text_{cell}"):
        return
    # 处理可编辑单元格的数值更新
    current_value = cell_values[cell]
    new_value = (current_value % 9) + 1 if current_value is not None else 1
    update_cell(cell, new_value)

def update_cell(cell, value):
    x_cord, y_cord = ord(cell[0]) - ord('a'), int(cell[1]) - 1
    puzzle[y_cord][x_cord] = value
    x_pos = 20 + x_cord * 42
    y_pos = 20 + y_cord * 42
    canvas.delete(f"text_{cell}")
    # 保持可编辑标签
    canvas.create_text(x_pos, y_pos, text=str(value), fill='gray', font=('Arial', 35, 'bold'), tags=(f"text_{cell}", "editable"))
    cell_values[cell] = value

def detect_pos(event):
    x_cord, y_cord = event.x // 42, event.y // 42
    if 0 <= x_cord <= 8 and 0 <= y_cord <= 8:
        return chr(ord('a') + x_cord) + str(y_cord + 1)

canvas.bind("<Button-1>", draw_ans)

draw_board()
draw_nums()

root.mainloop()

关键修改说明

  • 明确标签区分权限:在draw_nums中,给初始空单元格添加editable标签,初始有值单元格添加uneditable标签,直观区分权限。
  • 简化编辑判断逻辑:在draw_ans中,先检查点击的单元格是否带有uneditable标签,若是则直接返回,不执行任何编辑操作。
  • 移除冗余变量:删除了无用的puzzle_cells列表,避免逻辑混淆。
  • 优化视觉区分:将初始有值单元格的文字颜色改为黑色,和用户输入的灰色形成视觉差异,提升体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 20:45:14