Build a Classic Gobang Game with Python Tkinter – Step‑by‑Step Tutorial
This article walks you through creating a fully functional Gobang (Five‑in‑a‑Row) game using Python's Tkinter library, covering GUI setup, board rendering, game logic, win detection, undo and reset features, and provides the complete source code ready to run.
This tutorial demonstrates how to implement a basic Gobang (Five‑in‑a‑Row) game for beginners using Python and the Tkinter GUI toolkit.
Setup and Style Creation
First, import the required packages and define a chessBoard class that creates the main window, sets its size, disables resizing, and draws the board grid and initial stones.
''
@Auther : gaoxin
@Date : 2019.01.01
@Version : 1.0
''
from tkinter import *
import math
# Define chess board class
class chessBoard():
def __init__(self):
self.window = Tk()
self.window.title("五子棋游戏")
self.window.geometry("660x470")
self.window.resizable(0, 0)
self.canvas = Canvas(self.window, bg="#EEE8AC", width=470, height=470)
self.paint_board()
self.canvas.grid(row=0, column=0)
def paint_board(self):
# Draw horizontal lines
for row in range(0, 15):
if row == 0 or row == 14:
self.canvas.create_line(25, 25 + row * 30, 25 + 14 * 30, 25 + row * 30, width=2)
else:
self.canvas.create_line(25, 25 + row * 30, 25 + 14 * 30, 25 + row * 30, width=1)
# Draw vertical lines
for column in range(0, 15):
if column == 0 or column == 14:
self.canvas.create_line(25 + column * 30, 25, 25 + column * 30, 25 + 14 * 30, width=2)
else:
self.canvas.create_line(25 + column * 30, 25, 25 + column * 30, 25 + 14 * 30, width=1)
# Draw corner points
self.canvas.create_oval(112, 112, 118, 118, fill="black")
self.canvas.create_oval(352, 112, 358, 118, fill="black")
self.canvas.create_oval(112, 352, 118, 358, fill="black")
self.canvas.create_oval(232, 232, 238, 238, fill="black")
self.canvas.create_oval(352, 352, 358, 358, fill="black")Game Logic Implementation
The Gobang class encapsulates the game state, including the board matrix, move order, current player color, and flags for win/empty status. It provides methods for switching colors, handling mouse clicks to place stones, boundary checks, counting consecutive stones, win detection, undoing moves, clearing the board, and starting a new game.
# Define Gobang game class
# 0 = black stone, 1 = white stone, 2 = empty
class Gobang():
def __init__(self):
self.board = chessBoard()
self.game_print = StringVar()
self.game_print.set("")
# 16x16 board to avoid index errors
self.db = [([2] * 16) for i in range(16)]
self.order = []
self.color_count = 0
self.color = 'black'
self.flag_win = 1
self.flag_empty = 1
self.options()
# Switch between black and white
def change_color(self):
self.color_count = (self.color_count + 1) % 2
if self.color_count == 0:
self.color = "black"
elif self.color_count == 1:
self.color = "white"
# Handle mouse click to place a stone
def chess_moving(self, event):
if self.flag_win == 1 or self.flag_empty == 0:
return
x, y = event.x - 25, event.y - 25
x = round(x / 30)
y = round(y / 30)
while self.db[y][x] == 2 and self.limit_boarder(y, x):
self.db[y][x] = self.color_count
self.order.append(x + 15 * y)
self.board.canvas.create_oval(25 + 30 * x - 12, 25 + 30 * y - 12,
25 + 30 * x + 12, 25 + 30 * y + 12,
fill=self.color, tags="chessman")
if self.game_win(y, x, self.color_count):
print(self.color, "获胜")
self.game_print.set(self.color + "获胜")
else:
self.change_color()
self.game_print.set("请" + self.color + "落子")
# Ensure the click is inside the board
def limit_boarder(self, y, x):
if x < 0 or x > 14 or y < 0 or y > 14:
return False
else:
return True
# Count consecutive stones in all directions
def chessman_count(self, y, x, color_count):
count1 = count2 = count3 = count4 = 1
# Horizontal
for i in range(-1, -5, -1):
if self.db[y][x + i] == color_count:
count1 += 1
else:
break
for i in range(1, 5, 1):
if self.db[y][x + i] == color_count:
count1 += 1
else:
break
# Vertical
for i in range(-1, -5, -1):
if self.db[y + i][x] == color_count:
count2 += 1
else:
break
for i in range(1, 5, 1):
if self.db[y + i][x] == color_count:
count2 += 1
else:
break
# Diagonal \
for i in range(-1, -5, -1):
if self.db[y + i][x + i] == color_count:
count3 += 1
else:
break
for i in range(1, 5, 1):
if self.db[y + i][x + i] == color_count:
count3 += 1
else:
break
# Diagonal /
for i in range(-1, -5, -1):
if self.db[y + i][x - i] == color_count:
count4 += 1
else:
break
for i in range(1, 5, 1):
if self.db[y + i][x - i] == color_count:
count4 += 1
else:
break
return max(count1, count2, count3, count4)
# Determine if the current move wins the game
def game_win(self, y, x, color_count):
if self.chessman_count(y, x, color_count) >= 5:
self.flag_win = 1
self.flag_empty = 0
return True
else:
return False
# Undo the last move
def withdraw(self):
if len(self.order) == 0 or self.flag_win == 1:
return
self.board.canvas.delete("chessman")
z = self.order.pop()
x = z % 15
y = z // 15
self.db[y][x] = 2
self.color_count = 1
for i in self.order:
ix = i % 15
iy = i // 15
self.change_color()
self.board.canvas.create_oval(25 + 30 * ix - 12, 25 + 30 * iy - 12,
25 + 30 * ix + 12, 25 + 30 * iy + 12,
fill=self.color, tags="chessman")
self.change_color()
self.game_print.set("请" + self.color + "落子")
# Clear the board
def empty_all(self):
self.board.canvas.delete("chessman")
self.db = [([2] * 16) for i in range(16)]
self.order = []
self.color_count = 0
self.color = 'black'
self.flag_win = 1
self.flag_empty = 1
self.game_print.set("")
# Start a new game
def game_start(self):
if self.flag_empty == 0:
return
self.flag_win = 0
self.game_print.set("请" + self.color + "落子")
# Bind events and add control buttons
def options(self):
self.board.canvas.bind("<Button-1>", self.chess_moving)
Label(self.board.window, textvariable=self.game_print, font=("Arial", 20)).place(relx=0, rely=0, x=495, y=200)
Button(self.board.window, text="开始游戏", command=self.game_start, width=13, font=("Verdana", 12)).place(relx=0, rely=0, x=495, y=15)
Button(self.board.window, text="我要悔棋", command=self.withdraw, width=13, font=("Verdana", 12)).place(relx=0, rely=0, x=495, y=60)
Button(self.board.window, text="清空棋局", command=self.empty_all, width=13, font=("Verdana", 12)).place(relx=0, rely=0, x=495, y=105)
Button(self.board.window, text="结束游戏", command=self.board.window.destroy, width=13, font=("Verdana", 12)).place(relx=0, rely=0, x=495, y=420)
self.board.window.mainloop()
if __name__ == "__main__":
game = Gobang()Running the Program
Copy all the code above into a single Python file and execute it. The GUI window will appear, allowing you to start a new game, place black and white stones by clicking on the board, undo moves, clear the board, and end the session.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
