Just Made a Tic-Tac-Toe Game in Python (How You Can Too)
It's easy to think that making a tic-tac-toe game using Python is complicated, time-consuming, and just for really advanced developers. In reality it isn't, and in just a few steps, I'll show you how to make a simple tic-tac-toe game. Step 1: Create the Layout We'll start by creating a Python file. Afterwards, we'll import Tkinter (module for creating GUIs in Python) then define things such as fonts, the GUI's size and background, and so on: from tkinter import * from tkinter import font root = Tk() root.title("Python-Tic-Tac-Toe Game") root.configure(bg='lightblue') # Sets GUI background to lightblue root.geometry("300x400") # Defines size of GUI root.resizable(False, False) # Says GUI can't be resized f = font.Font(family='Courier', size=24) o = font.Font(family='Courier', size=18) Great! Now, wouldn't it be good to have a welcome page w/ a 'Yes' or 'No' button? I bet you said yes (and if you didn't, go back to Ohio!). To do that, simply type/copy and paste: l = Label(root, text="Python Tic\nTac Toe Game", font=f, bg='lightblue') l.place(x=30, y=30) b = Label(root, text="Wish to continue?", font=o, bg='lightblue') b.place(x=30, y=150) c = Button(root, text="Yes", font=o, width=10, height=1, bg='white') c.place(x=70, y=220) d = Button(root, text="No", font=o, width=10, height=1, bg='white') d.place(x=70, y=290) Our program should now look something like this: Our program looks great! But if you notice, the buttons won't do anything. To solve that, underneath d.place(), type/copy and paste: d.config(command=da) and underneath c.place(), type/copy and paste: c.config(command=ca) After that, create and fill in functions da and ca, like so: def da(): root.destroy() #This deletes the GUI when someone clicks the button 'No' def ca(): l.destroy() b.destroy() d.destroy() c.destroy() global vas global av global ab vas = Label(root, text="Which one would\nyou like to use?", font=o, bg='lightblue') vas.place(x=30, y=30) av = Button(root, text="X", font=o, bg='white', width=5, height=2) av.place(x=30, y=150) ab = Button(root, text="O", font=o, bg='white', width=5, height=2) ab.place(x=170, y=150) This will delete the contents from the welcome page and replace them with new text (that being 'Which one would you like to use?') and new buttons (that being X or O). Now, once we click 'Yes', or GUI should like this: Step 2: Create the Tic-Tac-Toe board We've now created a welcome page, and given the user the ability to choose either X or O. But sadly, the buttons don't do anything, and we still haven't made the actual tic-tac-toe board. To fix that, underneath av.place() type/copy and paste: av.config(command=x) and underneath ab.place() type/copy and paste: ab.config(command=ask) Once finished, create and fill in functions x and ask, like so: def x(): global vas, av, ab, ba, bb, bc, bd, be, bf, bg, bh, bi, label, i, buttons vas.destroy() av.destroy() ab.destroy() # Row 1 ba = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(ba, buttons)) ba.place(x=30, y=70) bb = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(bb, buttons)) bb.place(x=110, y=70) bc = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(bc, buttons)) bc.place(x=190, y=70) # Row 2 bd = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(bd, buttons)) bd.place(x=30, y=145) be = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(be, buttons)) be.place(x=110, y=145) bf = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(bf, buttons)) bf.place(x=190, y=145) # Row 3 bg = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(bg, buttons)) bg.place(x=30, y=220) bh = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(bh, buttons)) bh.place(x=110, y=220) bi = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(bi, buttons)) bi.place(x=190, y=220) label = Label(root, text=f'TIMER:\nO:15', font=o, bg='lightblue') label.place(x=100, y=10) buttons = [ba, bb, bc, bd, be, bf, bg, bh, bi] start_time = Time.time() for i in range(15, -1, -1): label.config(text=f'TIMER:\nO:{i}') root.update() #force the label to update. Time.sleep(0.8) #add a one second delay, so the user can see the change. end = Time.time() r = end - start_time result = 12 - r if result < 1: for button in buttons: button.config(state=DISABLED) label.destroy() d = Label(root, text='No Winner: Tie!!!!', font=o, bg='l

It's easy to think that making a tic-tac-toe game using Python is complicated, time-consuming, and just for really advanced developers. In reality it isn't, and in just a few steps, I'll show you how to make a simple tic-tac-toe game.
Step 1: Create the Layout
We'll start by creating a Python file. Afterwards, we'll import Tkinter (module for creating GUIs in Python) then define things such as fonts, the GUI's size and background, and so on:
from tkinter import *
from tkinter import font
root = Tk()
root.title("Python-Tic-Tac-Toe Game")
root.configure(bg='lightblue') # Sets GUI background to lightblue
root.geometry("300x400") # Defines size of GUI
root.resizable(False, False) # Says GUI can't be resized
f = font.Font(family='Courier', size=24)
o = font.Font(family='Courier', size=18)
Great! Now, wouldn't it be good to have a welcome page w/ a 'Yes' or 'No' button? I bet you said yes (and if you didn't, go back to Ohio!). To do that, simply type/copy and paste:
l = Label(root, text="Python Tic\nTac Toe Game", font=f, bg='lightblue')
l.place(x=30, y=30)
b = Label(root, text="Wish to continue?", font=o, bg='lightblue')
b.place(x=30, y=150)
c = Button(root, text="Yes", font=o, width=10, height=1, bg='white')
c.place(x=70, y=220)
d = Button(root, text="No", font=o, width=10, height=1, bg='white')
d.place(x=70, y=290)
Our program should now look something like this:
Our program looks great! But if you notice, the buttons won't do anything. To solve that, underneath d.place(), type/copy and paste:
d.config(command=da)
and underneath c.place(), type/copy and paste:
c.config(command=ca)
After that, create and fill in functions da and ca, like so:
def da():
root.destroy() #This deletes the GUI when someone clicks the button 'No'
def ca():
l.destroy()
b.destroy()
d.destroy()
c.destroy()
global vas
global av
global ab
vas = Label(root, text="Which one would\nyou like to use?", font=o, bg='lightblue')
vas.place(x=30, y=30)
av = Button(root, text="X", font=o, bg='white', width=5, height=2)
av.place(x=30, y=150)
ab = Button(root, text="O", font=o, bg='white', width=5, height=2)
ab.place(x=170, y=150)
This will delete the contents from the welcome page and replace them with new text (that being 'Which one would you like to use?') and new buttons (that being X or O). Now, once we click 'Yes', or GUI should like this:
Step 2: Create the Tic-Tac-Toe board
We've now created a welcome page, and given the user the ability to choose either X or O. But sadly, the buttons don't do anything, and we still haven't made the actual tic-tac-toe board. To fix that, underneath av.place() type/copy and paste:
av.config(command=x)
and underneath ab.place() type/copy and paste:
ab.config(command=ask)
Once finished, create and fill in functions x and ask, like so:
def x():
global vas, av, ab, ba, bb, bc, bd, be, bf, bg, bh, bi, label, i, buttons
vas.destroy()
av.destroy()
ab.destroy()
# Row 1
ba = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(ba, buttons))
ba.place(x=30, y=70)
bb = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(bb, buttons))
bb.place(x=110, y=70)
bc = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(bc, buttons))
bc.place(x=190, y=70)
# Row 2
bd = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(bd, buttons))
bd.place(x=30, y=145)
be = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(be, buttons))
be.place(x=110, y=145)
bf = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(bf, buttons))
bf.place(x=190, y=145)
# Row 3
bg = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(bg, buttons))
bg.place(x=30, y=220)
bh = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(bh, buttons))
bh.place(x=110, y=220)
bi = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action(bi, buttons))
bi.place(x=190, y=220)
label = Label(root, text=f'TIMER:\nO:15', font=o, bg='lightblue')
label.place(x=100, y=10)
buttons = [ba, bb, bc, bd, be, bf, bg, bh, bi]
start_time = Time.time()
for i in range(15, -1, -1):
label.config(text=f'TIMER:\nO:{i}')
root.update() #force the label to update.
Time.sleep(0.8) #add a one second delay, so the user can see the change.
end = Time.time()
r = end - start_time
result = 12 - r
if result < 1:
for button in buttons:
button.config(state=DISABLED)
label.destroy()
d = Label(root, text='No Winner: Tie!!!!', font=o, bg='lightblue')
d.place(x=20, y=30)
def ask():
global vas, av, ab, b1, b2, b3, b4, b5, b6, b7, b8, b9, label, buttons1
vas.destroy()
av.destroy()
ab.destroy()
# Row 1
b1 = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action1(b1, buttons1))
b1.place(x=30, y=70)
b2 = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action1(b2, buttons1))
b2.place(x=110, y=70)
b3 = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action1(b3, buttons1))
b3.place(x=190, y=70)
# Row 2
b4 = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action1(b4, buttons1))
b4.place(x=30, y=145)
b5 = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action1(b5, buttons1))
b5.place(x=110, y=145)
b6 = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action1(b6, buttons1))
b6.place(x=190, y=145)
# Row 3
b7 = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action1(b7, buttons1))
b7.place(x=30, y=220)
b8 = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action1(b8, buttons1))
b8.place(x=110, y=220)
b9 = Button(root, font=o, bg='white', width=5, height=2, text=' ', command=lambda: u_action1(b9, buttons1))
b9.place(x=190, y=220)
label = Label(root, text=f'TIMER:\nO:15', font=o, bg='lightblue')
label.place(x=100, y=10)
buttons1 = [b1, b2, b3, b4, b5, b6, b7, b8, b9]
start_time = Time.time()
for i in range(15, -1, -1):
label.config(text=f'TIMER:\nO:{i}')
root.update() #force the label to update.
Time.sleep(0.8) #add a one second delay, so the user can see the change.
end = Time.time()
r = end - start_time
result = 12 - r
if result < 1:
for button in buttons1:
button.config(state=DISABLED)
label.destroy()
d = Label(root, text='No Winner: Tie!!!!', font=o, bg='lightblue')
d.place(x=20, y=30)
With these functions, you should have the tic-tac-toe board as well as a 15 second timer:
(P.S: If the timer isn't what you wish it to be, you can always change it in text=f'TIMER:\nO:15' and for i in range(15, -1, -1) )
Again, we're faced with the issue of the buttons not doing anything. To solve that, we'll have to...
Step 3: Allow User to Play
Start by creating functions, u_action and u_action1, and fill them in with the code below:
def u_action(button, buttons):
button.config(text='X')
button.config(state=DISABLED)
def u_action1(button, buttons1):
button.config(text='O')
button.config(state=DISABLED)
Now, once we click a button, it becomes filled with X or O and is then disabled (as in it can't be clicked again). It's progress, but tic-tac-toe wasn't made for just one player. To fix that, we'll need to create a bot, and since I said this tutorial would be easy, simply download the Logic module (link: https://drive.google.com/file/d/1aWYqNuVPvVdRNNtXuo670ULCxJMiJ8Bq/view?usp=sharing), then import it into your file:
import Logic #make sure 'l' is uppercase to avoid errors.
Afterwards, add the line below to u_action():
Logic.b_action(root, buttons, label, o)
and add this code to u_action1():
Logic.b_action1(root, buttons1, label, o)
Congrats