问题
I am trying to code a program that starts and stops a turtle by pressing the space bar. I got the code to start the turtle moving but it doesn't stop it when I press it again. It seems to just increase the speed. Here are my coding requirements and the code I typed up.
Create a turtle program with three functions to control the turtle. Create a function called turnLeft that turns the turtle 90 degrees left when the right arrow is pressed on the keyboard. Create a function called turnRight that turns the turtle 90 degrees right when the right arrow is pressed. Create a third function called move() that moves the turtle forward when the space bar is pressed, then stops the turtle when the spacebar is pressed a second time.
import turtle
turtle.setup(400,500)
wn = turtle.Screen()
wn.title("Tess moves in space")
wn.bgcolor("lightgreen")
tess = turtle.Turtle()
def leftTurtle():
tess.left(90)
def rightTurtle():
tess.right(90)
state_num = 0
def advance_state_machine():
global state_num
if state_num == 0:
tess.penup()
state_num = 1
else:
tess.pendown()
tess.forward(2)
state_num = 0
wn.ontimer(advance_state_machine, 25)
def exitWindow():
wn.bye()
wn.onkey(advance_state_machine, "space")
wn.onkey(exitWindow, "q")
wn.onkey(leftTurtle, "Left")
wn.onkey(rightTurtle, "Right")
wn.listen()
wn.mainloop()
回答1:
You got it almost right except some tiny details to change. The global variable state_num
decided in the advance_state_machine()
function if the turtle should move or not. You got the proper logic for the turns, so why not apply the same logic for a move/pause ?
In your original code you were just switching each shown frame the global variable value from one state to another and with the SPACE key you started another instance of advance_state_machine()
what made the turtle faster. The turtle got faster because with each SPACE a further loop implemented in advance_state_machine()
was started to run in parallel to the existing one(s).
In the code below the function movementControl()
changes the value of boolean should_move
to the opposite one on SPACE and the advance_state_machine()
evaluates should_move
to let the turtle move or stop:
import turtle
turtle.setup(400,500)
wn = turtle.Screen()
wn.title("Tess moves in space")
wn.bgcolor("lightgreen")
tess = turtle.Turtle()
def leftTurtle():
tess.left(90)
def rightTurtle():
tess.right(90)
should_move = False
def movementControl():
global should_move
should_move = not should_move
def advance_state_machine():
global should_move
if should_move:
tess.pendown()
tess.forward(2)
else:
tess.penup()
wn.ontimer(advance_state_machine, 25)
def exitWindow():
wn.bye()
wn.onkey(movementControl, "space")
wn.onkey(exitWindow, "q")
wn.onkey(leftTurtle, "Left")
wn.onkey(rightTurtle, "Right")
wn.listen()
advance_state_machine()
wn.mainloop()
Wow!!! With cdlane's
help we put here a really nice basic turtle example together.
Now I have modified HIS code a bit more towards a minimalistic version and got rid of the movementControl() function, too.
I personally don't like to use from turtle import *
kind of import statements as they provide a huge number of available methods and variables which are "invisible" because you can't directly see where they come from, BUT ... having ALL the code in a so short block isn't it worth it?
from turtle import *
setup(400, 500); title('Turtle moves in space')
bgcolor('lightgreen'); up()
def advance_state_machine():
if isdown(): fd(2)
ontimer(advance_state_machine, 25)
onkey(lambda: (pd, pu)[isdown()](), 'space')
onkey(bye, 'q')
onkey(lambda: lt(90), 'Left')
onkey(lambda: rt(90), 'Right')
listen(); advance_state_machine(); done()
回答2:
The way the state variables state_num
and/or should_move
are used above can be seen as redundant with turtle's own isdown()
predicate. I've rewritten Claudio's solution accordingly but made it minimalist so the isdown()
logic stands out:
from turtle import *
def movementControl():
(pd, pu)[isdown()]()
def advance_state_machine():
if isdown():
fd(2)
ontimer(advance_state_machine, 25)
setup(400, 500)
title('Turtle moves in space')
bgcolor('lightgreen')
up()
onkey(movementControl, 'space')
onkey(bye, 'q')
onkey(lambda: lt(90), 'Left')
onkey(lambda: rt(90), 'Right')
listen()
advance_state_machine()
done()
来源:https://stackoverflow.com/questions/43591581/start-and-stop-python-turtle-with-space-bar