如何在Python Turtle中绑定回车键到函数?井字棋开发遇阻
解决你的井字棋Turtle绑定问题&实现交替落子
嘿,我来帮你搞定这个井字棋的问题!先说说你遇到的几个核心问题,然后给你修改后的完整代码,再解释关键改动点:
问题分析
- 回车键/C键绑定无效:你之前尝试用
getcanvas().bind但没成功,主要是因为你的c()和n()函数没有接收绑定事件传递的event参数,而且用Turtle自带的onkeypress会更简单直接。 - 程序启动自动画叉:大概率是你之前绑定按键时不小心写成了
turtle.onkeypress(c(), "c")——这里的c()会立即执行函数,而不是绑定函数对象,改成c(不带括号)就不会自动触发了。 - 未实现交替落子&位置检查:你需要一个变量跟踪当前该画叉还是圈,还要记录每个格子是否已被占用,避免重复落子。
修改后的完整代码
import turtle sc = turtle.Screen() bo = turtle.Turtle() # 屏幕设置 sc.bgcolor("black") sc.title("tic tac toe") # 绘制棋盘 bo.color("white") bo.penup() bo.speed(0) bo.setposition(-100, -300) bo.pendown() bo.setposition(-100, 300) bo.penup() bo.setposition(100, 300) bo.pendown() bo.setposition(100, -300) bo.penup() bo.setposition(-300, 100) bo.pendown() bo.setposition(300, 100) bo.penup() bo.setposition(300, -100) bo.pendown() bo.setposition(-300,-100) bo.penup() bo.setposition(0,0) # 全局变量:跟踪当前玩家和棋盘状态 current_player = "cross" # 初始为叉 board = [[None for _ in range(3)] for _ in range(3)] # 记录每个格子是否被占用 # 画叉函数 def c(event=None): global current_player x, y = bo.xcor(), bo.ycor() # 判断当前位置对应的棋盘格子 col = None if x == -200: col = 0 elif x == 0: col = 1 elif x == 200: col = 2 else: return # 不在有效格子,不执行 row = None if y == 200: row = 0 elif y == 0: row = 1 elif y == -200: row = 2 else: return # 检查格子是否为空且当前轮到叉玩家 if board[row][col] is None and current_player == "cross": # 绘制叉 bo.penup() bo.setposition(x - 80, y + 80) bo.pendown() bo.setposition(x + 80, y - 80) bo.penup() bo.setposition(x + 80, y + 80) bo.pendown() bo.setposition(x - 80, y - 80) bo.penup() # 更新棋盘状态并切换玩家 board[row][col] = "cross" current_player = "nought" # 画圈函数 def n(event=None): global current_player x, y = bo.xcor(), bo.ycor() # 判断当前位置对应的棋盘格子 col = None if x == -200: col = 0 elif x == 0: col = 1 elif x == 200: col = 2 else: return row = None if y == 200: row = 0 elif y == 0: row = 1 elif y == -200: row = 2 else: return # 检查格子是否为空且当前轮到圈玩家 if board[row][col] is None and current_player == "nought": # 绘制圈 bo.penup() bo.setposition(x, y - 80) bo.pendown() bo.circle(80) bo.penup() # 更新棋盘状态并切换玩家 board[row][col] = "nought" current_player = "cross" # 移动函数 def move_left(): x = bo.xcor() x -= 200 if x < -200: # 修正边界判断,确保停在有效格子位置 x = -200 bo.setx(x) def move_right(): x = bo.xcor() x += 200 if x > 200: x = 200 bo.setx(x) def move_down(): y = bo.ycor() y -= 200 if y < -200: y = -200 bo.sety(y) def move_up(): y = bo.ycor() y += 200 if y > 200: y = 200 bo.sety(y) # 按键绑定(改用Turtle自带的onkeypress,更简洁) turtle.listen() turtle.onkeypress(move_left, "Left") turtle.onkeypress(move_right, "Right") turtle.onkeypress(move_up, "Up") turtle.onkeypress(move_down, "Down") turtle.onkeypress(c, "c") # C键画叉 turtle.onkeypress(n, "Return") # 回车键画圈 turtle.done() # 保持窗口打开
关键改动说明
- 添加状态跟踪:用
current_player变量控制交替落子,board二维数组记录每个格子的占用情况,避免重复落子。 - 修正按键绑定:改用
turtle.onkeypress,不需要处理event参数(函数里留了event=None兼容两种绑定方式),并且绑定的是函数对象(不带括号),不会自动触发。 - 格子位置判断:在画叉/圈前先判断当前turtle位置是否在有效格子(-200/0/200),只有有效位置才会执行绘制。
- 移除不必要的位置重置:原代码里画完后会移回(0,0),现在保留当前位置,方便继续移动到其他格子。
- 修正移动边界:原代码里边界判断是
x < -300,改成x < -200,确保turtle停在正确的格子位置。
现在运行代码,你可以:
- 用方向键在9个格子间移动
- 按C键在当前空位置画叉,之后自动切换为圈玩家
- 按回车键在当前空位置画圈,之后自动切换为叉玩家
内容的提问来源于stack exchange,提问作者Leonardo Cremona
相关产品推荐
相关产品推荐

