我想在 turtlegraphics 的墙上有一个弹跳球,但它们停下来,它们徘徊并发送错误
I want a bouncing ball on the wall in turtlegraphics, but they stop and they wander and send an error
我画了一些三角形,它们应该在墙上弹跳,但它们不弹跳,不直行,几秒钟后打印错误消息。
当我让三角形只以十字形移动时,三角形摇摇欲坠并出现错误消息。
import turtle
import random
def draw_sq(t,distance=400):#Draw a box
t.penup()
t.goto(-200,200)
t.pendown()
t.forward(distance)
t.right(90)
t.forward(distance)
t.right(90)
t.forward(distance)
t.right(90)
t.forward(distance)
t.penup()
t.goto(0,0)
t.pendown()
def add_tri():
global l_tri
t=turtle.Turtle()
t.shape("triangle")
x=-200
y=random.randint(-200,200)
t.penup()
t.goto(x,y)
t.setheading(random.randint(-89,89))
# make triangle and start
l_tri.append(t)# add a triangle to list
def successMan():#write word succes
global playing
if playing==True:
t.write("success")
def turn_right():
global right
right = True
def turn_left():
global left
left = True
def turn_up():
global up
up = True
def turn_down():
global down
down = True
def _turn_right():
global right
right = False
def _turn_left():
global left
left = False
def _turn_up():
global up
up = False
def _turn_down():
global down
down = False
def is_touch(x,y,triangle,threshold=20):
global playing
if((x-triangle.position()[0])**2+(y-triangle.position()[1])**2<=threshold**2):
playing=False#if triangle touches the turtle make playing False
def timer_go():
global heading
global l_tri
global t
global playing
global up
global left
global down
global right# heading is where turtle heads
if up:
if right:
heading=45
elif left:
heading=135
elif down:
heading = heading
else:
heading=90
if down:
if right:
heading=315
elif left:
heading=225
elif up:
pass
else:
heading = 270
if left:
if right:
heading = heading
elif up:
pass
elif down:
pass
else:
heading = 180
if right:
if left:
pass
elif up:
pass
elif down:
pass
else:
heading = 0
t.setheading(heading)
t.forward(10)
# turtle controller
for i in range(3):#triangles move
if (l_tri[i].position()[0]<-200):
l_tri[i].setheading(180-l_tri[i].heading())
l_tri[i].forward(10)
if (l_tri[i].position()[0]>200):
l_tri[i].setheading(180-l_tri[i].heading())
l_tri[i].forward(10)
if (l_tri[i].position()[1]<-200):
l_tri[i].setheading(-l_tri[i].heading())
l_tri[i].forward(10)
if (l_tri[i].position()[1]>200):
l_tri[i].setheading(-l_tri[i].heading())
l_tri[i].forward(10)#triangle bounces on the wall
l_tri[i].forward(10)
is_touch(t.position()[0],t.position()[1],l_tri[i],threshold=20)
# check triangle and turtle
if (playing==False):
t.write("FAIL")
#Fail
up = False
down = False
right = False
left = False
playing = True
heading = 0
l_tri = []
t = turtle.Turtle()
t.shape('turtle')
t.speed(0)
draw_sq(t)
screen = t.screen
screen.onkeypress(turn_right, 'Right')
screen.onkeypress(turn_left, 'Left')
screen.onkeypress(turn_up, 'Up')
screen.onkeypress(turn_down, 'Down')
screen.onkeyrelease(_turn_right, 'Right')
screen.onkeyrelease(_turn_left, 'Left')
screen.onkeyrelease(_turn_up, 'Up')
screen.onkeyrelease(_turn_down, 'Down')
for i in range(3):
add_tri()
for i in range(1,200):
time = i*100
screen.ontimer(timer_go, time)
screen.ontimer(successMan,20000)
screen.listen()
screen.mainloop()
这应该是一个玩家在盒子里避开三角形的游戏。
当我 运行 它时,我看到错误
RecursionError: maximum recursion depth exceeded while calling a Python object
但我没有在代码中看到递归。
也许问题是
for i in range(1,200):
time = i*100
screen.ontimer(timer_go, time)
可能它创建了太多函数。
你可以运行一次
screen.ontimer(timer_go, 100)
并在 timer_go()
结束时再次使用它
def timer_go():
# ... rest of code ...
screen.ontimer(timer_go, 100)
它会一直重复。
在官方文档中也能看到这个方法:turtle.ontimer
我同意@furas (+1) 关于如何设置您的 ontimer(timer_go, 100)
,但我发现您的代码存在其他问题。我在下面对其进行了修改,希望您发现一些有用的更改。
具体问题:您需要(重新)阅读 global
作为错误使用的一半时间;您不需要重新发明 turtle.distance()
(例如 is_touch()
);您需要将 playing == False
与失败分开,因为您需要在成功或失败时停止游戏;您应该只需要在一个地方指定三角形的数量:
from turtle import Screen, Turtle
from random import randint, choice
FONT = ('Arial', 16, 'normal')
def draw_square(turtle, distance=400): # Draw a box
turtle.speed('fastest')
turtle.penup()
turtle.goto(-200, 200)
turtle.pendown()
for _ in range(4):
turtle.forward(distance)
turtle.right(90)
def add_triangle():
triangle = Turtle("triangle")
triangle.penup()
triangle.goto(choice([(choice([-150, 150]), randint(-150, 150)), (randint(-150, 150), choice([-150, 150]))]))
triangle.setheading(randint(-89, 89))
# make triangle and start
triangles.append(triangle) # add a triangle to list
def successMan(): # write word success
global playing
if playing:
player.write("Success!", font=FONT)
playing = False
def turn_right():
global right
right = True
def turn_left():
global left
left = True
def turn_up():
global up
up = True
def turn_down():
global down
down = True
def _turn_right():
global right
right = False
def _turn_left():
global left
left = False
def _turn_up():
global up
up = False
def _turn_down():
global down
down = False
def is_touch(player, triangle, threshold=20):
return player.distance(triangle) < threshold
def timer_go():
global playing
heading = player.heading()
if up:
if right:
heading = 45
elif left:
heading = 135
elif down:
pass
else:
heading = 90
if down:
if right:
heading = 315
elif left:
heading = 225
elif up:
pass
else:
heading = 270
if left:
if right:
pass
elif up:
pass
elif down:
pass
else:
heading = 180
if right:
if left:
pass
elif up:
pass
elif down:
pass
else:
heading = 0
player.setheading(heading)
player.forward(10)
# turtle controller
for triangle in triangles: # triangles move
x, y = triangle.position()
if not -200 < x < 200:
triangle.setheading(180 - triangle.heading())
triangle.forward(10)
if not -200 < y < 200:
triangle.setheading(-triangle.heading())
triangle.forward(10)
triangle.forward(10)
# check triangle and turtle
if is_touch(player, triangle, threshold=20):
playing = False
player.write("FAIL!", font=FONT) # Fail
if playing:
screen.ontimer(timer_go, 100)
up = False
down = False
right = False
left = False
playing = True
triangles = []
draw_square(Turtle(visible=False))
for _ in range(3):
add_triangle()
player = Turtle('turtle')
player.speed('fastest')
screen = Screen()
screen.onkeypress(turn_right, 'Right')
screen.onkeypress(turn_left, 'Left')
screen.onkeypress(turn_up, 'Up')
screen.onkeypress(turn_down, 'Down')
screen.onkeyrelease(_turn_right, 'Right')
screen.onkeyrelease(_turn_left, 'Left')
screen.onkeyrelease(_turn_up, 'Up')
screen.onkeyrelease(_turn_down, 'Down')
screen.ontimer(successMan, 20_000)
timer_go()
screen.listen()
screen.mainloop()
我怀疑您的 RecursionError
是由于您的按键事件造成的,因为您的模型似乎是一次可以按下多个按键。但是如果一个键按住的时间太长,它会在一个键事件中引起一个键事件,这看起来像递归。您通常可以通过在事件处理程序中首先禁用按键事件处理程序来解决此问题,完成您的工作,然后重新启用按键事件处理程序。
但是,OS 控制的自动按键重复逻辑也可能对您不利。如果您的密钥处理被证明是一个问题,请考虑使用更简单的方法。
我画了一些三角形,它们应该在墙上弹跳,但它们不弹跳,不直行,几秒钟后打印错误消息。
当我让三角形只以十字形移动时,三角形摇摇欲坠并出现错误消息。
import turtle
import random
def draw_sq(t,distance=400):#Draw a box
t.penup()
t.goto(-200,200)
t.pendown()
t.forward(distance)
t.right(90)
t.forward(distance)
t.right(90)
t.forward(distance)
t.right(90)
t.forward(distance)
t.penup()
t.goto(0,0)
t.pendown()
def add_tri():
global l_tri
t=turtle.Turtle()
t.shape("triangle")
x=-200
y=random.randint(-200,200)
t.penup()
t.goto(x,y)
t.setheading(random.randint(-89,89))
# make triangle and start
l_tri.append(t)# add a triangle to list
def successMan():#write word succes
global playing
if playing==True:
t.write("success")
def turn_right():
global right
right = True
def turn_left():
global left
left = True
def turn_up():
global up
up = True
def turn_down():
global down
down = True
def _turn_right():
global right
right = False
def _turn_left():
global left
left = False
def _turn_up():
global up
up = False
def _turn_down():
global down
down = False
def is_touch(x,y,triangle,threshold=20):
global playing
if((x-triangle.position()[0])**2+(y-triangle.position()[1])**2<=threshold**2):
playing=False#if triangle touches the turtle make playing False
def timer_go():
global heading
global l_tri
global t
global playing
global up
global left
global down
global right# heading is where turtle heads
if up:
if right:
heading=45
elif left:
heading=135
elif down:
heading = heading
else:
heading=90
if down:
if right:
heading=315
elif left:
heading=225
elif up:
pass
else:
heading = 270
if left:
if right:
heading = heading
elif up:
pass
elif down:
pass
else:
heading = 180
if right:
if left:
pass
elif up:
pass
elif down:
pass
else:
heading = 0
t.setheading(heading)
t.forward(10)
# turtle controller
for i in range(3):#triangles move
if (l_tri[i].position()[0]<-200):
l_tri[i].setheading(180-l_tri[i].heading())
l_tri[i].forward(10)
if (l_tri[i].position()[0]>200):
l_tri[i].setheading(180-l_tri[i].heading())
l_tri[i].forward(10)
if (l_tri[i].position()[1]<-200):
l_tri[i].setheading(-l_tri[i].heading())
l_tri[i].forward(10)
if (l_tri[i].position()[1]>200):
l_tri[i].setheading(-l_tri[i].heading())
l_tri[i].forward(10)#triangle bounces on the wall
l_tri[i].forward(10)
is_touch(t.position()[0],t.position()[1],l_tri[i],threshold=20)
# check triangle and turtle
if (playing==False):
t.write("FAIL")
#Fail
up = False
down = False
right = False
left = False
playing = True
heading = 0
l_tri = []
t = turtle.Turtle()
t.shape('turtle')
t.speed(0)
draw_sq(t)
screen = t.screen
screen.onkeypress(turn_right, 'Right')
screen.onkeypress(turn_left, 'Left')
screen.onkeypress(turn_up, 'Up')
screen.onkeypress(turn_down, 'Down')
screen.onkeyrelease(_turn_right, 'Right')
screen.onkeyrelease(_turn_left, 'Left')
screen.onkeyrelease(_turn_up, 'Up')
screen.onkeyrelease(_turn_down, 'Down')
for i in range(3):
add_tri()
for i in range(1,200):
time = i*100
screen.ontimer(timer_go, time)
screen.ontimer(successMan,20000)
screen.listen()
screen.mainloop()
这应该是一个玩家在盒子里避开三角形的游戏。
当我 运行 它时,我看到错误
RecursionError: maximum recursion depth exceeded while calling a Python object
但我没有在代码中看到递归。
也许问题是
for i in range(1,200):
time = i*100
screen.ontimer(timer_go, time)
可能它创建了太多函数。
你可以运行一次
screen.ontimer(timer_go, 100)
并在 timer_go()
结束时再次使用它
def timer_go():
# ... rest of code ...
screen.ontimer(timer_go, 100)
它会一直重复。
在官方文档中也能看到这个方法:turtle.ontimer
我同意@furas (+1) 关于如何设置您的 ontimer(timer_go, 100)
,但我发现您的代码存在其他问题。我在下面对其进行了修改,希望您发现一些有用的更改。
具体问题:您需要(重新)阅读 global
作为错误使用的一半时间;您不需要重新发明 turtle.distance()
(例如 is_touch()
);您需要将 playing == False
与失败分开,因为您需要在成功或失败时停止游戏;您应该只需要在一个地方指定三角形的数量:
from turtle import Screen, Turtle
from random import randint, choice
FONT = ('Arial', 16, 'normal')
def draw_square(turtle, distance=400): # Draw a box
turtle.speed('fastest')
turtle.penup()
turtle.goto(-200, 200)
turtle.pendown()
for _ in range(4):
turtle.forward(distance)
turtle.right(90)
def add_triangle():
triangle = Turtle("triangle")
triangle.penup()
triangle.goto(choice([(choice([-150, 150]), randint(-150, 150)), (randint(-150, 150), choice([-150, 150]))]))
triangle.setheading(randint(-89, 89))
# make triangle and start
triangles.append(triangle) # add a triangle to list
def successMan(): # write word success
global playing
if playing:
player.write("Success!", font=FONT)
playing = False
def turn_right():
global right
right = True
def turn_left():
global left
left = True
def turn_up():
global up
up = True
def turn_down():
global down
down = True
def _turn_right():
global right
right = False
def _turn_left():
global left
left = False
def _turn_up():
global up
up = False
def _turn_down():
global down
down = False
def is_touch(player, triangle, threshold=20):
return player.distance(triangle) < threshold
def timer_go():
global playing
heading = player.heading()
if up:
if right:
heading = 45
elif left:
heading = 135
elif down:
pass
else:
heading = 90
if down:
if right:
heading = 315
elif left:
heading = 225
elif up:
pass
else:
heading = 270
if left:
if right:
pass
elif up:
pass
elif down:
pass
else:
heading = 180
if right:
if left:
pass
elif up:
pass
elif down:
pass
else:
heading = 0
player.setheading(heading)
player.forward(10)
# turtle controller
for triangle in triangles: # triangles move
x, y = triangle.position()
if not -200 < x < 200:
triangle.setheading(180 - triangle.heading())
triangle.forward(10)
if not -200 < y < 200:
triangle.setheading(-triangle.heading())
triangle.forward(10)
triangle.forward(10)
# check triangle and turtle
if is_touch(player, triangle, threshold=20):
playing = False
player.write("FAIL!", font=FONT) # Fail
if playing:
screen.ontimer(timer_go, 100)
up = False
down = False
right = False
left = False
playing = True
triangles = []
draw_square(Turtle(visible=False))
for _ in range(3):
add_triangle()
player = Turtle('turtle')
player.speed('fastest')
screen = Screen()
screen.onkeypress(turn_right, 'Right')
screen.onkeypress(turn_left, 'Left')
screen.onkeypress(turn_up, 'Up')
screen.onkeypress(turn_down, 'Down')
screen.onkeyrelease(_turn_right, 'Right')
screen.onkeyrelease(_turn_left, 'Left')
screen.onkeyrelease(_turn_up, 'Up')
screen.onkeyrelease(_turn_down, 'Down')
screen.ontimer(successMan, 20_000)
timer_go()
screen.listen()
screen.mainloop()
我怀疑您的 RecursionError
是由于您的按键事件造成的,因为您的模型似乎是一次可以按下多个按键。但是如果一个键按住的时间太长,它会在一个键事件中引起一个键事件,这看起来像递归。您通常可以通过在事件处理程序中首先禁用按键事件处理程序来解决此问题,完成您的工作,然后重新启用按键事件处理程序。
但是,OS 控制的自动按键重复逻辑也可能对您不利。如果您的密钥处理被证明是一个问题,请考虑使用更简单的方法。