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

Tkinter GUI网格点击单元格坐标获取及战舰显示问题咨询

嘿,作为刚上手Python和tkinter的新手,能搞定战舰游戏的GUI部分已经超棒了!针对你遇到的两个问题,我来给你拆解一下解决思路和代码示例,应该能帮你顺利推进期末项目~


问题1:获取棋盘格子的A,3、I,9这类坐标

你之前直接用event.x和event.y的问题很典型——因为每个格子是一片区域,不是单点,所以同一格子里不同位置点击会返回不同数值,还会捕获到棋盘外的点击。解决的核心是把像素坐标映射到棋盘的行列索引,再转成字母+数字的格式。

首先,我们先定义几个统一的棋盘参数(你可以根据自己的GUI调整数值):

# 棋盘配置:10列(A-J)、10行(1-10),每个格子50px,棋盘左上角起始位置(50,50)
GRID_SIZE = 10
CELL_SIZE = 50
BOARD_X_START = 50
BOARD_Y_START = 50

然后修改你的donne_position函数,先判断点击是否在棋盘范围内,再计算对应的行列:

def donne_position(event):
    TexteC.delete("0.0", END)
    
    # 先过滤棋盘外的点击
    if (event.x < BOARD_X_START or event.x >= BOARD_X_START + GRID_SIZE * CELL_SIZE or
        event.y < BOARD_Y_START or event.y >= BOARD_Y_START + GRID_SIZE * CELL_SIZE):
        TexteC.insert(END, "请点击棋盘内的格子哦!")
        return
    
    # 计算列索引(0-9),转成A-J的字母
    col_index = (event.x - BOARD_X_START) // CELL_SIZE
    col_letter = chr(ord('A') + col_index)
    # 计算行索引(0-9),转成1-10的数字
    row_index = (event.y - BOARD_Y_START) // CELL_SIZE
    row_number = row_index + 1
    
    TexteC.insert(END, f"检测到点击:坐标 {col_letter},{row_number}")

这样不管你点击格子里的哪个位置,都会返回同一个标准坐标,棋盘外的点击也会被提示,完美解决你之前的问题~


问题2:在棋盘格子上显示5格战舰(圆形表示)

tkinter的Canvas组件可以用create_oval绘制圆形,我们只需要把战舰的每个格子对应到棋盘的像素坐标上就行。这里我写一个通用的绘制函数,支持水平或垂直放置战舰:

def draw_battleship(canvas, start_col, start_row, direction="horizontal"):
    # 把起始坐标(比如"A",1)转成索引(0-9)
    start_col_idx = ord(start_col.upper()) - ord('A')
    start_row_idx = start_row - 1
    
    # 遍历战舰的5个格子,逐个画圆形
    for i in range(5):
        if direction == "horizontal":
            # 水平放置:列索引递增,行索引不变
            current_col = start_col_idx + i
            current_row = start_row_idx
        else:
            # 垂直放置:行索引递增,列索引不变
            current_col = start_col_idx
            current_row = start_row_idx + i
        
        # 计算每个格子内圆形的坐标(留5px边距,让圆形居中美观)
        x1 = BOARD_X_START + current_col * CELL_SIZE + 5
        y1 = BOARD_Y_START + current_row * CELL_SIZE + 5
        x2 = BOARD_X_START + (current_col + 1) * CELL_SIZE - 5
        y2 = BOARD_Y_START + (current_row + 1) * CELL_SIZE - 5
        
        # 绘制蓝色圆形,黑色边框
        canvas.create_oval(x1, y1, x2, y2, fill="blue", outline="black")

调用示例(假设你的Canvas组件叫canvas):

# 在A1到A5的位置水平放置一艘战舰
draw_battleship(canvas, "A", 1, "horizontal")
# 或者在C3到C7的位置垂直放置
# draw_battleship(canvas, "C", 3, "vertical")

如果之后需要移除战舰,可以把create_oval返回的ID保存下来,比如:

# 保存战舰所有圆形的ID
battleship_ids = []
for i in range(5):
    # ...计算坐标...
    oval_id = canvas.create_oval(x1, y1, x2, y2, fill="blue", outline="black")
    battleship_ids.append(oval_id)

# 移除战舰时
for oval_id in battleship_ids:
    canvas.delete(oval_id)

另外,建议你用代码绘制棋盘网格(而不是手动画),这样所有元素的坐标都是基于统一参数,不容易出错:

def draw_board(canvas):
    # 绘制竖线
    for col in range(GRID_SIZE + 1):
        x = BOARD_X_START + col * CELL_SIZE
        canvas.create_line(x, BOARD_Y_START, x, BOARD_Y_START + GRID_SIZE * CELL_SIZE)
    # 绘制横线
    for row in range(GRID_SIZE + 1):
        y = BOARD_Y_START + row * CELL_SIZE
        canvas.create_line(BOARD_X_START, y, BOARD_X_START + GRID_SIZE * CELL_SIZE, y)
    # 绘制列字母(A-J)
    for col in range(GRID_SIZE):
        x = BOARD_X_START + col * CELL_SIZE + CELL_SIZE//2
        canvas.create_text(x, BOARD_Y_START-20, text=chr(ord('A')+col))
    # 绘制行数字(1-10)
    for row in range(GRID_SIZE):
        y = BOARD_Y_START + row * CELL_SIZE + CELL_SIZE//2
        canvas.create_text(BOARD_X_START-20, y, text=str(row+1))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:10:41