0

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()
quamrana
  • 37,849
  • 12
  • 53
  • 71
  • 1
    Why do you redefince your methods inside the loop over and over again? – Patrick Artner May 15 '22 at 19:17
  • Do you mean the def buttonClicksR/P/S ? I thought I had to do that for each button, in this case 3, because you can click in 3 different areas but they all give a different text on screen. I did one for rock (R), paper (P) and scissors (S), can I do this in 1? – beginnercoder May 15 '22 at 19:53
  • you have a `def whatever(..): ...` inside a loop - so the function is defined on each loop - that is normally not what you want to do or need to do. See overall answer below. You can handle your 3 buttons in one function without problems - same for some more "game logic" - I left you some "TODO"s ;) – Patrick Artner May 15 '22 at 20:12
  • I edited something in the code in the "yes" case - drew too many things there. – Patrick Artner May 15 '22 at 20:23

1 Answers1

0

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()
Patrick Artner
  • 50,409
  • 9
  • 43
  • 69