0

I'm trying to make Connect 4 in python, but I can't figure out how to get the coordinates of the screen click so I can use them. Right now, I want to draw the board, then have someone click, draw a dot, then go back to the top of the while loop, wipe the screen and try again. I've tried a couple different options but none have seemed to work for me.

def play_game():
"""
When this function runs, allows the user to play a game of Connect 4
against another person
"""
turn = 1
is_winner = False
while is_winner == False:
    # Clears screen
    clear()
    # Draws empty board
    centers = draw_board()
    # Decides whose turn it is, change color appropriately
    if turn % 2 == 0:
        color = RED
    else:
        color = BLACK
    # Gets coordinates of click
    penup()
    onscreenclick(goto)
    dot(HOLE_SIZE, color)
    turn += 1
ggorlen
  • 44,755
  • 7
  • 76
  • 106
Bleecher
  • 1
  • 1
  • 2
  • What options have you tried? Also, what GUI library are you using? Without knowing that, it's hard to answer. – wirefox Jul 29 '16 at 15:41
  • @wirefox presumably turtle - at least that's what the title says – Wayne Werner Jul 29 '16 at 16:54
  • @WayneWerner yeah, turtle to me doesn't unambiguously resolve to a GUI library; he could have been talking about a generic turtle agent and using something else to draw – wirefox Jul 29 '16 at 18:46
  • Does this answer your question? [Python 3.0 using turtle.onclick](https://stackoverflow.com/questions/15893236/python-3-0-using-turtle-onclick) – ggorlen Sep 22 '22 at 18:28

4 Answers4

1

As well intentioned as the other answers are, I don't believe either addresses the actual problem. You've locked out events by introducing an infinite loop in your code:

is_winner = False
while is_winner == False:

You can't do this with turtle graphics -- you set up the event handlers and initialization code but turn control over to the main loop event handler. My following rework show how you might do so:

import turtle

colors = ["red", "black"]
HOLE_SIZE = 2

turn = 0
is_winner = False

def draw_board():
    pass
    return (0, 0)

def dot(color):
    turtle.color(color, color)
    turtle.stamp()

def goto(x, y):
    global turn, is_winner

    # add code to determine if we have a winner

    if not is_winner:
        # Clears screen
        turtle.clear()
        turtle.penup()

        # Draws empty board
        centers = draw_board()

        turtle.goto(x, y)

        # Decides whose turn it is, change color appropriately
        color = colors[turn % 2 == 0]
        dot(color)

        turn += 1
    else:
        pass

def start_game():
    """
    When this function runs, sets up a new
    game of Connect 4 against another person
    """

    global turn, is_winner

    turn = 1
    is_winner = False

    turtle.shape("circle")
    turtle.shapesize(HOLE_SIZE)

    # Gets coordinates of click
    turtle.onscreenclick(goto)

start_game()

turtle.mainloop()

Run it and you'll see the desired behavior you described.

cdlane
  • 40,441
  • 5
  • 32
  • 81
  • What is the benefit of making turn and is_winner global variables instead of creating them in start_game and passing them into goto as parameters? – Bleecher Aug 01 '16 at 16:49
  • Also, if I want to create other functions that test if the place where the user clicked is already occupied or empty, I'm guessing I would call these functions in goto right above drawing the dot. However, if the condition is False, how can I have the game skip and let the person reclick? Does break work here? – Bleecher Aug 01 '16 at 16:57
  • @HelpPlz, we can't pass `turn` and `is_winner` into `goto()` as that function is called by `turtle.onscreenclick()` and we don't control what parameters are passed. As far as your other question, I suggest you close off this current question and ask a new one, with whatever additional code you've added. – cdlane Aug 01 '16 at 22:38
  • hi I am new to python and had a couple questions here. Your method has no instantiation of a screen but it creates one anyways, how is this? Also, on line 55 u pass in "goto" as a parameter when it is declared as a method, how did you do this? – Wizard Oct 30 '20 at 20:48
  • @Wizard, by doing `import turtle`, the screen object's methods are also defined as top level functions (on an *implicit* singular screen instance argument). Calling `turtle.onscreenclick()` is a function that invokes `onscreenclick()` on this screen instance. It is due to this sort of confusion that I typically do `from turtle import Screen, Turtle` to make the objects *explicit*. As far as the `goto`, functions are also data and the `onscreenclick()` takes a function as an argument, not a call to it, so that *it* can call the function later. Read about events in the turtle documentation. – cdlane Oct 30 '20 at 23:21
0

I'm assuming that your using Turtle in python(hence the name.) If that's the case, Here's a link to a helpful post: Turtle in python- Trying to get the turtle to move to the mouse click position and print its coordinates I know, i know. I hate just link answers as much as the next guy. But The post I gave a link to can probably do a much better job of answering your question than I can.

~Mr.Python

Community
  • 1
  • 1
Christian Dean
  • 22,138
  • 7
  • 54
  • 87
0

Assuming you're using turtle as mentioned in your title:

>>> import turtle
>>> help(turtle.onscreenclick)

Help on function onscreenclick in module turtle:

onscreenclick(fun, btn=1, add=None)
    Bind fun to mouse-click event on canvas.

    Arguments:
    fun -- a function with two arguments, the coordinates of the
           clicked point on the canvas.
    num -- the number of the mouse-button, defaults to 1

    Example (for a TurtleScreen instance named screen)

    >>> onclick(goto)
    >>> # Subsequently clicking into the TurtleScreen will
    >>> # make the turtle move to the clicked point.
    >>> onclick(None)

That means that your callback function, which you have apparently named goto, will take two parameters, an X and Y location.

import turtle

def goto(x, y):
    print('Moving to {}, {}'.format(x,y))
    turtle.goto(x, y)

turtle.onscreenclick(goto)
turtle.goto(0,0)

Each click that you make will move the turtle to a different position. Note that turtle already has an event loop - you don't need one of your own. Just respond to the clicks.

Wayne Werner
  • 49,299
  • 29
  • 200
  • 290
0

basically, you need to add an 'x' and 'y' parameter for the onclick and onscreenclick functions. You don't need to use them, they're just dummy params. After filling those out the clicks will work no problem:

window = turtle.Screen()

This function uses the x, y params because i'm saving the clicks in order to specify an area to fill with turtles

def on_left_click_save_coordinates(x, y):
    global counter, Fill_COORS1, Fill_COORS2
    counter += 1
    print(x, y)

    if counter == 1:
        Fill_COORS1 = (x, y)
    elif counter == 2:
        Fill_COORS2 = (x, y)
        counter = 0

This one doesn't use the x,y params because they are dummies, this one is used to allow multiple options, one of which exits, another tells the turtle to fill in the specified area saved in clicks above.

def on_right_click_open_options(x, y):
    global going
    last_color = options(window, filler, Fill_COORS1, Fill_COORS2, LAST_BLOCK_USED)
    if type(Last_COLOR) == type(bool):
        going = True



window.onscreenclick(on_click, btn=1)
window.onscreenclick(open_options, btn=3)

This is an example of a snippet of my code. hope this helps. btn 3 refers to the right click btn 1 is the default and isn't necessary to specify and refers to left click

btn 2 is the scroll wheel click, not scroll.

and sorry if this isn't formatted the best, it's my first time posting to stackoverflow. Hope it helps nonetheless

Andronicus
  • 25,419
  • 17
  • 47
  • 88