如何实现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
相关产品推荐
相关产品推荐

