如何检查 Tkinter 画布中的单元格是否存在于列表中

问题描述 投票:0回答:1

我正在尝试使用 tkinter 创建一个简单的数独游戏

我正在使用数独库,它会生成以下形式的谜题

puzzle = [[3, None, None, None, 2, None, None, None, None], [None, None, None, None, None, None, 7, None, 6], [2, 6, 7, None, None, None, None, None, None], [None, 9, None, None, None, None, None, 1, None], [None, None, None, None, None, None, None, None, None], [None, None, None, None, 4, None, None, None, None], [1, None, None, None, None, None, None, 9, 2], [None, None, None, None, 6, None, None, 
None, 1], [4, None, None, None, None, 1, None, None, None]]

例如

我试图让我的代码仅编辑初始值为“无”的单元格,并阻止其编辑。

你可以尝试完整的代码来理解我的意思:

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')



puzzle_cells = []

def draw_nums():
    global x_pos, y_pos, puzzle, cell_values
    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:
                # Only draw numbers for empty cells
                cell_id = canvas.create_text(x_pos, y_pos, text="", fill='gray', font=('Arial', 35, 'bold'), tags=(f"text_{cell}"))
                puzzle_cells.append(cell_id)
            else:
                # Don't allow editing filled cells
                cell_id = canvas.create_text(x_pos, y_pos, text=str(num), fill='gray', font=('Arial', 35, 'bold'), tags=(f"text_{cell}", "uneditable"))
            cell_values[cell] = num

puzzle = Sudoku(3).difficulty(0.8)
puzzle = puzzle.board
x_pos = 20
y_pos = 20
cell_values = {}

def draw_ans(event):
    global x_pos, y_pos, puzzle, cell_values, puzzle_cells
    cell = detect_pos(event)
    if cell:
        cell_id = canvas.find_withtag(f"text_{cell}")
        # Only allow adding numbers to empty cells in the puzzle and not in puzzle_cells
        if cell_values[cell] is None and not cell_id in puzzle_cells:
            new_value = 1  # Start with 1 for empty cells
        else:
            if cell_id not in puzzle_cells:
                new_value = (cell_values[cell] % 9) + 1
        update_cell(cell, new_value)

def update_cell(cell, value):
    global x_pos, y_pos, puzzle, cell_values
    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}")  # Delete the old text
    canvas.create_text(x_pos, y_pos, text=str(value), fill='gray', font=('Arial', 35, 'bold'), tags=f"text_{cell}")
    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("<Motion>", detect_pos)
canvas.bind("<Button-1>", draw_ans)

draw_board()
draw_nums()

root.mainloop()

这会编辑所有单元格,我希望拼图本身提供的单元格不可编辑

python-3.x tkinter tkinter-canvas sudoku
1个回答
1
投票

您应该保留原始生成的板并用它来确定单元格是否可编辑。

import copy
...
_puzzle = Sudoku(3).difficulty(0.8)
# duplicate the board to puzzle
puzzle = copy.deepcopy(_puzzle.board)
...
# function to get the value of a cell in original board
def get_puzzle_initial_value(cell):
    col = ord(cell[0]) - ord('a')
    row = int(cell[1]) - 1
    return _puzzle.board[row][col]

def draw_ans(event):
    cell = detect_pos(event)
    num = get_puzzle_initial_value(cell)
    if num is None:
        global x_pos, y_pos, puzzle, cell_values, puzzle_cells
        if cell:
            cell_id = canvas.find_withtag(f"text_{cell}")
            # Only allow adding numbers to empty cells in the puzzle and not in puzzle_cells
            if cell_values[cell] is None and not cell_id in puzzle_cells:
                new_value = 1  # Start with 1 for empty cells
            else:
                if cell_id not in puzzle_cells:
                    new_value = (cell_values[cell] % 9) + 1
            update_cell(cell, new_value)
© www.soinside.com 2019 - 2024. All rights reserved.