4

I'm new to python and I programed a tic tac toe with an AI that plays against you. Everything is working but I used textboxes to inform the AI what the player chose. Now I want to upgrade my game so that the player can click on the box he wants to fill instead of typing it in the textbox. My idea was to use onscreenclick() but I'm having some issues. onscreenclick() returns the coordinates that have been clicked on the canvas and I want to use a function to determine in which box the player clicked.

I got this:

from turtle import * 

def whichbox(x,y): #obviously i got 9 boxes but this is just an example for box 1
    if x<-40 and x>-120:
        if y>40 and y<120:
            return 1
        else:
            return 0
    else:
        return 0

box=onscreenclick(whichbox)
print(box)

It's obvious that I want box to be 0 or 1 in this case but instead the value of box is None. Does anyone know how to fix this? It has to do something with the variable box because I if replace return 1 with print("1") it works. I assume that the variable gets defined to quickly.

The second question that I have is if its possible pause the programm until the player clicked on a box but its more important to look at the first problem first.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
twinnxx
  • 49
  • 5
  • `whichbox` cannot return `None`. Besides, negative x coordinate is suspicious. Can't you print x and y when whichbox is called? – Jean-François Fabre Feb 21 '19 at 21:31
  • you need to get the x,y coordinates and send them to whichbox. – mauve Feb 21 '19 at 21:32
  • yes i can print the x and y but thats not what I'm aiming for. Sry if this question is dumb or obvious but as i said I'm not very good in programing so how can i put x and y in a variable without finishing the program? – twinnxx Feb 21 '19 at 21:35
  • This isn't a package I use, but I'm saying that you're not sending anything to whichbox. If the results from onscreenclick are (x,y), you would need to do: box = whichbox(onscreenclick[0], onscreenclick[1]) or change what the function is expecting. The way this is currently written, you're sending the variable whichbox (which isn't a variable) to the function onscreenclick – mauve Feb 21 '19 at 21:55
  • `onscreenclick()` simply remembers the specified function, for later use whenever a click occurs. It does not, and fundamentally CANNOT, return anything about a particular click, because no click has occurred yet. Anything you want to do in response to a click should be entirely contained in your `whichbox()` function - returning anything from it is pointless. – jasonharper Feb 21 '19 at 22:48
  • You're misunderstanding what `onscreenclick(()` does. But it doesn't matter as the is the wrong way to go about this problem. Instead, use a grid of nine square turtles and their individual `onclick()` handlers to avoid the decoding math. [Here's a simple example](https://stackoverflow.com/a/49785949/5771269) I swear I provided a similar comment to a similar question by the same OP yesterday but all that's disappeared. Deja vu. – cdlane Feb 23 '19 at 06:21

2 Answers2

2

Assuming you have named your Screen() in the turtle module, you should then put

screen.onscreenclick(whichbox)

instead of:

onscreenclick(whichbox)

Example:

from turtle import Turtle, Screen
turtle = Turtle()
screen = Screen()

def ExampleFunction():
    return 7

screen.onscreenclick(ExampleFunction)

Furthermore, jasonharper is correct when he says the onscreenclick() function is unable to return any value. As such, you can include a print function within your function whichbox() in order to print out a value, like:

def whichbox(x,y): 
    if x<-40 and x>-120:
        if y>40 and y<120:
            print(1)
            return 1
        else:
            print(0)
            return 0
    else:
        print(0)
        return 0

Alternatively, if you wanted to keep the print statement outside of whichbox(), you could also do the following:

screen.onscreenclick(lambda x, y: print(whichbox(x, y)))

which creates a lambda function that gives (x, y) from onscreenclick() to a print statement containing whichbox().

aargon
  • 126
  • 3
  • 9
2

Here's a stripped down example from the code I linked to in my comment. If you click on a square, it will print to the console window its number, from 0 to 8:

from turtle import Turtle, mainloop

CURSOR_SIZE = 20
SQUARE_SIZE = 60

def drawBoard():
    for j in range(3):
        for i in range(3):
            square = Turtle('square', visible=False)
            square.shapesize(SQUARE_SIZE / CURSOR_SIZE)
            square.fillcolor('white')
            square.penup()
            square.goto((i - 1) * (SQUARE_SIZE + 2), (j - 1) * (SQUARE_SIZE + 2))

            number = j * 3 + i
            square.onclick(lambda x, y, number=number: whichsquare(number))
            square.showturtle()

def whichsquare(number):
    print(number)

drawBoard()

mainloop()

There is no position decoding involved -- we let turtle handle that for us.

cdlane
  • 40,441
  • 5
  • 32
  • 81