Python Forum
[Tkinter] Tic Tac Toe Help
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] Tic Tac Toe Help
#1
Hello, I have been creating a Tic Tac Toe game in Tkinter. It is supposed to draw X's and O's. A left click should place an X and a right click should place an O. There should also be a key on the keyboard that clears all of the Xs and Os on the board (your window should include a Label that explains how to clear the board). I am supposed to write the code using ONLY Label widgets for the spaces (you can use other Widgets for the grid lines). Since you are not using Button widgets, you will have to use event-binding to change what is in each space. You are NOT trying to keep up with wins and losses, and you should NOT worry about preventing a user from "cheating" (e.g., O taking over a space already claimed by X)

I have gotten the grid drawn and I have the first row code done but when I click in any of the blank spaces it doesn't draw anything. I know there is supposed to be more stringvars in order for this to work and this is the part where I am stuck and I am going to define the letter "C" to clear the board. It's supposed to work like this
How Tic Tac Toe supposed to work

from tkinter import *
from tkinter import ttk


root = Tk()
root.title("Tic Tac Toe")

message = StringVar()

# This is the portion that draws out the grid used in Tic Tac Toe

label1 = ttk.Label(root, text="")
label1.grid(row=1, column=0)
label2 = ttk.Label(root, text="|")
label2.grid(row=1, column=1)
label3 = ttk.Label(root, text="")
label3.grid(row=1, column=2)
label4 = ttk.Label(root, text="|")
label4.grid(row=1, column=3)
label5 = ttk.Label(root, text="-")
label5.grid(row=4, column=1)
label6 = ttk.Label(root, text="-")
label6.grid(row=4, column=2)
label7 = ttk.Label(root, text="-")
label7.grid(row=4, column=3)
label8 = ttk.Label(root, text="-")
label8.grid(row=4, column=4)
label9 = ttk.Label(root, text="       ")
label9.grid(row=5, column=0)
label10 = ttk.Label(root, text="|")
label10.grid(row=5, column=1)
label11 = ttk.Label(root, text="       ")
label11.grid(row=5, column=2)
label12 = ttk.Label(root, text="|")
label12.grid(row=5, column=3)
label13 = ttk.Label(root, text="-")
label13.grid(row=6, column=1)
label14 = ttk.Label(root, text="-")
label14.grid(row=6, column=2)
label15 = ttk.Label(root, text="-")
label15.grid(row=6, column=3)
label16 = ttk.Label(root, text="-")
label16.grid(row=6, column=4)
label17 = ttk.Label(root, text="       ")
label17.grid(row=7, column=0)
label18 = ttk.Label(root, text="|")
label18.grid(row=7, column=1)
label19 = ttk.Label(root, text="       ")
label19.grid(row=7, column=2)
label20 = ttk.Label(root, text="|")
label20.grid(row=7, column=3)

#This is the code that draws out the O and X
label21 = ttk.Label(root, text="")
label21.grid(row=1, column=0)
label21.bind("<Button-1>", lambda e: message.set("X"))
label21.bind("<Button-3>", lambda e: message.set("O"))
label22 = ttk.Label(root, text="")
label22.grid(row=1, column=1)
label22.bind("<Button-1>", lambda e: message.set("X"))
label22.bind("<Button-3>", lambda e: message.set("O"))
label22.grid(row=1, column=3)
label22.bind("<Button-1>", lambda e: message.set("X"))
label22.bind("<Button-3>", lambda e: message.set("O"))


root.mainloop()
Reply
#2
This is how you use StringVar to set label text.
import tkinter as tk

font = ('Helvetica', '48', 'bold')

def make_slot(row, col):
    var = tk.StringVar()
    var.set(' ')
    label = tk.Label(root, textvariable=var, font=font, width=2)
    label.bind("<Button-1>", lambda e: var.set("X"))
    label.bind("<Button-3>", lambda e: var.set("O"))
    label.grid(row=row, column=col)
    return var

root = tk.Tk()
board = [make_slot(row, col) for row in range(3) for col in range(3)]
root.mainloop()
You need a StringVar for each label, and you bind it to the label using "textvariable=stringvar" in the label config. Because the same code is repeated 9 times I made a function.

This is an odd way to make a tic-tac-toe game. Players take turns in tic-tac-toe. You should not be using right button/left button. Each click should switch which player gets to play next.

"-" and "|" labels are not a good way to draw the board. If you want something that looks like tic-tac-toe, I suggest using a canvas and creating an image for the board, and images for X and O. Or you could draw the board using canvas.create_line().

If you just want something that is playable, use buttons instead of labels. The button border shows you where you can click.
import tkinter as tk

font = ('Helvetica', '48', 'bold')
player = 0
markers = ('X', 'O')

def play(slot):
    global player

    if board[slot].get() == ' ':
        board[slot].set(markers[player])
        player = (player + 1) % 2

def make_slot(row, col):
    var = tk.StringVar()
    var.set(' ')
    button = tk.Button(root, textvariable=var, font=font, width=2)
    button.configure(command=lambda:play(row * 3 + col))
    button.grid(row=row, column=col)
    return var

root = tk.Tk()
board = [make_slot(row, col) for row in range(3) for col in range(3)]
root.mainloop()
BashBedlam likes this post
Reply
#3
Yes thank you so much!! I got it now!
Reply
#4
You can make a pretty good board using Frames.
import tkinter as tk

Tk()
root.title('Tic-Tac-Toe')
root.geometry('240x240')

# Draw # using frames to make thick lines.
tk.Frame(root, bg='black').place(x=80, y=120, width=5, height=220, anchor=tk.CENTER)
tk.Frame(root, bg='black').place(x=160, y=120, width=5, height=220, anchor=tk.CENTER)
tk.Frame(root, bg='black').place(x=120, y=80, width=220, height=5, anchor=tk.CENTER)
tk.Frame(root, bg='black').place(x=120, y=160, width=220, height=5, anchor=tk.CENTER)

root.mainloop()
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020