python 五子棋游戏
pip install pygameimport pygame import sys from pygame import gfxdraw class GomokuGame: def __init__(self): pygame.init() # 游戏配置 self.BOARD_SIZE 15 self.CELL_SIZE 35 self.MARGIN 40 self.BOARD_PIXEL_SIZE (self.BOARD_SIZE - 1) * self.CELL_SIZE self.WINDOW_WIDTH self.BOARD_PIXEL_SIZE 2 * self.MARGIN self.WINDOW_HEIGHT self.BOARD_PIXEL_SIZE 2 * self.MARGIN 30 # 颜色配置 self.COLORS { background: (250, 248, 240), # 浅米色背景 board: (220, 190, 140), # 浅木纹色棋盘 line: (100, 80, 60), # 棋盘线颜色 black_piece: (30, 30, 30), # 黑棋颜色 white_piece: (245, 245, 245), # 白棋颜色 highlight: (255, 215, 0), # 高亮颜色 button_normal: (100, 140, 180), # 按钮正常颜色 button_hover: (70, 110, 150), # 按钮悬停颜色 button_text: (255, 255, 255), # 按钮文字颜色 text: (50, 50, 50), win_line: (255, 69, 0) # 胜利线颜色 } # 创建窗口 self.screen pygame.display.set_mode((self.WINDOW_WIDTH, self.WINDOW_HEIGHT)) pygame.display.set_caption(五子棋 - Gomoku) # 游戏状态 self.board [[0 for _ in range(self.BOARD_SIZE)] for _ in range(self.BOARD_SIZE)] self.current_player 1 # 1: 黑棋, 2: 白棋 self.game_over False self.winner None self.win_line [] self.last_move None # AI 模式 self.ai_mode False # 历史记录用于悔棋 self.move_history [] # 初始化字体支持中文 self.init_fonts() # 按钮 button_y self.BOARD_PIXEL_SIZE self.MARGIN 20 button_width 100 button_height 35 button_spacing 15 total_button_width 4 * button_width 3 * button_spacing start_x (self.WINDOW_WIDTH - total_button_width) // 2 self.buttons [ {text: 重新开始, rect: pygame.Rect(start_x, button_y, button_width, button_height), action: restart}, {text: AI: 关, rect: pygame.Rect(start_x button_width button_spacing, button_y, button_width, button_height), action: toggle_ai}, {text: 悔棋, rect: pygame.Rect(start_x 2 * (button_width button_spacing), button_y, button_width, button_height), action: undo}, {text: 退出, rect: pygame.Rect(start_x 3 * (button_width button_spacing), button_y, button_width, button_height), action: quit} ] def init_fonts(self): 初始化支持中文的字体 # 尝试多种中文字体 font_names [ microsoftyahei, # 微软雅黑 simsun, # 宋体 simhei, # 黑体 kaiti, # 楷体 Arial Unicode MS, None # 默认字体 ] self.font_large None self.font_medium None self.font_small None for font_name in font_names: try: if font_name: self.font_large pygame.font.SysFont(font_name, 32) self.font_medium pygame.font.SysFont(font_name, 24) self.font_small pygame.font.SysFont(font_name, 18) else: self.font_large pygame.font.Font(None, 32) self.font_medium pygame.font.Font(None, 24) self.font_small pygame.font.Font(None, 18) # 测试字体是否能渲染中文 test_surface self.font_medium.render(测试, True, (0, 0, 0)) if test_surface.get_width() 10: # 如果宽度合理说明字体支持中文 break except: continue # 如果所有字体都失败使用默认字体 if self.font_large is None: self.font_large pygame.font.Font(None, 32) self.font_medium pygame.font.Font(None, 24) self.font_small pygame.font.Font(None, 18) def draw_board(self): 绘制棋盘 # 绘制背景 self.screen.fill(self.COLORS[background]) # 绘制棋盘底座带圆角和阴影 board_rect pygame.Rect( self.MARGIN - 15, self.MARGIN - 15, self.BOARD_PIXEL_SIZE 30, self.BOARD_PIXEL_SIZE 30 ) # 绘制阴影 shadow_rect board_rect.copy() shadow_rect.x 4 shadow_rect.y 4 pygame.draw.rect(self.screen, (180, 160, 120), shadow_rect, border_radius8) # 绘制棋盘主体 pygame.draw.rect(self.screen, self.COLORS[board], board_rect, border_radius8) # 绘制网格线 for i in range(self.BOARD_SIZE): # 横线 start_pos (self.MARGIN, self.MARGIN i * self.CELL_SIZE) end_pos (self.MARGIN self.BOARD_PIXEL_SIZE, self.MARGIN i * self.CELL_SIZE) pygame.draw.line(self.screen, self.COLORS[line], start_pos, end_pos, 1) # 竖线 start_pos (self.MARGIN i * self.CELL_SIZE, self.MARGIN) end_pos (self.MARGIN i * self.CELL_SIZE, self.MARGIN self.BOARD_PIXEL_SIZE) pygame.draw.line(self.screen, self.COLORS[line], start_pos, end_pos, 1) # 绘制天元和星位 star_positions [(3, 3), (11, 3), (7, 7), (3, 11), (11, 11)] for x, y in star_positions: center_x self.MARGIN x * self.CELL_SIZE center_y self.MARGIN y * self.CELL_SIZE pygame.draw.circle(self.screen, self.COLORS[line], (center_x, center_y), 4) def draw_pieces(self): 绘制棋子 for i in range(self.BOARD_SIZE): for j in range(self.BOARD_SIZE): if self.board[i][j] ! 0: x self.MARGIN j * self.CELL_SIZE y self.MARGIN i * self.CELL_SIZE # 棋子颜色 if self.board[i][j] 1: piece_color self.COLORS[black_piece] outline_color (60, 60, 60) else: piece_color self.COLORS[white_piece] outline_color (200, 200, 200) # 绘制棋子带阴影 shadow_offset 2 shadow_pos (x shadow_offset, y shadow_offset) pygame.draw.circle(self.screen, (120, 110, 90), shadow_pos, self.CELL_SIZE // 2 - 3) # 绘制棋子 pygame.draw.circle(self.screen, piece_color, (x, y), self.CELL_SIZE // 2 - 2) pygame.draw.circle(self.screen, outline_color, (x, y), self.CELL_SIZE // 2 - 2, 2) # 绘制高光效果 if self.board[i][j] 1: # 黑棋高光 highlight_pos (x - self.CELL_SIZE // 8, y - self.CELL_SIZE // 8) pygame.draw.circle(self.screen, (90, 90, 90), highlight_pos, self.CELL_SIZE // 8) else: # 白棋高光 highlight_pos (x - self.CELL_SIZE // 8, y - self.CELL_SIZE // 8) pygame.draw.circle(self.screen, (255, 255, 255), highlight_pos, self.CELL_SIZE // 8) # 高亮最后一步 if self.last_move: x self.MARGIN self.last_move[1] * self.CELL_SIZE y self.MARGIN self.last_move[0] * self.CELL_SIZE pygame.draw.circle(self.screen, self.COLORS[highlight], (x, y), 4) def draw_win_line(self): 绘制胜利连线 if self.win_line: for i in range(len(self.win_line) - 1): start self.win_line[i] end self.win_line[i 1] start_x self.MARGIN start[1] * self.CELL_SIZE start_y self.MARGIN start[0] * self.CELL_SIZE end_x self.MARGIN end[1] * self.CELL_SIZE end_y self.MARGIN end[0] * self.CELL_SIZE pygame.draw.line(self.screen, self.COLORS[win_line], (start_x, start_y), (end_x, end_y), 5) def draw_ui(self): 绘制用户界面 # 绘制当前玩家提示 if not self.game_over: player_text 黑棋 if self.current_player 1 else 白棋 player_color self.COLORS[black_piece] if self.current_player 1 else self.COLORS[white_piece] text f当前玩家: {player_text} text_surface self.font_medium.render(text, True, player_color) self.screen.blit(text_surface, (self.WINDOW_WIDTH // 2 - text_surface.get_width() // 2, 10)) else: if self.winner: winner_text 黑棋 if self.winner 1 else 白棋 text f{winner_text}获胜! text_surface self.font_large.render(text, True, self.COLORS[win_line]) else: text 平局! text_surface self.font_large.render(text, True, self.COLORS[text]) self.screen.blit(text_surface, (self.WINDOW_WIDTH // 2 - text_surface.get_width() // 2, 10)) # 绘制按钮 mouse_pos pygame.mouse.get_pos() for button in self.buttons: rect button[rect] if rect.collidepoint(mouse_pos): color self.COLORS[button_hover] else: color self.COLORS[button_normal] # 绘制按钮阴影 shadow_rect rect.copy() shadow_rect.x 2 shadow_rect.y 2 pygame.draw.rect(self.screen, (100, 100, 100), shadow_rect, border_radius6) # 绘制按钮主体 pygame.draw.rect(self.screen, color, rect, border_radius6) # 绘制按钮文字 text_surface self.font_small.render(button[text], True, self.COLORS[button_text]) text_rect text_surface.get_rect(centerrect.center) self.screen.blit(text_surface, text_rect) def is_valid_move(self, row, col): 检查移动是否有效 return 0 row self.BOARD_SIZE and 0 col self.BOARD_SIZE and self.board[row][col] 0 def make_move(self, row, col): 落子 if self.is_valid_move(row, col): self.board[row][col] self.current_player self.last_move (row, col) self.move_history.append((row, col, self.current_player)) # 记录历史 # 检查胜利 if self.check_win(row, col): self.game_over True self.winner self.current_player elif self.is_board_full(): self.game_over True self.winner None else: # 切换玩家 self.current_player 3 - self.current_player # AI 模式下如果轮到白棋则AI下棋 if self.ai_mode and self.current_player 2 and not self.game_over: pygame.display.flip() pygame.time.wait(300) self.ai_move() return True return False def check_win(self, row, col): 检查是否胜利 player self.board[row][col] directions [ [(0, 1), (0, -1)], # 水平 [(1, 0), (-1, 0)], # 垂直 [(1, 1), (-1, -1)], # 对角线 [(1, -1), (-1, 1)] # 反对角线 ] for direction in directions: count 1 line_positions [(row, col)] for d in direction: dr, dc d new_row, new_col row dr, col dc while (0 new_row self.BOARD_SIZE and 0 new_col self.BOARD_SIZE and self.board[new_row][new_col] player): count 1 line_positions.append((new_row, new_col)) new_row dr new_col dc if count 5: self.win_line line_positions return True return False def is_board_full(self): 检查棋盘是否已满 return all(self.board[i][j] ! 0 for i in range(self.BOARD_SIZE) for j in range(self.BOARD_SIZE)) def get_valid_moves(self): 获取所有有效移动 valid_moves [] for i in range(self.BOARD_SIZE): for j in range(self.BOARD_SIZE): if self.board[i][j] 0: # 只考虑有邻居的位置 if self.has_neighbor(i, j): valid_moves.append((i, j)) return valid_moves def has_neighbor(self, row, col): 检查是否有邻居棋子 if self.is_board_empty(): return True for dr in [-2, -1, 0, 1, 2]: for dc in [-2, -1, 0, 1, 2]: if dr 0 and dc 0: continue nr, nc row dr, col dc if (0 nr self.BOARD_SIZE and 0 nc self.BOARD_SIZE and self.board[nr][nc] ! 0): return True return False def is_board_empty(self): 检查棋盘是否为空 return all(self.board[i][j] 0 for i in range(self.BOARD_SIZE) for j in range(self.BOARD_SIZE)) def evaluate_position(self, row, col, player): 评估某个位置的分数 score 0 directions [ (0, 1), # 水平 (1, 0), # 垂直 (1, 1), # 对角线 (1, -1) # 反对角线 ] for dr, dc in directions: # 连续棋子数 count 0 open_ends 0 # 正方向 for step in range(1, 5): nr, nc row dr * step, col dc * step if not (0 nr self.BOARD_SIZE and 0 nc self.BOARD_SIZE): break if self.board[nr][nc] player: count 1 elif self.board[nr][nc] 0: open_ends 1 break else: break # 反方向 for step in range(1, 5): nr, nc row - dr * step, col - dc * step if not (0 nr self.BOARD_SIZE and 0 nc self.BOARD_SIZE): break if self.board[nr][nc] player: count 1 elif self.board[nr][nc] 0: open_ends 1 break else: break # 评分 if count 4: score 100000 # 必胜 elif count 3: if open_ends 2: score 10000 # 活四 elif open_ends 1: score 1000 # 冲四 elif count 2: if open_ends 2: score 500 # 活三 elif open_ends 1: score 100 # 冲三 elif count 1 and open_ends 2: score 50 return score def ai_move(self): AI下棋 valid_moves self.get_valid_moves() if not valid_moves: return # 棋盘为空时下在中心 if self.is_board_empty(): center self.BOARD_SIZE // 2 self.make_move(center, center) return best_move None best_score -float(inf) for row, col in valid_moves: # 评估进攻分数 attack_score self.evaluate_position(row, col, 2) # 评估防守分数 defense_score self.evaluate_position(row, col, 1) # 综合评分 total_score attack_score defense_score * 0.9 # 略微偏向中心 center_distance abs(row - self.BOARD_SIZE // 2) abs(col - self.BOARD_SIZE // 2) total_score - center_distance * 5 if total_score best_score: best_score total_score best_move (row, col) if best_move: self.make_move(best_move[0], best_move[1]) def undo_move(self): 悔棋 if not self.move_history or self.game_over: return # 如果是AI模式需要回退两步AI的一步和玩家的一步 if self.ai_mode: if len(self.move_history) 2: # 回退AI的棋 row, col, player self.move_history.pop() self.board[row][col] 0 # 回退玩家的棋 row, col, player self.move_history.pop() self.board[row][col] 0 # 更新最后一步 if self.move_history: self.last_move (self.move_history[-1][0], self.move_history[-1][1]) else: self.last_move None # 切换回玩家 self.current_player 1 elif len(self.move_history) 1: # 只有一步棋玩家第一步回退 row, col, player self.move_history.pop() self.board[row][col] 0 self.last_move None self.current_player 1 else: # 双人模式只回退一步 row, col, player self.move_history.pop() self.board[row][col] 0 # 更新最后一步 if self.move_history: self.last_move (self.move_history[-1][0], self.move_history[-1][1]) else: self.last_move None # 切换回上一个玩家 self.current_player player def restart_game(self): 重新开始游戏 self.board [[0 for _ in range(self.BOARD_SIZE)] for _ in range(self.BOARD_SIZE)] self.current_player 1 self.game_over False self.winner None self.win_line [] self.last_move None self.move_history [] # 清空历史记录 def toggle_ai_mode(self): 切换AI模式 self.ai_mode not self.ai_mode for button in self.buttons: if button[action] toggle_ai: button[text] fAI: {开 if self.ai_mode else 关} break def handle_click(self, pos): 处理鼠标点击 # 检查按钮点击 for button in self.buttons: if button[rect].collidepoint(pos): if button[action] restart: self.restart_game() elif button[action] toggle_ai: self.toggle_ai_mode() elif button[action] undo: self.undo_move() elif button[action] quit: pygame.quit() sys.exit() return # 检查棋盘点击 if not self.game_over and not (self.ai_mode and self.current_player 2): x, y pos if y self.BOARD_PIXEL_SIZE self.MARGIN: # 转换为网格坐标 col round((x - self.MARGIN) / self.CELL_SIZE) row round((y - self.MARGIN) / self.CELL_SIZE) if self.is_valid_move(row, col): self.make_move(row, col) def run(self): 运行游戏主循环 clock pygame.time.Clock() while True: for event in pygame.event.get(): if event.type pygame.QUIT: pygame.quit() sys.exit() elif event.type pygame.MOUSEBUTTONDOWN: if event.button 1: # 左键 self.handle_click(event.pos) # 绘制 self.draw_board() self.draw_pieces() self.draw_win_line() self.draw_ui() pygame.display.flip() clock.tick(60) def main(): 主函数 game GomokuGame() game.run() if __name__ __main__: main()

相关新闻

大白话之——本地部署的大模型文件实际保存的是什么

大白话之——本地部署的大模型文件实际保存的是什么

大白话之——大模型生成答案的核心原理 大白话之——大模型训练过程 大白话之——本地部署的大模型文件实际保存的是什么 大白话之——大模型相同问题为啥答案不完全相同 大白话之——大模型训练好了,使用为啥还需要GPU 训练好的大模型文件里,只存了一堆…

2026/5/17 11:53:24 阅读更多 →
Windows无法安装到这个磁盘.选中的磁盘具有MBR分区表,在EFI 系统上,Windows 只能安装到 GPT 磁盘。

Windows无法安装到这个磁盘.选中的磁盘具有MBR分区表,在EFI 系统上,Windows 只能安装到 GPT 磁盘。

当你在PE系统重装windows 10系统时候 提示:无法点击下一步。问题原因你当前是 EFI 启动模式,但目标磁盘是 MBR 分区表,Windows 不允许在 EFI 模式下安装到 MBR 磁盘,因此报错。解决方法:将磁盘转换为 GPT 分区表&#…

2026/5/17 11:53:23 阅读更多 →
基于QT(C++)实现加、减、乘、除括号混合运算计算器

基于QT(C++)实现加、减、乘、除括号混合运算计算器

计算器,加、减、乘、除括号混合运算。 开发环境 Qt creator4.4.1 qt4.7 算法 1.字符串转中缀表达式 扫描字符串,遇到数字或"."则将该字符添加到tempString,如果遇到"-/()"则将tempString(非空&#xff0…

2026/7/3 10:40:48 阅读更多 →

最新新闻

PyTorch模型性能优化实战:从数据加载到部署

PyTorch模型性能优化实战:从数据加载到部署

1. PyTorch模型性能优化全景解析在深度学习项目实践中,模型性能优化是每个从业者必须掌握的硬核技能。最近接手的一个工业级图像分类项目让我深刻体会到:当数据集规模达到千万级,即使使用RTX 4090这样的顶级显卡,未经优化的PyTorc…

2026/7/3 21:05:29 阅读更多 →
MuleSoft企业级AI编排:让大模型听懂ERP与CRM

MuleSoft企业级AI编排:让大模型听懂ERP与CRM

1. 项目概述:当企业级集成平台遇上大语言模型,不是叠加,而是重定义工作流“AI Orchestration in Action: How MuleSoft and LLMs Fuel the Future of Enterprise AI”——这个标题里藏着一个正在发生的、静默却剧烈的范式转移。它说的不是“用…

2026/7/3 21:05:29 阅读更多 →
STM32与TI降压转换器的高效电源管理方案

STM32与TI降压转换器的高效电源管理方案

1. 项目背景与硬件选型解析在嵌入式电源管理领域,DC-DC降压转换是基础但至关重要的技术环节。本次项目采用171010550电源管理IC与STM32F215ZG微控制器的组合方案,这个搭配在工业控制领域颇具代表性。171010550是TI(德州仪器)旗下的…

2026/7/3 21:03:28 阅读更多 →
Rust 流式输出:让模型边生成边显示,但别忘了中断

Rust 流式输出:让模型边生成边显示,但别忘了中断

Rust 流式输出:让模型边生成边显示,但别忘了中断 第一次用 AI CLI 工具时,我最喜欢的体验就是"字一个一个往外蹦"的感觉——不用等模型完全生成完,就能看到内容在慢慢出现。但自己动手实现流式输出后才知道,…

2026/7/3 21:03:28 阅读更多 →
STM32F415RG与ICM-45605构建高精度IMU系统指南

STM32F415RG与ICM-45605构建高精度IMU系统指南

1. 项目背景与核心器件选型在嵌入式系统开发中,精确测量物体的运动状态是一个常见但极具挑战性的需求。ICM-45605作为TDK InvenSense最新推出的6轴MEMS IMU传感器,配合STM32F415RG这款高性能ARM Cortex-M4微控制器,能够构建一个高精度、低功耗…

2026/7/3 21:01:28 阅读更多 →
AI智能剪辑新范式:用LLM“阅读”视频,告别传统剪辑苦力

AI智能剪辑新范式:用LLM“阅读”视频,告别传统剪辑苦力

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Claude 随心用,限时 5 折。 👉 点击领海量免费额度 如果你还在用传统剪辑软件,一帧一帧地剪掉“嗯…啊…”的停顿,手动对齐字幕,反复渲染预览&#…

2026/7/3 21:01:28 阅读更多 →

日新闻

Nginx防御TLS重协商攻击实战:从原理到配置与监控

Nginx防御TLS重协商攻击实战:从原理到配置与监控

1. 项目概述:为什么TLS重协商攻击至今仍需警惕十多年前的CVE-2011-1473,一个关于TLS/SSL协议重协商机制的漏洞,现在提起来还有必要吗?很多运维和开发朋友可能会觉得,这都老掉牙了,现代服务器和客户端不都默…

2026/7/3 0:03:59 阅读更多 →
华为防火墙双通道远程管理实战:Web与SSH配置详解

华为防火墙双通道远程管理实战:Web与SSH配置详解

1. 项目概述:为什么需要双通道远程管理防火墙?在任何一个稍具规模的企业网络里,防火墙都是那个默默守护在边界的关键角色。作为网络工程师,我们不可能每次都跑到机房,插上console线去配置它。远程管理能力,…

2026/7/3 0:03:59 阅读更多 →
AD74413R与PIC18F65K40的高精度工业数据采集方案

AD74413R与PIC18F65K40的高精度工业数据采集方案

1. 项目概述:AD74413R与PIC18F65K40的协同工作在工业自动化和精密测量领域,同时实现高精度模数转换(ADC)和数模转换(DAC)功能是许多复杂系统的核心需求。AD74413R作为一款四通道可配置模拟输入/输出器件,与PIC18F65K40微控制器的组合&#xf…

2026/7/3 0:05:59 阅读更多 →

周新闻

月新闻