Python汉字贪吃蛇程序升级版
代码分析概要
该代码实现了一个结合贪吃蛇游戏与汉字学习的教育应用框架,使用PyQt5构建图形界面。核心思路是将传统贪吃蛇机制与汉字学习元素融合,通过游戏互动帮助用户记忆汉字。
游戏机制设计
蛇的移动采用经典贪吃蛇逻辑,使用坐标列表存储蛇身位置。方向控制采用direction
和next_direction
双变量缓冲机制,避免快速按键导致的直接逆向移动问题。游戏区域划分为45×30的网格系统(每个网格20×20像素),用于碰撞检测和食物位置计算。
教育元素整合
汉字数据存储在hanzi_data
列表中,包含15个基础汉字及其拼音和英文释义。游戏计划通过显示目标汉字要求玩家收集对应拼音或释义的食物来得分。当前代码中汉字显示逻辑尚未完全实现,但预留了current_target
变量存储当前学习目标。
界面布局结构
主窗口采用水平布局,左侧占70%空间为游戏区,右侧为控制面板。游戏区包含标题标签和600×900像素的画布,使用绿色系样式。控制面板包含开始/暂停按钮组,采用Material Design风格的CSS样式,包含悬浮效果和圆角边框。
状态管理系统
定义多个游戏状态变量:
game_active
控制游戏运行状态game_paused
处理暂停逻辑score
和streak
记录学习进度level
实现难度分级errors
跟踪错误次数
待完善功能
- 汉字显示逻辑:画布绘制部分代码不完整(如
Q极AlignCenter
和game极anvas
存在拼写错误),需实现汉字在食物上的渲染 - 碰撞检测系统:网格数组
grid
已初始化但未使用,需补充蛇身与食物/边界的碰撞判断 - 学习反馈机制:缺少对答案正确性的判断逻辑和对应的得分/提示系统
- 游戏难度曲线:
level
变量未与蛇速或汉字难度关联
改进建议
- 在食物生成时随机选择汉字数据,并验证玩家输入是否匹配
- 添加计分板显示当前学习的汉字、拼音和释义
- 实现错误三次后显示正确答案的容错机制
- 不同级别可调整蛇速或增加汉字复杂度
- 添加音效反馈和视觉特效增强学习记忆点
该框架已具备基本游戏结构和教育元素,后续开发需重点完善汉字学习交互逻辑与游戏机制的深度结合。
import sys
import random
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QFrame, QSizePolicy, QMessageBox, QGroupBox,QGridLayout, QSlider, QTextEdit, QScrollArea
)
from PyQt5.QtCore import Qt, QTimer, QSize, QRect
from PyQt5.QtGui import QFont, QColor, QPainter, QPen, QBrush, QPixmap, QFontMetricsclass SnakeGame(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("贪吃蛇学汉字")self.setGeometry(100, 100, 1200, 800)self.setMinimumSize(1100, 700)# 游戏状态self.game_active = Falseself.game_paused = Falseself.score = 0self.streak = 0self.level = 1self.errors = 0# 蛇的初始设置self.snake = [(200, 250), (180, 250), (160, 250)]self.direction = "Right"self.next_direction = "Right"self.snake_length = 3# 汉字和拼音数据self.hanzi_data = [{"character": "猫", "pinyin": "māo", "meaning": "cat"},{"character": "狗", "pinyin": "gǒu", "meaning": "dog"},{"character": "鸟", "pinyin": "niǎo", "meaning": "bird"},{"character": "鱼", "pinyin": "yú", "meaning": "fish"},{"character": "花", "pinyin": "huā", "meaning": "flower"},{"character": "树", "pinyin": "shù", "meaning": "tree"},{"character": "日", "pinyin": "rì", "meaning": "sun"},{"character": "月", "pinyin": "yuè", "meaning": "moon"},{"character": "山", "pinyin": "shān", "meaning": "mountain"},{"character": "水", "pinyin": "shuǐ", "meaning": "water"},{"character": "火", "pinyin": "huǒ", "meaning": "fire"},{"character": "木", "pinyin": "mù", "meaning": "wood"},{"character": "人", "pinyin": "rén", "meaning": "person"},{"character": "口", "pinyin": "kǒu", "meaning": "mouth"},{"character": "手", "pinyin": "shǒu", "meaning": "hand"},]# 当前目标汉字 - 添加默认目标防止空指针错误self.current_target = self.hanzi_data[0]# 目标汉字位置列表self.target_positions = []self.grid = [[False]*30 for _ in range(45)] # 45x30 网格 (900/20=45, 600/20=30)# 创建中央部件central_widget = QWidget()self.setCentralWidget(central_widget)main_layout = QHBoxLayout(central_widget)main_layout.setContentsMargins(15, 10, 15, 15)main_layout.setSpacing(15) # 减少间距# 左侧游戏区域 (70%)game_container = QWidget()game_layout = QVBoxLayout(game_container)game_layout.setContentsMargins(0, 0, 0, 0)game_layout.setSpacing(10) # 减少间距# 游戏标题title_label = QLabel("贪吃蛇学汉字")title_label.setAlignment(Qt.AlignCenter)title_label.setStyleSheet("""font-size: 28px;font-weight: bold;color: #FF5722;background-color: rgba(255, 245, 157, 0.7);border-radius: 12px;padding: 6px;border: 2px solid #FF9800;""")game_layout.addWidget(title_label)# 游戏画布self.game_canvas = QLabel()self.game_canvas.setFixedSize(900, 600)self.game_canvas.setStyleSheet("background-color: #C8E6C9; border: 3px solid #4CAF50; border-radius: 10px;")game_layout.addWidget(self.game_canvas, alignment=Qt.AlignCenter)# 控制区域control_layout = QVBoxLayout()control_layout.setContentsMargins(5, 5, 5, 5)control_layout.setSpacing(5)# 按钮布局button_layout = QHBoxLayout()button_layout.setSpacing(10)# 开始按钮self.start_btn = QPushButton("开始游戏")self.start_btn.setStyleSheet("""QPushButton {background-color: #4CAF50;color: white;border: none;border-radius: 10px;padding: 10px 15px;font-size: 16px;font-weight: bold;}QPushButton:hover {background-color: #81C784;}""")self.start_btn.clicked.connect(self.start_game)button_layout.addWidget(self.start_btn)# 暂停按钮self.pause_btn = QPushButton("暂停")self.pause_btn.setStyleSheet("""QPushButton {background-color: #FF9800;color: white;border: none;border-radius: 10px;padding: 10px 15px;font-size: 16px;font-weight: bold;}QPushButton:hover {background-color: #FFB74D;}""")self.pause_btn.clicked.connect(self.toggle_pause)self.pause_btn.setEnabled(False)button_layout.addWidget(self.pause_btn)control_layout.addLayout(button_layout)# 调速滑条speed_layout = QHBoxLayout()speed_layout.setSpacing(5)speed_label = QLabel("游戏速度:")speed_label.setStyleSheet("font-size: 15px; color: #333;")speed_layout.addWidget(speed_label)self.speed_slider = QSlider(Qt.Horizontal)self.speed_slider.setMinimum(50)self.speed_slider.setMaximum(400)self.speed_slider.setValue(200)self.speed_slider.setTickPosition(QSlider.TicksBelow)self.speed_slider.setTickInterval(50)self.speed_slider.setStyleSheet("""QSlider::groove:horizontal {border: 1px solid #999999;height: 6px;background: #e0e0e0;margin: 2px 0;}QSlider::handle:horizontal {background: #4CAF50;border: 1px solid #388E3C;width: 16px;margin: -7px 0;border-radius: 8px;}QSlider::sub-page:horizontal {background: #81C784;}""")self.speed_slider.valueChanged.connect(self.adjust_speed)speed_layout.addWidget(self.speed_slider)# 速度指示标签self.speed_label = QLabel("中等")self.speed_label.setStyleSheet("font-size: 15px; font-weight: bold; color: #1976D2; min-width: 60px;")speed_layout.addWidget(self.speed_label)control_layout.addLayout(speed_layout)game_layout.addLayout(control_layout)main_layout.addWidget(game_container, 70)# 右侧信息区域 (30%)info_container = QWidget()info_layout = QVBoxLayout(info_container)info_layout.setContentsMargins(10, 10, 10, 10) # 减少边距info_layout.setSpacing(10) # 减少间距# 信息区域样式info_container.setStyleSheet("""background-color: #E3F2FD;border: 3px solid #2196F3;border-radius: 15px;""")# 当前目标 - 压缩高度target_group = QGroupBox("当前目标")target_group.setMaximumHeight(260) # 限制最大高度target_group.setStyleSheet("""QGroupBox {font-size: 18px;font-weight: bold;color: #1976D2;margin-top: 0px;}""")target_layout = QVBoxLayout(target_group)target_layout.setSpacing(0) # 减少内部间距self.target_pinyin = QLabel("māo")self.target_pinyin.setAlignment(Qt.AlignCenter)self.target_pinyin.setStyleSheet("""font-size: 36px;font-weight: bold;color: #D32F2F;background-color: #FFEBEE;border-radius: 8px;padding: 3px;""")target_layout.addWidget(self.target_pinyin)self.target_character = QLabel("猫")self.target_character.setAlignment(Qt.AlignCenter)self.target_character.setStyleSheet("""font-size: 110px;font-weight: bold;color: #1976D2;padding: 0px;margin: 0px;""")target_layout.addWidget(self.target_character)self.target_meaning = QLabel("意思: cat")self.target_meaning.setAlignment(Qt.AlignCenter)self.target_meaning.setStyleSheet("""font-size: 18px;color: #5C6BC0;font-style: italic;margin-top: 0px;""")target_layout.addWidget(self.target_meaning)info_layout.addWidget(target_group)# 得分和等级 - 压缩高度stats_group = QGroupBox("游戏数据")stats_group.setMaximumHeight(180) # 限制最大高度stats_group.setStyleSheet("""QGroupBox {font-size: 18px;font-weight: bold;color: #1976D2;margin-top: 0px;}""")stats_layout = QGridLayout(stats_group)stats_layout.setVerticalSpacing(3) # 减少行间距stats_layout.setContentsMargins(10, 5, 10, 5)# 得分score_label = QLabel("得分:")score_label.setStyleSheet("font-size: 18px; color: #00796B;")stats_layout.addWidget(score_label, 0, 0)self.score_value = QLabel("0")self.score_value.setStyleSheet("font-size: 26px; font-weight: bold; color: #F44336;")stats_layout.addWidget(self.score_value, 0, 1)# 连续正确streak_label = QLabel("连续正确:")streak_label.setStyleSheet("font-size: 18px; color: #00796B;")stats_layout.addWidget(streak_label, 1, 0)self.streak_value = QLabel("0")self.streak_value.setStyleSheet("font-size: 26px; font-weight: bold; color: #F44336;")stats_layout.addWidget(self.streak_value, 1, 1)# 等级level_label = QLabel("等级:")level_label.setStyleSheet("font-size: 18px; color: #00796B;")stats_layout.addWidget(level_label, 2, 0)self.level_value = QLabel("1")self.level_value.setStyleSheet("font-size: 26px; font-weight: bold; color: #F44336;")stats_layout.addWidget(self.level_value, 2, 1)# 错误次数error_label = QLabel("错误次数:")error_label.setStyleSheet("font-size: 18px; color: #00796B;")stats_layout.addWidget(error_label, 3, 0)self.error_value = QLabel("0")self.error_value.setStyleSheet("font-size: 26px; font-weight: bold; color: #F44336;")stats_layout.addWidget(self.error_value, 3, 1)info_layout.addWidget(stats_group)# 游戏提示区域 - 压缩高度self.notification_group = QGroupBox("游戏提示")self.notification_group.setMaximumHeight(100) # 限制最大高度self.notification_group.setStyleSheet("""QGroupBox {font-size: 18px;font-weight: bold;color: #1976D2;margin-top: 0px;}""")notification_layout = QVBoxLayout(self.notification_group)notification_layout.setContentsMargins(0, 0, 0, 0)self.notification_text = QTextEdit()self.notification_text.setReadOnly(True)self.notification_text.setStyleSheet("""QTextEdit {font-size: 14px;border: 1px solid #BBDEFB;border-radius: 6px;background-color: #FFFFFF;padding: 5px;margin: 0px;}""")notification_layout.addWidget(self.notification_text)info_layout.addWidget(self.notification_group)# 游戏规则 - 滚动视图解决空间不足问题rules_group = QGroupBox("游戏规则")rules_group.setStyleSheet("""QGroupBox {font-size: 18px;font-weight: bold;color: #1976D2;margin-top: 0px;}""")rules_layout = QVBoxLayout(rules_group)rules_text = QLabel("""<ul><li>找到并吃掉<span style='color:#4CAF50; font-weight:bold'>绿色汉字</span>(当前目标)</li><li>每吃对一个汉字:<span style='color:#4CAF50; font-weight:bold'>+10分</span></li><li>连续正确3次:<span style='color:#FF9800; font-weight:bold'>+30分</span></li><li>连续正确5次:<span style='color:#F44336; font-weight:bold'>+50分</span></li><li>每100分升一级,蛇速度加快</li><li>碰到<span style='color:#F44336; font-weight:bold'>红色汉字</span>:<span style='color:#F44336; font-weight:bold'>-5分</span>,错误次数+1</li><li>错误次数达到5次:<span style='color:#F44336; font-weight:bold'>游戏结束</span></li></ul>""")rules_text.setStyleSheet("font-size: 15px; color: #616161; padding: 0px;")rules_text.setWordWrap(True)rules_layout.addWidget(rules_text)info_layout.addWidget(rules_group)# 操作说明 - 压缩高度controls_group = QGroupBox("操作说明")controls_group.setStyleSheet("""QGroupBox {font-size: 18px;font-weight: bold;color: #1976D2;margin-top: 0px;}""")controls_layout = QVBoxLayout(controls_group)controls_text = QLabel("""<ul><li><span style='color:#FF5722; font-weight:bold'>方向键</span> 或 <span style='color:#FF5722; font-weight:bold'>WASD</span> 控制蛇移动</li><li>蛇头显示拼音,找到对应汉字吃掉</li><li>绿色汉字:<span style='color:#4CAF50; font-weight:bold'>当前目标</span></li><li>红色汉字:<span style='color:#F44336; font-weight:bold'>错误汉字</span>(避开)</li><li>使用下方滑条调节游戏速度</li><li><span style='color:#FF5722; font-weight:bold'>滑条左侧慢,右侧快</span></li></ul>""")controls_text.setStyleSheet("font-size: 15px; color: #616161; padding: 0px;")controls_text.setWordWrap(True)controls_layout.addWidget(controls_text)info_layout.addWidget(controls_group)# 添加拉伸因子确保合理布局info_layout.setStretch(0, 3) # 当前目标info_layout.setStretch(1, 2) # 游戏数据info_layout.setStretch(2, 1) # 游戏提示info_layout.setStretch(3, 2) # 游戏规则info_layout.setStretch(4, 2) # 操作说明main_layout.addWidget(info_container, 30)# 游戏定时器self.timer = QTimer(self)self.timer.timeout.connect(self.update_game)# 初始绘制self.draw_game()def reset_grid(self):"""重置网格状态"""self.grid = [[False]*30 for _ in range(45)]# 标记蛇占据的位置for x, y in self.snake:grid_x = int(x // 20)grid_y = int(y // 20)if 0 <= grid_x < 45 and 0 <= grid_y < 30:self.grid[grid_x][grid_y] = Truedef adjust_speed(self, value):"""根据滑条值调整游戏速度"""if value <= 100:speed_text = "非常快"elif value <= 150:speed_text = "快"elif value <= 250:speed_text = "中等"elif value <= 350:speed_text = "慢"else:speed_text = "非常慢"self.speed_label.setText(speed_text)if self.game_active and not self.game_paused:self.timer.start(value)def start_game(self):"""开始新游戏"""try:self.game_active = Trueself.game_paused = Falseself.score = 0self.streak = 0self.errors = 0self.level = 1self.snake = [(200, 250), (180, 250), (160, 250)]self.snake_length = 3self.direction = "Right"self.next_direction = "Right"# 重置网格self.reset_grid()# 清空提示框self.notification_text.clear()self.start_btn.setText("重新开始")self.pause_btn.setEnabled(True)self.pause_btn.setText("暂停")# 生成第一个目标self.generate_new_target()self.generate_target_positions()# 启动游戏self.timer.setInterval(self.speed_slider.value())self.timer.start()# 添加欢迎提示self.add_notification("游戏开始!请使用方向键或WASD控制贪吃蛇")self.update_stats()self.draw_game()except Exception as e:import tracebackself.add_notification(f"游戏启动时发生错误: {str(e)}")self.add_notification(traceback.format_exc())# 确保错误后仍可重新开始self.game_active = Falseself.timer.stop()def toggle_pause(self):"""暂停/继续游戏"""try:self.game_paused = not self.game_pausedif self.game_paused:self.timer.stop()self.pause_btn.setText("继续")self.add_notification("游戏已暂停")else:self.timer.start()self.pause_btn.setText("暂停")self.add_notification("游戏继续运行")self.draw_game()except Exception as e:self.add_notification(f"暂停/继续游戏时发生错误: {str(e)}")def add_notification(self, message):"""添加游戏提示到右侧提示框"""self.notification_text.append(f"• {message}")# 自动滚动到底部self.notification_text.verticalScrollBar().setValue(self.notification_text.verticalScrollBar().maximum())def generate_new_target(self):"""生成新的目标汉字"""if self.hanzi_data:self.current_target = random.choice(self.hanzi_data)# 安全更新目标显示self.target_pinyin.setText(self.current_target["pinyin"])self.target_character.setText(self.current_target["character"])self.target_meaning.setText(f"意思: {self.current_target['meaning']}")# 添加提示self.add_notification(f"新目标: {self.current_target['pinyin']} ({self.current_target['character']})")def generate_target_positions(self):"""生成目标汉字的位置 - 使用网格系统避免重叠"""self.target_positions = []if not self.current_target:returntarget_character = self.current_target["character"]# 重置网格标记self.reset_grid()# 计算可用空间available_spaces = 45 * 30 - len(self.snake)# 确保有足够的空间生成目标if available_spaces < 3: # 需要至少3个空格才能生成正确目标self.add_notification("空间不足,无法生成目标!")self.game_over()return# 生成正确目标位置 (1-3个)targets_to_generate = min(3, available_spaces - 1)generated_targets = 0target_count = random.randint(1, min(3, targets_to_generate))while generated_targets < target_count:grid_x = random.randint(0, 44)grid_y = random.randint(0, 29)if not self.grid[grid_x][grid_y]:x = grid_x * 20y = grid_y * 20self.target_positions.append({"pos": (x, y), "character": target_character, "is_target": True})self.grid[grid_x][grid_y] = Truegenerated_targets += 1available_spaces -= 1# 生成错误目标位置 (1-5个)other_characters = [h["character"] for h in self.hanzi_data if h["character"] != target_character]if not other_characters:other_characters = ["错"]errors_to_generate = min(5, available_spaces)generated_errors = 0if errors_to_generate > 0:while generated_errors < errors_to_generate:grid_x = random.randint(0, 44)grid_y = random.randint(0, 29)if not self.grid[grid_x][grid_y]:x = grid_x * 20y = grid_y * 20self.target_positions.append({"pos": (x, y), "character": random.choice(other_characters), "is_target": False})self.grid[grid_x][grid_y] = Truegenerated_errors += 1available_spaces -= 1self.add_notification(f"目标已生成: {target_count}个正确目标,{generated_errors}个错误目标")def update_stats(self):"""更新游戏统计数据"""self.score_value.setText(str(self.score))self.streak_value.setText(str(self.streak))self.level_value.setText(str(self.level))self.error_value.setText(str(self.errors))def update_game(self):"""更新游戏状态"""if not self.game_active or self.game_paused:returntry:# 更新方向self.direction = self.next_direction# 计算蛇头新位置head_x, head_y = self.snake[0]if self.direction == "Right":head_x += 20elif self.direction == "Left":head_x -= 20elif self.direction == "Up":head_y -= 20elif self.direction == "Down":head_y += 20new_head = (head_x, head_y)# 检查碰撞if self.check_collision(new_head):self.game_over()return# 移动蛇self.snake.insert(0, new_head)# 更新网格中的蛇位置self.reset_grid()# 检查是否碰到目标汉字if not self.target_positions:self.generate_target_positions()# 如果生成失败,结束游戏if not self.target_positions:self.game_over()returnfor target in self.target_positions[:]:t_x, t_y = target["pos"]# 碰撞检测容差if abs(head_x - t_x) < 30 and abs(head_y - t_y) < 30:if target["is_target"]:# 吃对了self.score += 10self.streak += 1self.snake_length += 1# 连续正确奖励if self.streak % 5 == 0:self.score += 50self.add_notification(f"🎉 连续正确5次!奖励50分")elif self.streak % 3 == 0:self.score += 30self.add_notification(f"🏆 连续正确3次!奖励30分")# 安全更新等级if self.score >= 100 and self.level < self.score // 100 + 1:self.level = min(self.level + 1, 10)self.add_notification(f"⭐ 升级啦!现在等级: {self.level}")# 生成新目标self.generate_new_target()self.generate_target_positions()# 添加提示self.add_notification(f"✅ 吃对了!+10分")breakelse:# 吃错了self.score = max(0, self.score - 5)self.streak = 0self.errors += 1# 添加提示self.add_notification(f"❌ 吃错了!-5分")if self.errors >= 5:self.game_over()return# 移除目标self.target_positions.remove(target)# 更新网格状态grid_x = int(t_x // 20)grid_y = int(t_y // 20)if 0 <= grid_x < 45 and 0 <= grid_y < 30:self.grid[grid_x][grid_y] = Falsebreak# 移除多余蛇身while len(self.snake) > self.snake_length:self.snake.pop()# 更新界面self.update_stats()self.draw_game()except Exception as e:self.add_notification(f"游戏更新时发生错误: {str(e)}")self.game_over()def check_collision(self, position):"""检查碰撞"""x, y = position# 撞墙检测if x < 0 or x >= 900 or y < 0 or y >= 600:return True# 撞自己检测if position in self.snake[1:]:return Truereturn Falsedef game_over(self):"""游戏结束"""self.game_active = Falseself.timer.stop()self.start_btn.setEnabled(True) # 确保可以重新开始# 在右侧提示区域显示结果if self.errors >= 5:self.add_notification("💥 错误次数达到5次!游戏结束")else:self.add_notification("🛑 游戏结束!")self.add_notification(f"最终得分: {self.score}")def keyPressEvent(self, event):"""处理键盘事件"""if not self.game_active or self.game_paused:returnkey = event.key()# 方向键控制if key == Qt.Key_Right and self.direction != "Left":self.next_direction = "Right"elif key == Qt.Key_Left and self.direction != "Right":self.next_direction = "Left"elif key == Qt.Key_Up and self.direction != "Down":self.next_direction = "Up"elif key == Qt.Key_Down and self.direction != "Up":self.next_direction = "Down"# WASD控制elif key == Qt.Key_W and self.direction != "Down":self.next_direction = "Up"elif key == Qt.Key_S and self.direction != "Up":self.next_direction = "Down"elif key == Qt.Key_A and self.direction != "Right":self.next_direction = "Left"elif key == Qt.Key_D and self.direction != "Left":self.next_direction = "Right"def draw_game(self):"""绘制游戏画面"""try:# 创建画布canvas = QPixmap(900, 600)canvas.fill(Qt.transparent)painter = QPainter(canvas)painter.setRenderHint(QPainter.Antialiasing)# 绘制背景painter.fillRect(0, 0, 900, 600, QColor("#C8E6C9"))# 绘制网格painter.setPen(QPen(QColor("#A5D6A7"), 1))for x in range(0, 900, 20):painter.drawLine(x, 0, x, 600)for y in range(0, 600, 20):painter.drawLine(0, y, 900, y)# 绘制蛇for i, (x, y) in enumerate(self.snake):if i == 0: # 蛇头painter.setBrush(QBrush(QColor("#FF5722")))painter.setPen(QPen(QColor("#E64A19"), 2))painter.drawEllipse(x, y, 20, 20)# 绘制拼音 - 增加字体大小并加粗if self.current_target and "pinyin" in self.current_target:pinyin = self.current_target["pinyin"]painter.setPen(QPen(QColor("#FFFFFF")))# 使用更大更粗的字体font = QFont("Arial", 20, QFont.Bold)painter.setFont(font)# 绘制背景增强可见性text_metrics = painter.fontMetrics()text_width = text_metrics.horizontalAdvance(pinyin)text_height = text_metrics.height()# 计算背景矩形位置bg_rect = QRect(int(x + 10 - text_width//2 - 5),int(y - text_height - 5),text_width + 10,text_height + 5)painter.setBrush(QBrush(QColor(0, 0, 0, 150)))painter.setPen(Qt.NoPen)painter.drawRect(bg_rect)# 绘制拼音文本painter.setPen(QPen(QColor("#FFFF00"))) # 更醒目的黄色painter.setFont(font)text_x = int(x + 10 - text_width // 2)text_y = int(y - 10)painter.drawText(text_x, text_y, pinyin)else: # 蛇身color = QColor("#4CAF50") if i % 2 == 0 else QColor("#388E3C")painter.setBrush(QBrush(color))painter.setPen(QPen(QColor("#1B5E20"), 1))painter.drawRect(x, y, 20, 20)# 绘制目标汉字for target in self.target_positions:x, y = target["pos"]hanzi = target["character"]if target["is_target"]:bg_color = QColor("#4CAF50")text_color = QColor("#1B5E20")else:bg_color = QColor("#F44336")text_color = QColor("#B71C1C")char_size = 60painter.setBrush(QBrush(bg_color))painter.setPen(QPen(text_color, 2))painter.drawEllipse(int(x + 10 - char_size/2), int(y + 10 - char_size/2), char_size, char_size)# 绘制汉字painter.setPen(QPen(text_color))font = QFont("SimSun", 36, QFont.Bold)painter.setFont(font)text_metrics = painter.fontMetrics()text_width = text_metrics.horizontalAdvance(hanzi)text_height = text_metrics.height()text_x = int(x + 10 - text_width // 2)text_y = int(y + 10 + text_height // 3)painter.drawText(text_x, text_y, hanzi)# 绘制游戏状态if not self.game_active:painter.setBrush(QBrush(QColor(0, 0, 0, 150)))painter.drawRect(0, 0, 900, 600)painter.setPen(QPen(QColor("#FFFFFF")))font = QFont("Arial", 28, QFont.Bold)painter.setFont(font)painter.drawText(QRect(0, 0, 900, 600), Qt.AlignCenter, "点击'开始游戏'")if self.game_paused:painter.setBrush(QBrush(QColor(0, 0, 0, 150)))painter.drawRect(0, 0, 900, 600)painter.setPen(QPen(QColor("#FFFFFF")))font = QFont("Arial", 28, QFont.Bold)painter.setFont(font)painter.drawText(QRect(0, 0, 900, 600), Qt.AlignCenter, "游戏暂停")painter.end()self.game_canvas.setPixmap(canvas)except Exception as e:try:painter.end()except:passself.add_notification(f"绘制游戏画面时发生错误: {str(e)}")if __name__ == "__main__":app = QApplication(sys.argv)# 设置安全字体font = QFont()font.setFamily("Arial")font.setPointSize(12)app.setFont(font)# 安全启动游戏try:game = SnakeGame()game.show()sys.exit(app.exec_())except Exception as e:msg = QMessageBox()msg.setIcon(QMessageBox.Critical)msg.setWindowTitle("致命错误")msg.setText(f"应用程序启动时发生严重错误:\n{str(e)}")msg.exec_()sys.exit(1)