介绍
本项目将指导你完成使用 Pygame 创建井字棋游戏的步骤。井字棋是一款双人游戏,目标是让你的三个符号在水平、垂直或对角线上连成一排。在本项目中,你将学习如何设置游戏窗口、绘制游戏棋盘、处理玩家和 AI 的移动以及确定获胜者。在本项目结束时,你将拥有一个功能齐全的井字棋游戏,可以与 AI 对手对战。
👀 预览

🎯 任务
在本项目中,你将学习:
- 如何创建项目文件并导入必要的库
- 如何初始化 PyGame 并设置游戏窗口
- 如何定义符号、颜色和游戏状态
- 如何定义按钮属性并创建辅助函数
- 如何创建主游戏循环并实现辅助函数
- 如何在主游戏循环中填充其余代码
🏆 成果
完成本项目后,你将能够:
- 使用 Pygame 创建图形化游戏
- 使用 Pygame 在窗口上绘制图形
- 处理用户输入并更新游戏状态
- 实现游戏逻辑,如检查获胜条件
- 创建游戏循环以保持游戏运行
创建项目文件
首先,创建一个名为 tic_tac_toe.py 的新文件。在你喜欢的文本编辑器中打开该文件。
cd ~/project
touch tic_tac_toe.py
导入必要的库
在 tic_tac_toe.py 中,导入必要的库:pygame 和 random。这些库将分别用于处理游戏图形和生成随机的 AI 移动。
import pygame
import random
使用以下命令安装 pygame 库:
sudo pip install pygame
初始化 PyGame 并设置游戏窗口
在 tic_tac_toe.py 中,使用 pygame.init() 初始化 PyGame。然后,通过定义窗口宽度和高度、背景颜色、线条颜色以及单元格大小来设置游戏窗口。此外,创建一个具有指定宽度和高度的 PyGame 窗口,并设置窗口标题。
pygame.init()
WIDTH = 600
HEIGHT = 600
BACKGROUND_COLOR = (40, 40, 40)
LINE_COLOR = (70, 70, 70)
CELL_SIZE = WIDTH // 3
win = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Tic-Tac-Toe")
定义符号和颜色
在 tic_tac_toe.py 中,定义玩家和 AI 的符号及颜色。这些符号和颜色将用于在游戏棋盘上绘制玩家和 AI 的落子。
PLAYER_SYMBOL = "X"
AI_SYMBOL = "O"
PLAYER_COLOR = (0, 255, 0)
AI_COLOR = (255, 0, 0)
EMPTY_COLOR = (0, 0, 0)
定义游戏状态
在 tic_tac_toe.py 中,定义初始游戏状态。这包括游戏棋盘、当前轮到谁(“玩家”或“AI”)、一个表示游戏是否结束的标志,以及游戏的获胜者。
board = [["" for _ in range(3)] for _ in range(3)]
turn = "player"
game_over = False
winner = None
定义按钮属性
在 tic_tac_toe.py 中,定义重置按钮的属性,包括按钮宽度、高度、颜色、文本颜色和字体大小。此外,使用 pygame.Rect 类创建一个 reset_button_rect 对象,以表示按钮的位置和大小。
BUTTON_WIDTH = 200
BUTTON_HEIGHT = 50
BUTTON_COLOR = (50, 50, 50)
BUTTON_TEXT_COLOR = (255, 255, 255)
BUTTON_FONT = pygame.font.Font(None, 30)
reset_button_rect = pygame.Rect(
(WIDTH - BUTTON_WIDTH) // 2,
(HEIGHT - BUTTON_HEIGHT) // 2,
BUTTON_WIDTH,
BUTTON_HEIGHT,
)
创建辅助函数
在 tic_tac_toe.py 中,定义几个在整个游戏中都会用到的辅助函数。
draw_board():此函数将在窗口上绘制游戏棋盘。draw_symbols():此函数将在游戏棋盘上绘制玩家和 AI 的符号。is_board_full():此函数将检查游戏棋盘是否已满。is_winner():此函数将检查是否有玩家赢得了游戏。make_move():此函数将在游戏棋盘上进行一步操作。player_move():此函数将处理玩家的操作。ai_move():此函数将处理 AI 的操作。check_game_over():此函数将检查游戏是否结束。draw_winner():此函数将在窗口上绘制获胜者消息。draw_reset_button():此函数将在窗口上绘制重置按钮。reset_game():此函数将重置游戏状态。
## 辅助函数
def draw_board():
## 绘制游戏棋盘
pass
def draw_symbols():
## 在游戏棋盘上绘制玩家和 AI 的符号
pass
def is_board_full():
## 检查游戏棋盘是否已满
pass
def is_winner(symbol):
## 检查是否有玩家赢得了游戏
pass
def make_move(x, y, symbol):
## 在游戏棋盘上进行一步操作
pass
def player_move():
## 处理玩家的操作
pass
def ai_move():
## 处理 AI 的操作
pass
def check_game_over():
## 检查游戏是否结束
pass
def draw_winner():
## 在窗口上绘制获胜者消息
pass
def draw_reset_button():
## 在窗口上绘制重置按钮
pass
def reset_game():
## 重置游戏状态
pass
创建主游戏循环
在 tic_tac_toe.py 中,使用 while 循环创建主游戏循环。这个循环会一直运行,直到用户关闭游戏窗口。在游戏循环内部,处理用户的输入事件并相应地更新游戏状态。
## 主游戏循环
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
if reset_button_rect.collidepoint(event.pos):
reset_game()
elif not game_over and turn == "player":
player_move()
if not game_over and turn == "ai":
ai_move()
check_game_over()
draw_board()
draw_symbols()
if game_over:
draw_winner()
draw_reset_button()
pygame.display.flip()
## 退出游戏
pygame.quit()
实现辅助函数
现在,让我们实现之前定义的辅助函数。首先完成 draw_board() 函数。这个函数将通过使用 pygame.draw.line() 函数绘制垂直线和水平线,在窗口上绘制游戏棋盘。
## 辅助函数
def draw_board():
win.fill(BACKGROUND_COLOR)
## 绘制垂直线
for x in range(1, 3):
pygame.draw.line(
win, LINE_COLOR, (CELL_SIZE * x, 0), (CELL_SIZE * x, HEIGHT), 2
)
## 绘制水平线
for y in range(1, 3):
pygame.draw.line(win, LINE_COLOR, (0, CELL_SIZE * y), (WIDTH, CELL_SIZE * y), 2)
实现其余辅助函数
接下来,实现其余的辅助函数:draw_symbols()、is_board_full()、is_winner()、make_move()、player_move()、ai_move()、check_game_over()、draw_winner()、draw_reset_button() 和 reset_game()。
## 辅助函数
def draw_symbols():
for x in range(3):
for y in range(3):
symbol = board[x][y]
if symbol == PLAYER_SYMBOL:
color = PLAYER_COLOR
elif symbol == AI_SYMBOL:
color = AI_COLOR
else:
color = EMPTY_COLOR
if symbol!= "":
pygame.draw.circle(
win,
color,
(x * CELL_SIZE + CELL_SIZE // 2, y * CELL_SIZE + CELL_SIZE // 2),
CELL_SIZE // 2 - 10,
2,
)
def is_board_full():
for row in board:
if "" in row:
return False
return True
def is_winner(symbol):
for row in board:
if all(cell == symbol for cell in row):
return True
for col in range(3):
if all(board[row][col] == symbol for row in range(3)):
return True
if all(board[i][i] == symbol for i in range(3)):
return True
if all(board[i][2 - i] == symbol for i in range(3)):
return True
return False
def make_move(x, y, symbol):
if board[x][y] == "":
board[x][y] = symbol
return True
return False
def player_move():
global turn
mouse_pos = pygame.mouse.get_pos()
cell_x = mouse_pos[0] // CELL_SIZE
cell_y = mouse_pos[1] // CELL_SIZE
if make_move(cell_x, cell_y, PLAYER_SYMBOL):
turn = "ai"
def ai_move():
global turn
empty_cells = []
for x in range(3):
for y in range(3):
if board[x][y] == "":
empty_cells.append((x, y))
if empty_cells:
x, y = random.choice(empty_cells)
make_move(x, y, AI_SYMBOL)
turn = "player"
def check_game_over():
global game_over, winner
if is_winner(PLAYER_SYMBOL):
game_over = True
return "player"
elif is_winner(AI_SYMBOL):
game_over = True
return "ai"
elif is_board_full():
game_over = True
return "tie"
return None
def draw_winner():
font = pygame.font.Font(None, 50)
if winner == "player":
text = font.render("玩家获胜!", True, PLAYER_COLOR)
elif winner == "ai":
text = font.render("AI 获胜!", True, AI_COLOR)
else:
text = font.render("平局!", True, (255, 255, 255))
text_rect = text.get_rect(center=(WIDTH // 2, HEIGHT // 3))
win.blit(text, text_rect)
def draw_reset_button():
pygame.draw.rect(win, BUTTON_COLOR, reset_button_rect)
button_text = BUTTON_FONT.render("重置", True, BUTTON_TEXT_COLOR)
button_text_rect = button_text.get_rect(center=reset_button_rect.center)
win.blit(button_text, button_text_rect)
def reset_game():
global board, turn, game_over, winner
board = [["" for _ in range(3)] for _ in range(3)]
turn = "玩家"
game_over = False
winner = None
在上述代码中,draw_symbols() 函数将在棋盘上绘制符号。is_board_full() 函数将检查棋盘是否已满。is_winner() 函数将检查给定符号是否赢得了游戏。make_move() 函数将在棋盘上进行一步操作。player_move() 函数将处理玩家的操作。ai_move() 函数将处理 AI 的操作。check_game_over() 函数将检查游戏是否结束。draw_winner() 函数将绘制获胜者消息。draw_reset_button() 函数将绘制重置按钮。reset_game() 函数将重置游戏。
填充剩余代码
最后,在主游戏循环中补全剩余代码,以便在适当的位置调用辅助函数。这包括调用 draw_board() 和 draw_symbols() 函数来绘制游戏棋盘和符号,调用 check_game_over() 函数来检查游戏是否结束,以及分别调用 draw_winner() 和 draw_reset_button() 函数来绘制获胜者消息和重置按钮。
## 主游戏循环
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
if reset_button_rect.collidepoint(event.pos):
reset_game()
elif not game_over and turn == "player":
player_move()
if not game_over and turn == "ai":
ai_move()
winner = check_game_over()
draw_board()
draw_symbols()
if game_over:
draw_winner()
draw_reset_button()
pygame.display.flip()
## 退出游戏
pygame.quit()
使用以下命令运行游戏:
python tic_tac_toe.py

总结
恭喜你!你已经成功使用 Pygame 创建了一个井字棋游戏。在这个项目中,你学习了如何设置游戏窗口、绘制游戏棋盘、处理玩家和 AI 的移动以及确定获胜者。你还学习了如何实现辅助函数来简化代码并使其更具模块化。



