Randomly chose an action (definition) with random.choice() - python

Code doesn't work like it should. It is just a small thing i would like to learn as a new coder:
import turtle
import random
me=turtle.Turtle()
def up_right():
me.right(90)
me.forward(100)
def down_right():
me.right(90)
me.forward(100)
choose = (up_right(), down_right)
random.choice(chose)
It should pick one and do it but it picks them both.
I've tried random.sample and random.choice but cant get them to work.

Besides the typo of choose... My suggestion is that after you create a tuple of functions and choose the function using random.choice(), you should make a call to the function chosen by the random.choice().
# Notice I removed the () after up_right so it doesn't make the function call on this line
choose = (up_right, down_right)
# random.choice will return one of the two, and then the () will call whatever function was chosen
random.choice(choose)()

I see three issues with your code. The first two folks have pointed out already, the choose vs chose typo and leaving the parens () on upright when refering to it as a function (up_right(), down_right).
The third is that up_right and down_right both implement the same motion, so even if the rest of your code worked, you wouldn't see any difference! Below's a rewrite that fixes this issue:
from turtle import Screen, Turtle
from random import choice
def up_right(turtle):
turtle.setheading(90)
turtle.forward(100)
def down_right(turtle):
turtle.setheading(270)
turtle.forward(100)
choices = [up_right, down_right]
screen = Screen()
me = Turtle('turtle')
choice(choices)(me)
screen.mainloop()
Run it several times and you'll see sometimes the turtle heads up the screen, sometimes it heads down.

Related

How do I fix the "turtle.terminator error?

I wanted to make a blinking "Press SPACE to start!" screen and if SPACE was pressed, the program should shut down but I always get the turtle.terminator error. Can someone help me please?
from turtle import *
import pygame
while True:
x = 0
penup()
tracer(0)
if x == 0:
color("black")
goto(-80,-170)
write("Press SPACE to start!",font=50)
update()
pygame.time.delay(1*800)
x = 1
if x == 1:
color("white")
goto(-90,-180)
begin_fill()
goto(90,-180)
goto(90,-140)
goto(-90,-140)
goto(-90,-180)
end_fill()
update()
x = 0
pygame.time.delay(1*800)
def close():
bye()
onkey(close(),"Space")
done()
After integrating advice from the comments, it still raises an error when I use onkey(close,...) instead of onkey(close(),..).
It is "space", not "Space". Also, it is still correct to use onkey(close, ...).
The complete function would be onkey(close, "space")
There are a few issues here. A word of advice: work in small bursts and run your code often to validate all of your assumptions at each step of the way. This code looks as if it was all written in one fell swoop, and once it didn't work, there was too much complexity to isolate the bugs. Had you run the code to test it often as you went along, you'd see those errors immediately and the solutions would be more obvious.
Try to minimize the problem space by breaking your functionality into small pieces and validating each one.
First, let me provide my solution:
import turtle
def render_white_screen():
win.ontimer(render_press_space, delay_ms)
t.clear()
turtle.update()
def render_press_space():
win.ontimer(render_white_screen, delay_ms)
t.write(
"Press SPACE to start!",
move=False,
align="center",
font=("Arial", 20, "normal"),
)
turtle.update()
delay_ms = 800
turtle.tracer(0)
win = turtle.Screen()
win.onkey(turtle.bye, "space")
win.listen()
t = turtle.Turtle()
t.hideturtle()
t.color("black")
render_press_space()
turtle.mainloop()
Turtle is surprisingly not especially beginner-friendly and has a huge list of gotchas, so it's important to check the docs and do research on Stack Overflow as soon as you encounter an error.
Errors:
turtle.onkey(some_func(), "some key") is incorrect (assuming some_func isn't a higher-order function) because you're calling some_func rather than passing it as the handler. This should be turtle.onkey(some_func, "some key"). This happens to trigger the terminator error because terminator occurs when you run turtle code after exiting, which is what your handler does. See Python Turtle.Terminator even after using exitonclick() and onkeypress( ) function in turtle module problem.
turtle.onkey(space_handler, "Space") should be turtle.onkey(space_handler, "space") (lowercase). See Couldn't get rid of (_tkinter.TclError: bad event type or keysym "UP") problem.
You must call turtle.listen() to activate key handlers that you've registered. See Turtle.onkeypress not working (Python).
Suggestions/better practices:
Always use import turtle, never from turtle import *. The reason is that from turtle import * dumps 160+ functions into the global namespace, causing potential clashes with your own functions. Many of these functions have common names like update and reset that can easily cause confusion and bugs. Turtle has a module-level instance ostensibly to avoid confusion for beginners, but it only winds up introducing more problems in the long run than simply creating a turtle instance.
Don't import pygame just to sleep. Python has a native function sleep available in the time module. But even better is to use turtle's ontimer callback as shown above.
You can clear the screen with t.clear().

Using onscreen.click() in turtle but only works at the end of the programme

This is the programme I wrote but I'm not sure what's wrong:-
import turtle
import random
bob = turtle.Turtle()
screen = turtle.Screen()
def coord(x,y):
print(x,y)
turtle.onscreenclick(None)
turtle.onscreenclick(coord)
turtle.listen()
print('hello')
turtle.done()
The programme works fine except that the print('hello') part happens first, followed by the on screen event. How do I make the onscreen event occur first before the rest of my programme?
You can simply make the rest of your code part of the coord function:
def coord():
print(x,y)
turtle.onscreenclick(None)
print("Hello")
# The rest of your program goes here.
However, a few things to note:
This isn't an amazing elegant solution, especially if you intend to set up other events further into your code. It can become quite hard to keep track of.
It's imperative that you remove the event binding (in this case the binding of coord to onscreenclick) as soon as it's been used, otherwise you could end up with multiple instances of the same code running at once if someone double-clicked the screen, for example. In your case you've already done this (with turtle.onscreenclick(None)), but it is something to keep in mind.
If you choose to go this route, don't forget to rename the coord function something more representative of what that section of your code will do.

Python Turtle Graphics - Bring A Turtle To The Front

I have two turtles in my program. An animation happened where they collide together, but I would like one turtle to be on top of the other like this:
So, my question is - how can I make this happen - is there a simple line of code such as: turtle.front(), if not what is it?
I discuss this briefly in my response to Make one turtle object always above another where the rule of thumb for this simple situation is:
last to arrive is on top
Since Python turtle doesn't optimize away zero motion, a simple approach is to move the turtle you want on top by a zero amount:
import turtle
def tofront(t):
t.forward(0)
gold = turtle.Turtle("square")
gold.turtlesize(5)
gold.color("gold")
gold.setx(-10)
blue = turtle.Turtle("square")
blue.turtlesize(5)
blue.color("blue")
blue.setx(10)
turtle.onscreenclick(lambda x, y: tofront(gold))
turtle.done()
The blue turtle overlaps the gold one. Click anywhere and the situation will be reversed.
Although #Bally's solution works, my issue with it is that it creates a new turtle everytime you adjust the layering. And these turtles don't go away. Watch turtle.turtles() grow. Even my solution leaves footprints in the turtle undo buffer but I have to believe it consumes less resources.
Just add this to turtle.py file
def tofront(self, tobring):
newfront = tobring.clone()
tobring.ht()
return newfront
works correct,
so method - sould return you new clone of turtle, on the top of all other turtles.
parameter tobring - it's your current turtle (the one you want to bring to front)
you can use this def in your program or put it into turtle.py file
if so, don't forget to add it to list of commands, - _tg_turtle_functions
_tg_turtle_functions = ['back', 'backward', 'begin_fill', 'begin_poly', 'bk',
'circle', 'clear', 'clearstamp', 'clearstamps', 'clone', 'tofront', 'color',
I did it after clone command
Hope this will help you

Python Turtle with user input

I want to use python turtle to create a program that asks the user how many sides they want on a polygon, then turtle draws it. Here is my code:
import turtle
window = turtle.Screen()
window.bgcolor("lightgreen")
shape = turtle.Turtle()
shape.color("blue")
shape.pensize(3)
sides = int(input("How many sides do you want? Use digits: "))
def polygon(sides,length):
for x in range(sides):
shape.forward(length)
shape.left(360/sides)
For some reason this won't work. Any ideas?
Thanks in advance!
You don't actually call polygon, you only define it (that's what the def part of def polygon(sides,length): means.
Try adding something like
polygon(sides, length)
to the bottom of your script; or more specifically anywhere after the definition.
Original
If you're using Python 2 you should probably use raw_input instead of input.
Other than that, try and include the error message / output to receive a moore targeted answer.
The only reason i can see why it doesn't work is that you haven't put in the final line of code in. This is actually essential or python wont run the def. For your instance it would be: polygon(sides,100)
I only put the 100 in as an example and you can change it yourself to whatever you desire
You need to call the function you create like this:
polygon(sides,100)
Or any other length you want instead of 100
The other thing you can do is to ask user to enter the length from console
length = int(input("How tall do you want the lines? Use digits: "))
Your code should look like this
import turtle
window = turtle.Screen()
window.bgcolor("lightgreen")
shape = turtle.Turtle()
shape.color("blue")
shape.pensize(3)
sides = int(input("How many sides do you want? Use digits: "))
def polygon(sides, length):
for x in range(sides):
shape.forward(length)
shape.left(360/sides)
polygon(10, 90) # replace these numbers with the values that you want
The first thing I saw was you didn't have a space between the two variables in the def() statement. The second thing is that when you create a def it is like creating a big variable where all the code inside is that variable(kinda) the variables inside the parenthesis in the def statement are variables that need to be defined later on when calling the function so that the function will run correctly!

turtle.tracer not working properly

I was writing code for a CodeGolf.SE contest and I came onto something I didn't understand. The code is not the best (e.g. I wouldn't normally use while 1) but the issue is still the same:
import time
from turtle import *
ht()
tracer(3)
while 1:
clear() #1
color("snow") #
a=time.strftime("#%H%M%S") #
bgcolor(a) #2
write(a,0,"center") #3
From the documentation it seems that tracer(3) means that each third screen update is drawn. I think this doesn't work, because when I run this I don't get clear text (it seems like it switches very fast between visible/invisible).
I tried with different arguments for tracer without success. I know a solution is to call tracer(0) instead and update() when needed, but I'd like it to work without update().
the following does solve it, just to show what I mean. As I have understood tracer(n) should propagate the changes each n-th step, and it does not seem to do that:
import time
from turtle import*
tracer(0) #turn of auto-update
while 1:
reset()
ht()
color("snow")
a=time.strftime("#%H%M%S")
write(a,0,"center")
bgcolor(a)
update() #8 propagate changes
The way I would approach this with the current Python3 turtle is avoid tracer() and take advantage of undo() instead:
from turtle import*
import time
ht()
color("snow")
write("")
while 1:
undo()
a=time.strftime("#%H%M%S")
bgcolor(a)
write(a,0,"center")
It does what you want and is fewer strokes golf-wise.

Categories

Resources