I recently made this tic-tac-toe program using tkinter, but I am quite new to tkinter, so I would be grateful for tips on how to improve the program. Note that the actual tic-tac-toe logic is being done by the python-tictactoe library.
This is my code:
import tkinter as tk
from tictactoe import Board
from tictactoe import X, O
root = tk.Tk()
root.geometry("400x400")
frame = tk.Frame(root, bg="white")
frame.pack()
board = Board()
def convert_to_str(player):
return "X" if player == X else "O"
def push(i):
pos = ((i + 1) % 3, i // 3)
if board.is_empty(pos) and board.result() is None:
squares[i].config(text=convert_to_str(board.turn))
board.push(pos)
# if there is a winner (use bool, because a draw is 0; so True only if board.result is 1 or 2)
if bool(board.result()):
for square in squares:
if square.cget("text") == convert_to_str(board.result()):
square.config(bg="green", fg="gold")
# if it is a draw
elif board.result() == 0:
for square in squares:
square.config(bg="yellow")
squares = [tk.Button(frame, text=" ", font=("Courier", 50), bg="white", command=lambda i=i: push(i)) for i in range(9)]
for i, square in enumerate(squares):
square.grid(row=(i + 1) % 3, column=i // 3)
tk.mainloop()
This is what it looks like:
GUI:
An image of the tkinter window
Win:
An image of the tkinter window where X has won
Draw:
-
1\$\begingroup\$ For a win wouldn't it be better if you only use the green background on the 3 squares that constituted the win? \$\endgroup\$Booboo– Booboo2023年10月10日 11:41:15 +00:00Commented Oct 10, 2023 at 11:41
1 Answer 1
Layout
Move the functions to top after the import
lines.
Having them in the middle of the code interrupts the natural flow of the
code (from a human readability standpoint).
Imports
Since O
is not used in the code, there is no need to import it. Change:
from tictactoe import Board
from tictactoe import X, O
to:
from tictactoe import Board, X
Documentation
Add a doctring at the top of the file to summarize the purpose of the code:
"""
tic-tac-toe game using tkinter.
The user plays against self.
"""
Instructions
Add instructions for the user in the GUI window. For example:
Tic-tac-toe game
For the 1st move, click in a square to add an X.
For the 2nd move, click in another square to add an O.
Etc.
Long line
Long lines of code like the following can be hard to read and maintain:
squares = [tk.Button(frame, text=" ", font=("Courier", 50), bg="white", command=lambda i=i: push(i)) for i in range(9)]
You could use the black program to automatically format the line:
squares = [
tk.Button(
frame, text=" ", font=("Courier", 50), bg="white", command=lambda i=i: push(i)
)
for i in range(9)
]
Naming
The following function name and variable are not very descriptive:
def push(i):
It looks like the function updates the board and checks the result. Perhaps a name like the following would be better:
def update_and_check_result(i):
Also, add a docstring to summarize the purpose if the function and to describe the input variable (expected range, etc.).
Explore related questions
See similar questions with these tags.