I'm trying to make a rock paper scissors game with 3 buttons to click on on-screen with import turtle. That went well and it worked, the buttons worked and the right text showed up on screen when clicking a certain button. (I haven't added the computer choosing part yet, so my code is only the users input) But now I wanted to add that when you clicked a button for the second time, the text of the last button disappears. Because if you keep clicking, the text stays there and it overlaps. So I wanted to add a "Do you want to play again?" input thing by putting the buttons in a while True loop so it asks the user if they want to play again every time you click a button, but that doesn't work. I don't get any errors, the screen opens and it draws everything for me but I can't click any buttons, the text doesn't show up and then it crashes. If I remove the while loop and the input question, it works again. It should work right? Or is this not possible? I read it somewhere else with another game so I don't know why it doesn't work. This is my code with the while True loop. The while True loop is at the end and I'm sorry if my code is longer than it should be, I don't know all the tricks yet:
import turtle
fontButtons = ("Courier", 22, "bold")
fontText = ("Arial", 26, "bold")
screen = turtle.Screen()
screen.bgcolor("light blue")
screen.setup(800,800)
#center = turtle.Turtle()
#center.goto(0,0)
#center.shape("circle")
#center.size(1)
#game
pen = turtle.Turtle()
pen.hideturtle()
pen.speed(0)
pen.penup()
pen.fillcolor("light yellow")
pen.goto(-250,0)
pen.begin_fill()
pen.pendown()
for i in range(2):
pen.forward(225)
pen.left(90)
pen.forward(200)
pen.left(90)
pen.end_fill()
pen.penup()
pen.goto(25,0)
pen.begin_fill()
pen.pendown()
for i in range(2):
pen.forward(225)
pen.left(90)
pen.forward(200)
pen.left(90)
pen.end_fill()
pen.penup()
pen.goto(-135,165)
pen.write("You", font=fontText, align="center")
pen.goto(135,165)
pen.write("Computer", font=fontText, align="center")
#rock
rock = turtle.Turtle()
rock.hideturtle()
rock.penup()
rock.speed(0)
rock.fillcolor("light yellow")
rock.goto(-200,-100)
rock.pendown()
rock.begin_fill()
for i in range(2):
rock.forward(100)
rock.left(90)
rock.forward(40)
rock.left(90)
rock.end_fill()
rock.penup()
rock.goto(-150,-95)
rock.write("ROCK",font=fontButtons, align="center")
#paper
paper = turtle.Turtle()
paper.hideturtle()
paper.penup()
paper.speed(0)
paper.fillcolor("light yellow")
paper.goto(-50,-100)
paper.pendown()
paper.begin_fill()
for i in range(2):
paper.forward(100)
paper.left(90)
paper.forward(40)
paper.left(90)
paper.end_fill()
paper.penup()
paper.goto(0,-95)
paper.write("PAPER",font=fontButtons, align="center")
#scissor
scissor = turtle.Turtle()
scissor.hideturtle()
scissor.penup()
scissor.speed(0)
scissor.fillcolor("light yellow")
scissor.goto(100,-100)
scissor.pendown()
scissor.begin_fill()
for i in range(2):
scissor.forward(100)
scissor.left(90)
scissor.forward(40)
scissor.left(90)
scissor.end_fill()
scissor.penup()
scissor.goto(150,-95)
scissor.write("SCISSOR",font=fontButtons, align="center")
while True:
#rock click
def buttonClickR(x,y):
if x > -200 and x < -100 and y > -100 and y < -60:
pen.goto(-135,100)
pen.write("Rock", font=fontText, align="center")
turtle.onscreenclick(buttonClickR, 1, True)
turtle.listen()
#paper click
def buttonClickP(x,y):
if x > -50 and x < 50 and y > -100 and y < -60:
pen.goto(-135,100)
pen.write("Paper", font=fontText, align="center")
turtle.onscreenclick(buttonClickP, 1, True)
turtle.listen()
#scissor click
def buttonClickS(x,y):
if x > 100 and x < 200 and y > -100 and y < -60:
pen.goto(-135,100)
pen.write("Scissor", font=fontText, align="center")
turtle.onscreenclick(buttonClickS, 1, True)
turtle.listen()
again = input("Do you want to play again? ")
if again == 'yes':
screen.clear()
else:
print('Bye!')
turtle.done()
The "loop" for turtle needs no while loop - turtle.done()
does not "end" the turtle code - it signals that you are "done" setting all up and starts the everlasting turtle mainloop.
Your code is long because you solve the same problem over and over again instead of putting it into a method to be called with parameters.
You draw 2 big boxes and 3 small boxes, the small boxes also get centered text inside, the bigger boxes different text on top.
Asking for text input while in turtle can be done via turtle.textinput(...) more elegantly then skipping to input() on console.
To quit, use turtle.exitonclick() where appropriate - or call turtle.bye()
.
Your code repeats lots of things you should put into functions:
import turtle
# this uses the ealy defined "pen" turtle - no need to use different ones
# and a global for logic - you can refine that if you want, for demo it works
fontButtons = ("Courier", 22, "bold")
fontText = ("Arial", 26, "bold")
screen = turtle.Screen()
pen = turtle.Turtle()
pen.hideturtle()
pen.speed(0)
pen.penup()
pen.fillcolor("light yellow")
# reapeating things put into methods to be used multiple times
def box_at(x, y, width, height):
"""Makes a box in the current fillcolor at x,y to x+width,y+height.
Pen is up afterwards."""
pen.penup()
pen.goto(x,y)
pen.begin_fill()
pen.pendown()
for i in range(2):
pen.forward(width)
pen.left(90)
pen.forward(height)
pen.left(90)
pen.end_fill()
pen.penup()
def button(x,y,width,height, text):
"""Makes box + text centered inside, space width appropriate to text."""
# no need to repeat painting a box - we solved that earlier
box_at(x,y,width,height)
pen.goto(x+width/2,y)
pen.write(text, font=fontButtons, align="center")
def board():
# YOU
box_at(-250,10,225,200)
# COMPUTER
box_at(25,10,225,200)
# custom text placement
pen.goto(-135,165)
pen.write("You", font=fontText, align="center")
pen.goto(135,165)
pen.write("Computer", font=fontText, align="center")
def buttons():
# all the buttons
button(-200, -100, 120, 40, "ROCK")
button( -50, -100, 120, 40, "PAPER")
button( 100, -100, 120, 40, "SCISSOR")
def reset():
# clear screen and make it beautiful
screen.bgcolor("light blue")
screen.setup(800,800)
board()
buttons()
The game uses these functions like so:
reset()
moves = 0
# all the logic
def buttonClick(x,y):
global moves # not fancy - buts its just a demo
# handle all button clicks inside this one function
# adapted the x/y values to fit my bigger buttons
if x > -200 and x < -80 and y > -100 and y < -60:
board() # this clears the former things
pen.goto(-135,100)
pen.write("Rock", font=fontText, align="center")
moves += 1
elif x > -50 and x < 70 and y > -100 and y < -60:
board() # this clears the former things
pen.goto(-135,100)
pen.write("Paper", font=fontText, align="center")
moves += 1
elif x > 100 and x < 220 and y > -100 and y < -60:
board() # this clears the former things
pen.goto(-135,100)
pen.write("Scissor", font=fontText, align="center")
moves += 1
# TODO make the computer do something, evaluate moves, print tally
# program logic, every 3rd click ask for continue
if moves == 3:
# TODO: print tally and announce winner
again = turtle.textinput("Continue?" , "Do you want to play again? ")
if again == 'yes':
moves = 0
reset()
else:
print('Bye!')
screen.clear()
turtle.exitonclick() # or turtle.bye() directly
# register the game logic click handler
turtle.onscreenclick(buttonClick, 1, True)
# start the mainloop until turtly.bye() or exitonclick() is done
turtle.mainloop()