Tic-Tac-Toe Game in Python

Effect Diagram

Tic-Tac-Toe Game in PythonTic-Tac-Toe Game in Python

Hi! Today we will create a Tic-Tac-Toe game with less than 200 lines of Python code, which can be played by one or two players. Don’t underestimate its simplicity; it integrates GUI, events, AI, and state machines. I will guide you through it step by step: starting with the interface, then the logic, followed by AI, and finally packaging and summarizing, ensuring clarity and progression!

1. Overall Overview

Level File/Class Function
L0 <span>081403_tictactoe.py</span> Entry script, starts the Tkinter main loop
L1 <span>TicTacToe</span> class Encapsulates all data and behavior
L2 <span>__init__</span> Initializes the root window and member variables
L2 <span>create_widgets</span> Builds the entire GUI (mode selection + board + status + reset)
L2 <span>make_move</span> Entry point for player moves
L2 <span>computer_move</span> AI move strategy
L2 <span>update_game_state</span> Updates win/loss/draw/turn after a move
L2 <span>check_winner</span> Determines the winner
L2 <span>is_board_full</span> Checks for a draw
L2 <span>reset_game</span> Resets the game

Memory mnemonic: “Entry class, class division; interface logic AI three-legged stool”.

2. Layered Deep Dive

1. Entry Script (L0)

if __name__ == "__main__":
    root = tk.Tk()
    game = TicTacToe(root)
    root.mainloop()
  • Only 4 lines, yet it accomplishes four tasks: “create window → pass root → attach object → run main loop”.
  • Injects <span>root</span> into <span>TicTacToe</span>, making all subsequent controls children of it, ensuring clear hierarchy.

2. Constructor (L2-<span>__init__</span>)

def __init__(self, root):
    self.root = root
    self.root.title("Tic-Tac-Toe Game")
    self.root.resizable(False, False)

    self.board = [" "] * 9          # Board data, one-dimensional list mapping 0~8
    self.current_player = "X"       # Current player
    self.game_mode = 1              # 1 single player 2 two players
    self.buttons = []               # Stores 9 tk.Button instances
    self.create_widgets()           # Set up the interface all at once
  • Member variables have single responsibilities:
    • <span>board</span> stores logic,
    • <span>buttons</span> stores visuals,
    • <span>current_player</span> acts as a state machine.
  • Call chain: entry → <span>__init__</span><span>create_widgets</span>, completing UI initialization in one go.

3. Building the Interface (L2-<span>create_widgets</span>)

# 1. Mode selection
mode_frame = tk.Frame(self.root)
mode_frame.pack(pady=10)
tk.Label(mode_frame, text="Select Game Mode:").pack(side=tk.LEFT, padx=5)
self.mode_var = tk.IntVar(value=1)
tk.Radiobutton(mode_frame, text="Single vs Computer", variable=self.mode_var,
               value=1, command=self.reset_game).pack(side=tk.LEFT)
tk.Radiobutton(mode_frame, text="Two Player", variable=self.mode_var,
               value=2, command=self.reset_game).pack(side=tk.LEFT)

# 2. Board buttons
self.board_frame = tk.Frame(self.root)
self.board_frame.pack(pady=10)
for i in range(9):
    btn = tk.Button(self.board_frame, text="", font=('Arial', 24),
                    width=5, height=2,
                    command=lambda idx=i: self.make_move(idx))
    row, col = i // 3, i % 3
    btn.grid(row=row, column=col, padx=2, pady=2)
    self.buttons.append(btn)

# 3. Status label
self.status_label = tk.Label(self.root, text="Player X's Turn", font=('Arial', 12))
self.status_label.pack(pady=10)

# 4. Reset button
reset_btn = tk.Button(self.root, text="Restart", command=self.reset_game)
reset_btn.pack(pady=10)

# 5. Position instructions
info_frame = tk.Frame(self.root)
info_frame.pack(pady=10)
tk.Label(info_frame, text="Board Position Numbers:").pack()
pos_frame = tk.Frame(info_frame)
pos_frame.pack()
for i in range(9):
    tk.Label(pos_frame, text=str(i + 1), font=('Arial', 8),
             width=3, height=1, borderwidth=1, relief="solid").grid(
        row=i // 3, column=i % 3, padx=1, pady=1)
  • Uses the “Frame nesting” concept:
    • <span>mode_frame</span> manages mode,
    • <span>board_frame</span> manages the board,
    • <span>info_frame</span> manages help.
  • <span>lambda idx=i</span> technique: captures loop variable i in closure to prevent all buttons from sharing the same i.
  • <span>grid</span> row-column calculation: <span>row=i//3</span>, <span>col=i%3</span>, one-dimensional to two-dimensional, very intuitive.

4. Player Move (L2-<span>make_move</span>)

def make_move(self, idx):
    # Boundary check
    if self.board[idx] != " " or self.check_winner() is not None:
        return

    # 1. Update data
    self.board[idx] = self.current_player
    # 2. Update view
    self.buttons[idx].config(text=self.current_player,
                             fg="blue" if self.current_player == "X" else "red")

    # 3. Check for win
    winner = self.check_winner()
    if winner:
        self.status_label.config(text=f"Player {winner} Wins!")
        messagebox.showinfo("Game Over", f"Player {winner} Wins!")
        return

    # 4. Check for draw
    if self.is_board_full():
        self.status_label.config(text="Draw!")
        messagebox.showinfo("Game Over", "Draw!")
        return

    # 5. Switch player
    self.current_player = "O" if self.current_player == "X" else "X"
    self.status_label.config(text=f"Player {self.current_player}'s Turn")

    # 6. AI delay trigger
    if self.mode_var.get() == 1 and self.current_player == "O":
        self.root.after(500, self.computer_move)
  • Six-step pipeline: validate → update data → update view → check win/loss → check draw → switch turn/AI.
  • <span>messagebox.showinfo</span> will block the main thread, preventing user clicks.
  • <span>root.after(500, ...)</span> non-blocking delay, giving the player the illusion that the computer is “thinking”.

5. AI Strategy (L2-<span>computer_move</span>)

def computer_move(self):
    # 1. Win if possible
    for i in range(9):
        if self.board[i] == " ":
            self.board[i] = "O"
            if self.check_winner() == "O":
                self.buttons[i].config(text="O", fg="red")
                self.update_game_state()
                return
            self.board[i] = " " # Backtrack

    # 2. Block if necessary
    for i in range(9):
        if self.board[i] == " ":
            self.board[i] = "X"
            if self.check_winner() == "X":
                self.board[i] = "O"
                self.buttons[i].config(text="O", fg="red")
                self.update_game_state()
                return
            self.board[i] = " "

    # 3. Take center
    if self.board[4] == " ":
        self.board[4] = "O"
        self.buttons[4].config(text="O", fg="red")
        self.update_game_state()
        return

    # 4. Randomly select empty
    available_moves = [i for i, spot in enumerate(self.board) if spot == " "]
    if available_moves:
        move = random.choice(available_moves)
        self.board[move] = "O"
        self.buttons[move].config(text="O", fg="red")
        self.update_game_state()
  • Four-level fallback:
  1. Win (victory check O) →
  2. Block (victory check X) →
  3. Center (tactical point) →
  4. Random fallback.
  • Simulates move effect using “temporary board modification + backtracking” without additional data structures.
  • <span>update_game_state()</span> reuses unified ending logic to avoid code duplication.
  • 6. State Updates and Utility Functions

    6.1 update_game_state

    def update_game_state(self):
        winner = self.check_winner()
        if winner:
            self.status_label.config(text=f"Player {winner} Wins!")
            messagebox.showinfo("Game Over", f"Player {winner} Wins!")
            return
        if self.is_board_full():
            self.status_label.config(text="Draw!")
            messagebox.showinfo("Game Over", "Draw!")
            return
        self.current_player = "X"
        self.status_label.config(text=f"Player {self.current_player}'s Turn")
    
    • Logic is highly similar to that in <span>make_move</span>, but designed specifically for AI calls, not switching O→X but directly returning to X, reflecting “AI turn ends → player’s turn”.

    6.2 check_winner

    def check_winner(self):
        win_combinations = [
            [0, 1, 2], [3, 4, 5], [6, 7, 8],  # Rows
            [0, 3, 6], [1, 4, 7], [2, 5, 8],  # Columns
            [0, 4, 8], [2, 4, 6]              # Diagonals
        ]
        for combo in win_combinations:
            a, b, c = combo
            if self.board[a] == self.board[b] == self.board[c] != " ":
                return self.board[a]
        return None
    
    • Uses a “victory table” to hard-code 8 winning combinations, with clear and readable logic.
    • Time complexity O(1), as it always iterates 8 times.

    6.3 is_board_full

    def is_board_full(self):
        return " " not in self.board
    
    • Pythonic one-liner to check if full.

    6.4 reset_game

    def reset_game(self):
        self.board = [" "] * 9
        self.current_player = "X"
        self.game_mode = self.mode_var.get()
        for btn in self.buttons:
            btn.config(text="", fg="black")
        self.status_label.config(text=f"Player {self.current_player}'s Turn")
    
    • Resets three main components: data, player, view.
    • Each time the radio button is clicked, it also triggers <span>command=self.reset_game</span>, achieving “switch mode and restart immediately”.

    3. Knowledge Points Overview

    Theme Specific Technical Points Code Representation
    GUI Basic tkinter <span>tk.Tk()</span>, <span>Frame</span>, <span>Button</span>, <span>Label</span>, <span>Radiobutton</span>
    Events Callback/command binding <span>command=lambda idx=i: ...</span>
    MVC Data-view separation <span>self.board</span> vs <span>self.buttons</span>
    State Machine Player rotation <span>current_player</span>, <span>game_mode</span>
    AI Minimax prototype Four-level strategy
    Defensive Programming Boundary checks <span>if self.board[idx] != " "</span>
    Code Reuse Function extraction <span>update_game_state</span>, <span>check_winner</span>

    4. Project Goals and Learning Path

    1. Beginner: Able to read and modify. Change the AI strategy to random, or replace X/O icons with emojis.
    2. Intermediate: Introduce the minimax algorithm to make the AI truly “unbeatable”.
    3. Advanced:
    • Expand the board to 4×4/5×5;
    • Use <span>Canvas</span><span> to draw the board;</span>
    • Add online battle (<span>socket</span><span> or </span><code><span>asyncio</span><span>).</span>

    5. Conclusion

    This small project of less than 200 lines is comprehensive:

    • Uses <span>tkinter</span><span> to create an interactive GUI;</span>
    • Implements a prototype of MVC with “data + view” dual arrays;
    • Uses “four-level fallback” to implement lightweight AI;
    • Manages game flow with a “state machine”;
    • Keeps code clean with “function decomposition”.

    By following this article step by step, you not only learned how to write a Tic-Tac-Toe game but also mastered the general approach of “how to break down a requirement into modules and implement them layer by layer”. Have fun and happy coding!

    Click 【Follow + Collect】 to get the latest practical code examples

    Python 20-day learning plan

    7-day learning plan for Python

    Python creative drawing board code

    Python character stroke query tool: from GUI interface to stroke animation implementation

    Python emoji maker code

    Python Chinese chess game code analysis

    Python seal generator implementation

    Python simulation of Jinshan typing software

    Python super useful Markdown to rich text tool – full code analysis

    Python snake game source code analysis

    Python QR code generator implementation

    Python video player implementation

    Python online seal maker implementation

    Python + AI to create a simple smart voice assistant

    Python simple notepad implementation

    Python Markdown to HTML tool code implementation

    Python simple drawing tool code implementation

    Python video player implementation

    Python simple notepad implementation

    Python implementation of the link game code analysis

    Python simple computer process manager implementation

    A super useful tool in Python – word frequency statistics tool

    Python simple web scraper for weather

    Python scheduled task reminder tool

    Python “Guess the Number Game Code Analysis”

    Python “Simple Calculator Code Analysis”

    Python + AI online document generation assistant

    Python “Password Generator Code Analysis”

    Python | + AI to create a simple smart voice assistant

    Python simple drawing tool code implementation

    Python Markdown to HTML implementation

    Python video player implementation

    Python implementation of the link game code analysis

    Python implementation of Huashan AI call to generate stories

    Python implementation of Doubao AI call to generate stories

    Python simple notepad implementation

    Python simple computer process manager implementation

    Practical 1

    1. Python: QR code generator

    2. Python-pgame to implement maze

    3. Python – implement weather clock assistant

    4. Python-QrCode to implement various QR codes

    5. Python-pyglet to implement Hongmeng clock

    6. Python-pickle to parse and get WeChat friend information

    7. Python-wxPy initial version to implement WeChat message bombing

    8. Python to implement the Eight Trigrams starry sky clock

    9. Python to implement the National Day red flag avatar effect

    10. Python-PIL to add icons at specified positions on images

    Practical 2

    1. Python-wxPy initial version to implement WeChat message bombing

    2. Python-PIL library Image class parsing

    3. Python-tlinter to implement a simple student management system

    4. Python-itChat to implement WeChat message push

    5. Python to implement Pdf to Word conversion

    6. Python – implement automatic generation of couplet assistant

    7. Py2Exe another way to package

    8. Python-tts to generate voice conversion assistant

    9. python-win32 etc. to automatically add exe to computer startup options

    10. python to implement desktop video recording

    11. PySimpleGUI-checkboxPython to implement image clipping into a grid

    12. python to package into exe file

    13. Python-faker to generate virtual data

    14. python to implement player Python-FastApi simple implementation

    15. python to scrape Douban movie reviews

    16. Python to scrape public account article collections

    Practical 3

    1. python to implement a simple flower order

    2. python – get the image for guessing idioms

    3. python-menu implementation

    4. Python-pySimpleGUI to implement interface

    5. Python – convert color images to black and white

    6. Python-moviepy – implement audio and video player

    7. Python to operate SQLite database

    8. Python-PySimpleGUI to implement menu

    9. python-Tkinter to implement personalized signature

    10. Python-WordCloud cloud word map

    11. Python-customTkinter usage

    12. Python-tkinter (down)

    13. Python-tkinter (middle)

    14. python-tkinter (1)

    15. Python to implement video assistant

    Practical 4

    1. Python to implement video assistant

    2. Python-flask-1: build main page

    3. Python ttkbootstrap interface

    4. python-PyQt5 to implement image display and simple reader

    5. Configure Qt Designer and Pyuic on Pycharm

    6. Python to implement cropping and generating images of one inch and two inches

    7. Python to scrape Jinshan dictionary query results

    8. python to generate personalized QR codes

    AI human-computer battle version of Gomoku game (AI + pygame implementation)

  • python to implement garbage classification query tool

  • python – implement menu

  • Python field application: automated testing

  • Python field application: Web development

  • Python field application: automated operations

  • Tic-Tac-Toe Game in Python

    Tic-Tac-Toe Game in Python

    Follow the public account below for the latest articlesTic-Tac-Toe Game in Python

    Emperors of the Ming Dynasty – 16: In order as follows:

    1: Ming Taizu Zhu Yuanzhang (Hongwu, 1368–1398)

    Starting with a bowl, ending with a nation: Zhu Yuanzhang’s entrepreneurial history of reversal

    2: Ming Huizong Zhu Yunwen (Jianwen, 1398–1402)

    Jianwen Emperor: The most tragic entrepreneur in history, losing the billion-dollar empire left by his grandfather in four years

    3:Ming Chengzu Zhu Di (Yongle, 1402–1424)

    Zhu Di: From street thug to eternal emperor, how did this usurper become the king of the Ming Dynasty?

    4: Ming Renzong Zhu Gaochi (Hongxi, 1424–1425)

    Zhu Gaochi: The “fat Renzong” of the Ming Dynasty who reigned for ten months, how did he become a great ruler through eating and lying down?

    5:Ming Xuan Zong Zhu Zhanji (Xuan De, 1425–1435)

    Zhu Zhanji: An artist delayed by the throne, if Emperor Xuan De had a social media account

    6:Ming Yingzong Zhu Qizhen (Zheng Tong, 1435–1449; later restored, Tian Shun, 1457–1464)

    Ming Yingzong Zhu Qizhen: The first emperor to go from emperor to captive and then back to power

    7: Ming Daizong Zhu Qiyu (Jingtai, 1449–1457)

    Ming Daizong Zhu Qiyu: From prince to CEO: the throne that fell from the sky

    8:Ming Xian Zong Zhu Jian Shen (Chenghua, 1464–1487)

    Ming Xian Zong Zhu Jian Shen: The multifaceted emperor of a legendary life

    9: Ming Xiao Zong Zhu Youzhuang (Hongzhi, 1487–1505)

    Ming Xiao Zong Zhu Youzhuang: The warmest emperor of the Ming Dynasty’s reversal script

    10:Ming Wu Zong Zhu Houzhao (Zhengde, 1505–1521)

    Ming Wu Zong Zhu Houzhao: The entertainment blogger delayed by the throne

    11: Ming Shi Zong Zhu Houxuan (Jiajing, 1521–1566)

    Ming Shi Zong Zhu Houxuan: The power game in the alchemy furnace – the absurd entrepreneurial history of the Ming Dynasty’s immortal CEO

    12:Ming Mu Zong Zhu Zaiqi (Longqing, 1566–1572)

    Ming Mu Zong Zhu Zaiqi: The economic reformer delayed by the throne

    13: Ming Shen Zong Zhu Yijun (Wanli, 1572–1620)

    Ming Shen Zong Zhu Yijun: The “homebody emperor” buried in memorials

    14:Ming Guang Zong Zhu Changluo (Taichang, 1620, only one month)

    One-month emperor Zhu Changluo: The roller coaster of a 30-day reign

    15: Ming Xi Zong Zhu Youjiao (Tianqi, 1620–1627)

    Ming Xi Zong Zhu Youjiao: The “Lu Ban” emperor delayed by the throne

    16: Ming Si Zong Zhu Youjian (Chongzhen, 1627–1644)

    Chongzhen Zhu Youjian: A “fallen nation CEO” tragedy of KPI

    Note:

    Ming Yingzong reigned twice (Zheng Tong, Tian Shun), replaced in between by his brother Ming Daizong.

    The Southern Ming regime (such as Hongguang Emperor, etc.) is not considered legitimate Ming Dynasty emperors.

    Legendary Story Series

    The Great Tang Criminal Investigation Record: When Di Renjie Meets the Theatrical Water Bandit

    Go Determines Lifelong: How the Chess God of the Song Dynasty Won the First Female Chess Child of Liao with Two Games

    Half a Gold Box Marriage Fraud: How a Scholar of the Ming Dynasty Became a Son-in-law of a Wealthy Family with Antiques

    Incense Pilgrims Recklessly Read the Diamond Sutra: A Hand-Copied Manuscript from the Tang Dynasty Leads to a Political Revelation

    Ancient Version of “Sweeping Black Wind”: Unveiling the Strange Cases in Volume Four of “Two Eras of Surprises”

    Du Shiniang Angrily Sinks the Treasure Chest: The Tragedy and Survival Insights of an Ancient Socialite with “Love Brain”

    When the Roll King Meets the Virgin: The Blood-Stained Friendship of the Han Dynasty Version of “China Partner”

    From “Naked Resignation to Save a Friend” to “Ten Years of Debt Repayment”: The Ceiling of Loyalty for Tang Dynasty Workers

    From “Starving to Death” to “Prime Minister’s Fate”: The Reversal of Life in the Tang Dynasty Version of “Counterattack Star Path”

    From Pancake Seller to Prime Minister of the Tang Dynasty: How High is the Investment Return Rate of This Aunt Selling Pancakes?

    When the Abstinent General Meets the Love-Brain Bodyguard: The Blood-Stained Romance of the Five Dynasties Version of “Yanxi Strategy”

    Ming Dynasty “Immortal Jump” Record: The Bloody Entanglement of the Rich Second Generation and the Green Tea Bitch

    Gold Hairpin Blood Case: The Reversal of the Ming Dynasty’s Son-in-law, the Green Tea Cousin Turned Out to Be the Ultimate Boss?

    Did the Wrong Question Book Harm Him? A Ming Dynasty Scholar Missed the Top Scholar Due to a Typo, but Found a Provincial Governor in a Tea House

    Leave a Comment