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

Python中创建Paddle类第二个实例时第一个实例消失问题

Pong游戏左侧Paddle消失问题排查与修复

问题现象

使用Python Turtle模块开发Pong游戏,创建left_pad = Paddle("left")和right_pad = Paddle("right")实例后,左侧Paddle短暂显示后消失,仅右侧Paddle正常保留在屏幕上,形状与定位均符合预期。

问题代码

paddles.py

from turtle import Turtle

class Paddle:
    side = ""
    paddle = [Turtle(shape="square") for i in range(4)]
    paddle_bottom = -30
    paddle_range = []


    def __init__(self, side):
        self.side = side
        self.paddle_range = [self.paddle[0].screen.canvheight-10, -self.paddle[0].screen.canvheight+10]

        for box in range(len(self.paddle)):
            self.paddle[box].penup()

        # Set to middle height
        for box in range(len(self.paddle)):
            self.paddle[box].sety(self.paddle_bottom + 20*box)
        
        # Set to sides
        if side == "left":
            for box in range(len(self.paddle)):
                self.paddle[box].setx((-self.paddle[0].screen.canvwidth / 2) + 20)
        else:
            for box in range(len(self.paddle)):
                self.paddle[box].setx((self.paddle[0].screen.canvwidth / 2) - 20)


    def move():
        global paddle
        for box in len(range(paddle)):
            paddle[box].forward(1)
        paddle[0].screen.update()


    def move_up():
        global paddle_range
        global move
        for box in len(range(paddle)):
            paddle[box].setheading(90)
        while paddle[-1].ycor() < paddle_range[0]:
            move()


    def move_down():
        for box in len(range(paddle)):
            paddle[box].setheading(270)
        while paddle[0].ycor() > paddle_range[1]:
            move()


    if side == "left":
        paddle[0].screen.onkey(key="w", fun=move_up)
        paddle[0].screen.onkey(key="s", fun=move_down)
    else:
        paddle[0].screen.onkey(key="Up", fun=move_up)
        paddle[0].screen.onkey(key="Down", fun=move_down)

game.py

from turtle import Screen
from paddles import Paddle

screen = Screen()
screen.bgcolor("beige")
screen.title("Pong!")
screen.setup(width=820, height=620)
screen.screensize(canvwidth=800, canvheight=600)
screen.tracer(0)
screen.listen()


left_pad = Paddle("left")
screen.update()
right_pad = Paddle("right")
screen.update()


screen.exitonclick()

问题根源

  1. 类属性共享冲突:paddle是Paddle类的类属性,所有实例共享同一个Turtle列表。创建右侧Paddle时,会覆盖左侧Paddle中所有Turtle的位置,导致左侧Paddle被移至右侧。
  2. 类级事件绑定错误:类定义末尾的事件绑定代码在类加载时执行,而非实例化阶段,此时side为空字符串,绑定逻辑完全失效。
  3. 方法定义不规范:move、move_up、move_down缺少self参数,错误使用全局变量,无法正确访问实例属性。
  4. 循环语法错误:for box in len(range(paddle))是语法错误,正确写法应为for box in range(len(paddle))。
  5. 阻塞事件循环:move_up和move_down中的while循环会阻塞Turtle的事件循环,导致程序无响应。

修复后的代码

paddles.py

from turtle import Turtle

class Paddle:
    def __init__(self, side, screen):
        self.side = side
        self.screen = screen
        # 每个实例独立拥有Turtle列表,避免共享冲突
        self.paddle = [Turtle(shape="square") for _ in range(4)]
        self.paddle_bottom = -30
        self.paddle_range = [self.screen.canvheight - 10, -self.screen.canvheight + 10]

        for box in self.paddle:
            box.penup()
            box.color("black")
        
        # 设置初始高度
        for idx, box in enumerate(self.paddle):
            box.sety(self.paddle_bottom + 20 * idx)
        
        # 设置左右位置并绑定按键
        if side == "left":
            x_pos = (-self.screen.canvwidth / 2) + 20
            self.screen.onkey(key="w", fun=self.move_up)
            self.screen.onkey(key="s", fun=self.move_down)
        else:
            x_pos = (self.screen.canvwidth / 2) - 20
            self.screen.onkey(key="Up", fun=self.move_up)
            self.screen.onkey(key="Down", fun=self.move_down)
        
        for box in self.paddle:
            box.setx(x_pos)

    def move(self, direction):
        # 单次移动逻辑,避免阻塞事件循环
        for box in self.paddle:
            box.setheading(direction)
            box.forward(20)
        self.screen.update()

    def move_up(self):
        # 边界检查后再移动
        if self.paddle[-1].ycor() < self.paddle_range[0]:
            self.move(90)

    def move_down(self):
        # 边界检查后再移动
        if self.paddle[0].ycor() > self.paddle_range[1]:
            self.move(270)

game.py

from turtle import Screen
from paddles import Paddle

screen = Screen()
screen.bgcolor("beige")
screen.title("Pong!")
screen.setup(width=820, height=620)
screen.screensize(canvwidth=800, canvheight=600)
screen.tracer(0)
screen.listen()

# 创建实例时传入screen对象,方便内部访问
left_pad = Paddle("left", screen)
right_pad = Paddle("right", screen)
screen.update()

screen.exitonclick()

修复说明

  • 将paddle从类属性改为实例属性,确保每个Paddle实例拥有独立的Turtle对象集合。
  • 将事件绑定逻辑移至__init__方法内,根据实例的side参数绑定对应按键。
  • 为所有实例方法添加self参数,通过self访问实例属性,移除错误的全局变量引用。
  • 修复循环语法错误,使用enumerate简化索引遍历逻辑。
  • 移除while循环,改为单次移动的逻辑,避免阻塞Turtle事件循环,保证程序响应性。
  • 创建Paddle实例时传入screen对象,方便实例内部访问屏幕属性与绑定事件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 18:46:02