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

Python Turtle库turtle.Terminator报错排查及修复求助

Fixing turtle.Terminator Exception in Your Python Turtle Game

我帮你分析下这个问题——你遇到的turtle.Terminator异常,本质是当Turtle图形窗口已经关闭后,代码还在尝试创建或操作Turtle对象导致的。结合你的代码和错误栈,我梳理出几个核心问题,以及对应的修复步骤:

1. 核心错误原因

  • 循环内重复定义函数与创建Turtle/Screen对象:你的Forme.draw()方法里有个while boucle循环,每次选"1. Jouer"时,都会重复定义setup_labyrinthe、scorefn,还会重新创建Screen、Stylo等对象。第一次退出游戏后窗口关闭,循环再次运行时,旧的Turtle上下文没清理,新对象创建就触发了异常。
  • 未正确导入模块却使用turtle.Pen():你只from turtle import Turtle, Screen,但代码里写了t = turtle.Pen(),这会导致NameError(虽然你的错误栈没显示,但这是隐藏隐患)。
  • 全局变量使用混乱:scorefn里用global score,但score是在循环内定义的,多次运行会导致作用域冲突。

2. 分步修复方案

(1)把函数移到循环外部,避免重复定义

将setup_labyrinthe、scorefn这些核心函数从while boucle里抽出来,明确变量传递逻辑:

from turtle import Turtle, Screen

# 你的类定义保持不变:Stylo、Joueur、Tresor、Forme

# 移到循环外的关卡初始化函数
def setup_labyrinthe(niveau, stylo, joueur, tresors, murs):
    for y in range(len(niveau)):
        for x in range(len(niveau[y])):
            caractere = niveau[y][x]
            ecran_x = -288 + (x * 24)
            ecran_y = 288 - (y * 24)
            if caractere == "X":
                stylo.goto(ecran_x, ecran_y)
                stylo.stamp()
                murs.append((ecran_x, ecran_y))
            elif caractere == "J":
                joueur.goto(ecran_x, ecran_y)
            elif caractere == "T":
                tresors.append(Tresor(ecran_x, ecran_y))

# 移到循环外的得分函数,用参数传递替代全局变量
def scorefn(joueur, tresors, score, marker, police1, police2, screen):
    # 用切片遍历,避免修改列表时的迭代错误
    for tresor in tresors[:]:
        if joueur.collision(tresor):
            tresor.destruction()
            tresors.remove(tresor)
            score += 100
            marker.undo()
            marker.write(score, font=police1)
            if score == 1000 :
                marker.goto(-150, 0)
                marker.write("You Win !", font=police2)
    return score

(2)每次游戏创建全新的Turtle上下文

每次启动游戏时,都创建新的Screen和Turtle实例,避免复用已失效的窗口对象:

class Forme(object):
    def __init__(self, length, width, color, sides):
        self.length = length
        self.width = width
        self.color = color
        self.sides = sides

    def draw(self):
        # 替换turtle.Pen()为Turtle(),适配你的导入方式
        t = Turtle()
        boucle=True
        while boucle:
            a=int(input("Choisissez la figure à réaliser avec Turtle :\n1. Jouer \n2. Leaderboard \n0. Sortir"))
            if a==1:
                # 每次游戏都创建全新的屏幕
                game_screen = Screen()
                game_screen.bgcolor("black")
                game_screen.title("No Escape!")
                game_screen.setup(700, 700)

                # 加载游戏资源
                IMAGES = ["right.gif", "left.gif", "face.gif", "back.gif", "tresor.gif", "mur.gif", "sol.gif"]
                for image in IMAGES:
                    game_screen.addshape(image)

                POLICE1 = ('Arial', 24, 'bold')
                POLICE2 = ('Arial', 50, 'bold')
                NIVEAUX = [[ 
                    "XXXXXXXXXXXXXXXXXXXXXXXXX",
                    "XJ X X X",
                    "X X XXX X XXXXXXX X",
                    "X X TX X X X",
                    "X XXXXX X X XXXXXXX X",
                    "XT X X X",
                    "XXXXXXXX X XT X X X",
                    "X X X XXXXXXXXXXXXXX X",
                    "X X X X X X X",
                    "X X XT X X X X XTX",
                    "X X XXXX X X XXXXXX X XXX",
                    "X X X X X TX X X",
                    "X XXX XX XXXXXXXXXXXXXX",
                    "X X X X",
                    "XXXXXXXX XTX X X XXX X",
                    "X X X XXX X X XT X",
                    "X XXX X X X X XXXXX",
                    "X XXT X X XXXXXXX X X X",
                    "X XXXXX X X",
                    "X XXXXXXXXXX X X",
                    "XXXXX XXXXX X",
                    "X X X X XX XXXXX",
                    "X XXXXXXXX X XXX X XX",
                    "X TX X XT X X X",
                    "XXXXXXXXXXXXXXXXXXXXXXXXX"]]

                # 创建游戏对象
                stylo = Stylo()
                joueur = Joueur()
                tresors = []
                murs = []

                # 初始化关卡
                setup_labyrinthe(NIVEAUX[0], stylo, joueur, tresors, murs)

                # 初始化得分面板
                score = 0
                marker = Turtle(visible=False)
                marker.penup()
                marker.color('gray')
                marker.goto(-275, 305)
                marker.write("No Escape !", font=POLICE1)
                marker.goto(240, 305)
                marker.write(score, font=POLICE1)

                # 给玩家对象绑定游戏引用,方便调用得分函数
                joueur.set_game_refs(tresors, marker, POLICE1, POLICE2, game_screen, murs)

                # 绑定按键事件
                game_screen.onkeypress(joueur.gauche, "Left")
                game_screen.onkeypress(joueur.droite, "Right")
                game_screen.onkeypress(joueur.haut, "Up")
                game_screen.onkeypress(joueur.bas, "Down")
                
                # 自定义退出逻辑,确保窗口干净关闭
                def quit_game():
                    game_screen.clear()
                    game_screen.bye()
                game_screen.onkey(quit_game, "Escape")
                
                game_screen.listen()
                game_screen.tracer(True)
                game_screen.mainloop()  # 阻塞直到窗口关闭

            elif a==0:
                boucle=False
                # 退出时关闭所有残留窗口
                Screen().bye()

(3)修改Joueur类,支持参数传递

给Joueur类添加方法,让它能访问游戏状态变量,调用得分函数:

class Joueur(Turtle):
    def __init__(self):
        Turtle.__init__(self, "face.gif")
        self.color("blue")
        self.penup()
        self.speed('fastest')
        # 初始化游戏引用
        self.tresors = []
        self.marker = None
        self.police1 = None
        self.police2 = None
        self.screen = None
        self.murs = []
        self.score = 0

    def set_game_refs(self, tresors, marker, police1, police2, screen, murs):
        self.tresors = tresors
        self.marker = marker
        self.police1 = police1
        self.police2 = police2
        self.screen = screen
        self.murs = murs

    def haut(self):
        move_to_x = self.xcor()
        move_to_y = self.ycor() + 24
        self.shape("back.gif")
        if (move_to_x, move_to_y) not in self.murs:
            self.goto(move_to_x, move_to_y)
            self.score = scorefn(self, self.tresors, self.score, self.marker, self.police1, self.police2, self.screen)

    # 同理修改bas、gauche、droite方法,把murs换成self.murs,调用scorefn更新self.score
    def bas(self):
        move_to_x = self.xcor()
        move_to_y = self.ycor() - 24
        self.shape("face.gif")
        if (move_to_x, move_to_y) not in self.murs:
            self.goto(move_to_x, move_to_y)
            self.score = scorefn(self, self.tresors, self.score, self.marker, self.police1, self.police2, self.screen)

    def gauche(self):
        move_to_x = self.xcor() - 24
        move_to_y = self.ycor()
        self.shape("left.gif")
        if (move_to_x, move_to_y) not in self.murs:
            self.goto(move_to_x, move_to_y)
            self.score = scorefn(self, self.tresors, self.score, self.marker, self.police1, self.police2, self.screen)

    def droite(self):
        move_to_x = self.xcor() + 24
        move_to_y = self.ycor()
        self.shape("right.gif")
        if (move_to_x, move_to_y) not in self.murs:
            self.goto(move_to_x, move_to_y)
            self.score = scorefn(self, self.tresors, self.score, self.marker, self.police1, self.police2, self.screen)

    def collision(self, other):
        return self.distance(other) < 5

3. 关键注意点

  • 别用全局变量:全局变量很容易在循环场景下出问题,尽量用参数传递或类属性管理状态。
  • 每次游戏都新建上下文:Turtle的窗口和对象绑定紧密,窗口关闭后对象就失效了,所以每次启动游戏都要创建新实例。
  • 遍历列表时用切片:修改tresors列表时,用tresors[:]创建切片遍历,避免迭代时修改原列表导致的错误。

这样修改后,应该就能解决turtle.Terminator异常,游戏逻辑也会更稳定清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:03:38