Reputation: 163
The GUI tiles in this program don't work properly when I first launch the program, but they seem to work fine after I hit the restart button. It seems like the issue is with find_closest()
not selecting the right squares on launch, but it seems to work properly after restarting in the play()
method.
def play(self, event):
"""
user performs a move
calls computer move directly after if game not over
"""
selected_square = self.canvas.find_closest(event.x, event.y)
I've tried moving board
to be an instance variable, but that didn't fix it.
Here is the __init__
method:
class Game(object):
'''
GUI Tic-tac-toe game.
Argument:
parent (tkinter.Tk): the root window object
Attributes:
canvas = (tkinter.Canvas) widget defining game board
game_over = (bool) game state, game over = False, game ongoing = True
moves = (int) number of moves taken by both user and computer
label = (tkinter.Label) shows win/loss/draw message
'''
# Add your class variables if needed here - square size, etc...)
board = [[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]
MAX_MOVES = 9
def __init__(self, parent):
self.parent = parent
parent.title('Tic Tac Toe')
# Create the restart button widget
restart_button = tkinter.Button(self.parent, text='RESTART', width=20,
command=self.restart)
restart_button.pack()
# Create a canvas widget
self.canvas = tkinter.Canvas(parent, background='white', width=300,
height=300)
self.canvas.create_rectangle(0, 0, 300, 300)
self.canvas.create_rectangle(0, 0, 100, 100)
self.canvas.create_rectangle(100, 0, 200, 100)
self.canvas.create_rectangle(200, 0, 300, 100)
self.canvas.create_rectangle(0, 100, 100, 200)
self.canvas.create_rectangle(100, 100, 200, 200)
self.canvas.create_rectangle(200, 100, 300, 200)
self.canvas.create_rectangle(0, 200, 100, 300)
self.canvas.create_rectangle(100, 200, 200, 300)
self.canvas.create_rectangle(200, 200, 300, 300)
self.canvas.pack()
self.label = tkinter.Label(self.parent, text="")
self.label.pack()
self.game_over = False
if not self.game_over:
self.canvas.bind("<Button-1>", self.play)
self.moves = 0
Here is the restart method:
def restart(self):
"""
resets game to beginning state
label erased, game tiles turned back white, button-1 rebound, moves set
to zero
"""
for square in self.canvas.find_all():
self.canvas.itemconfigure(square, fill='white')
self.board = [[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]
self.moves = 0
self.game_over = False
self.canvas.bind("<Button-1>", self.play)
self.label.config(text="")
The rest of the code can be found here.
I've tried printing event.x and event.y and it seems like they're registering correctly as well as updating the board correctly.
Upvotes: 0
Views: 40
Reputation:
The canvas/bindings aren't properly configured when the game starts. I haven't really dug through your code to find out why (There's a lot to dig through for a short answer), but your indices seem to be one behind when you first start. This can be fixed by adding the canvas configuration loop from your restart()
function to the game loop at the bottom of the code block as follows:
def main():
root = tkinter.Tk()
gen_game = Game(root)
**for square in gen_game.canvas.find_all():**
**gen_game.canvas.itemconfigure(square, fill='white')**
root.mainloop()
Or by adding it to the bottom of the __init__
function as follows:
def __init__(self, parent):
self.parent = parent
parent.title('Tic Tac Toe')
# Create the restart button widget
restart_button = tkinter.Button(self.parent, text='RESTART', width=20,
command=self.restart)
restart_button.pack()
# Create a canvas widget
self.canvas = tkinter.Canvas(parent, background='white', width=300,
height=300)
self.canvas.create_rectangle(0, 0, 300, 300)
self.canvas.create_rectangle(0, 0, 100, 100)
self.canvas.create_rectangle(100, 0, 200, 100)
self.canvas.create_rectangle(200, 0, 300, 100)
self.canvas.create_rectangle(0, 100, 100, 200)
self.canvas.create_rectangle(100, 100, 200, 200)
self.canvas.create_rectangle(200, 100, 300, 200)
self.canvas.create_rectangle(0, 200, 100, 300)
self.canvas.create_rectangle(100, 200, 200, 300)
self.canvas.create_rectangle(200, 200, 300, 300)
self.canvas.pack()
self.label = tkinter.Label(self.parent, text="")
self.label.pack()
self.game_over = False
if not self.game_over:
self.canvas.bind("<Button-1>", self.play)
self.moves = 0
**for square in self.canvas.find_all():**
**self.canvas.itemconfigure(square, fill='white')**
Note: Don't actually include the **
when you copy the code. It is just there for emphasis. If it weren't a code block, that would have been reformatted as bold, but it can't be formatted as both bold and code
.
Upvotes: 1