猜数字游戏:从数学原理到交互体验的完整设计指南
目录
- 猜数字游戏:从数学原理到交互体验的完整设计指南
- 引言
- 第一章 游戏数学原理
- 1.1 均匀分布与随机生成
- 1.2 最优猜测策略
- 第二章 游戏系统设计
- 2.1 核心架构
- 2.2 动态难度系统
- 第三章 交互设计细节
- 3.1 输入验证系统
- 3.2 渐进式提示机制
- 第四章 进阶功能设计
- 4.1 智能辅导系统
- 4.2 数据驱动平衡
- 第五章 性能优化
- 5.1 内存管理策略
- 5.2 实时反馈优化
- 第六章 测试与调试
- 6.1 自动化测试矩阵
- 6.2 蒙特卡洛测试
- 结语
- 附录:部分代码
猜数字游戏:从数学原理到交互体验的完整设计指南
引言
猜数字游戏作为编程教学中的"Hello World"级项目,其看似简单的表象下蕴含着精妙的数学原理和交互设计哲学。本文将深入解析一个专业级猜数字游戏的设计过程,揭示其背后的概率论基础、算法优化策略以及用户体验设计原则。
第一章 游戏数学原理
1.1 均匀分布与随机生成
游戏核心依赖的随机数生成遵循离散均匀分布原理:
P ( X = k ) = 1 N , k ∈ [ 1 , N ] P(X=k) = \frac{1}{N},\quad k \in [1,N] P(X=k)=N1,k∈[1,N]
其中 N N N表示数字范围上限。现代编程语言通常采用梅森旋转算法(Mersenne Twister)生成伪随机数,其周期长度达 2 19937 − 1 2^{19937}-1 219937−1,通过以下步骤实现理想随机性:
- 系统时间播种: s e e d = ⌊ t i m e s t a m p × 1 0 3 ⌋ seed = \lfloor timestamp \times 10^3 \rfloor seed=⌊timestamp×103⌋
- 范围映射: t a r g e t = ⌊ r a n d ( ) × ( m a x − m i n ) ⌋ + m i n target = \lfloor rand() \times (max-min) \rfloor + min target=⌊rand()×(max−min)⌋+min
1.2 最优猜测策略
采用二分查找算法时,最大猜测次数满足:
T m a x = ⌈ log 2 N ⌉ T_{max} = \lceil \log_2 N \rceil Tmax=⌈log2N⌉
当 N = 100 N=100 N=100时,理论最小次数为7次。实际游戏中玩家平均尝试次数为:
E ( T ) = ∑ k = 1 log 2 N 2 k − 1 N k E(T) = \sum_{k=1}^{\log_2 N} \frac{2^{k-1}}{N}k E(T)=k=1∑log2NN2k−1k
第二章 游戏系统设计
2.1 核心架构
2.2 动态难度系统
通过实时监测玩家表现调整参数:
指标 | 调节策略 | 数学表达式 |
---|---|---|
连续失败次数 | 缩小数字范围 | N n e w = ⌊ 0.8 N ⌋ N_{new} = \lfloor 0.8N \rfloor Nnew=⌊0.8N⌋ |
平均响应时间 | 调整倒计时长度 | t l i m i t = m a x ( 10 , 30 − T ‾ ) t_{limit} = max(10, 30-\overline{T}) tlimit=max(10,30−T) |
历史胜率 | 动态平衡随机分布 | μ = μ ± σ / 2 \mu = \mu \pm \sigma/2 μ=μ±σ/2 |
第三章 交互设计细节
3.1 输入验证系统
建立多层防护体系:
- 类型过滤:正则表达式
^[1-9]\d*$
- 范围检查: i n p u t ∈ [ l a s t L o w , l a s t H i g h ] input \in [lastLow, lastHigh] input∈[lastLow,lastHigh]
- 历史检测: i n p u t ∉ H i s t o r y S e t input \notin HistorySet input∈/HistorySet
3.2 渐进式提示机制
根据尝试次数动态释放提示:
尝试次数 | 提示类型 | 触发条件 |
---|---|---|
1-3 | 范围指示条 | 每次猜测后更新 |
4-5 | 质数高亮 | 涉及质数时触发 |
≥6 | 数字热度图 | 累计数据超过20条 |
第四章 进阶功能设计
4.1 智能辅导系统
采用贝叶斯推理实时分析玩家策略:
P ( S t r a t e g y ∣ A c t i o n s ) = P ( A c t i o n s ∣ S t r a t e g y ) P ( S t r a t e g y ) P ( A c t i o n s ) P(Strategy|Actions) = \frac{P(Actions|Strategy)P(Strategy)}{P(Actions)} P(Strategy∣Actions)=P(Actions)P(Actions∣Strategy)P(Strategy)
系统可识别的典型策略模式包括:
- 随机猜测(熵值>3.5)
- 线性搜索(猜测差值标准差<2)
- 二分法(符合 μ = 0.5 N \mu=0.5N μ=0.5N分布)
4.2 数据驱动平衡
收集以下指标进行游戏平衡:
metrics = {'attempt_dist': [], # 尝试次数分布'time_heatmap': [], # 时段活跃度'dropoff_point': [], # 玩家流失节点'pattern_cluster': [] # 策略聚类
}
第五章 性能优化
5.1 内存管理策略
采用环形缓冲区存储游戏记录:
B u f f e r S i z e = ⌈ log 2 N ⌉ × 2 BufferSize = \lceil \log_2 N \rceil \times 2 BufferSize=⌈log2N⌉×2
实现O(1)时间复杂度的历史查询操作。
5.2 实时反馈优化
通过插值算法实现流畅动画:
x t = x 0 + ( x t a r g e t − x 0 ) × 1 − ( 1 − t ) 4 x_{t} = x_{0} + (x_{target}-x_{0}) \times \sqrt{1-(1-t)^4} xt=x0+(xtarget−x0)×1−(1−t)4
R G B c u r r e n t = l e r p ( R G B s t a r t , R G B e n d , t T ) RGB_{current} = lerp(RGB_{start}, RGB_{end}, \frac{t}{T}) RGBcurrent=lerp(RGBstart,RGBend,Tt)
第六章 测试与调试
6.1 自动化测试矩阵
构建参数组合测试:
test_cases = [{'range': (1,10), 'strategy': 'random'},{'range': (1,100), 'strategy': 'binary'},{'range': (1,1000), 'strategy': 'linear'}
]
6.2 蒙特卡洛测试
进行10,000次模拟运行验证稳定性:
S u c c e s s R a t e = ∑ i = 1 1 0 4 I ( w i n i ) 1 0 4 SuccessRate = \frac{\sum_{i=1}^{10^4} I(win_i)}{10^4} SuccessRate=104∑i=1104I(wini)
结语
通过本文的深度解析,我们揭示了猜数字游戏设计背后复杂的系统工程。从数学公式推导到交互细节打磨,每个环节都体现着软件工程的基本原则。这种经典游戏的设计方法论,可延伸应用于各类交互系统的开发实践。
延伸思考:
- 如何将设计原则迁移到其他猜谜类游戏?
- 在保证公平性的前提下引入社交元素
- 基于玩家画像的个性化游戏调整
附录:部分代码
import sys
import time
import math
import random
from typing import Dict, Any, List, Optional
from PyQt6.QtWidgets import (QApplication, QMainWindow, QPushButton, QLineEdit, QLabel, QVBoxLayout, QHBoxLayout, QWidget, QSpinBox,QProgressBar, QGroupBox, QGridLayout, QSlider, QMessageBox,QTabWidget, QComboBox, QTextEdit, QRadioButton, QButtonGroup)
from PyQt6.QtCore import Qt, QTimer, pyqtSignal, QThread, QObject
from PyQt6.QtGui import QFont, QColor, QPalette, QIntValidator, QPixmap, QIcon
from game_engine import GameEngine, GameStateManager, GameState
from game_config import GameConfig
from player_analytics import PlayerAnalytics, StrategyType
from advanced_features import InterpolationUtilclass NumberGuessGame(QMainWindow):"""猜数字游戏GUI主窗口"""def __init__(self):super().__init__()# 设置窗口属性self.setWindowTitle("猜数字游戏 - 从数学原理到交互体验")self.setMinimumSize(800, 600)# 初始化游戏配置和引擎self.config = GameConfig()self.engine = GameEngine(self.config)self.analytics = PlayerAnalytics()# 游戏状态变量self.game_active = Falseself.start_time = 0self.last_guess_time = 0self.timer = QTimer(self)self.timer.timeout.connect(self.update_game_timer)# 搭建界面self.setup_ui()# 连接信号和槽self.connect_signals()# 准备新游戏self.prepare_new_game()def setup_ui(self):"""设置用户界面"""# 创建中央窗口部件central_widget = QWidget()self.setCentralWidget(central_widget)# 主布局main_layout = QVBoxLayout(central_widget)# 标题title_label = QLabel("猜数字游戏")title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)title_label.setFont(QFont("Arial", 20, QFont.Weight.Bold))main_layout.addWidget(title_label)# 设置选项组settings_group = QGroupBox("游戏设置")settings_layout = QHBoxLayout()# 最小值设置min_layout = QVBoxLayout()min_label = QLabel("最小值:")self.min_spinbox = QSpinBox()self.min_spinbox.setRange(1, 999)self.min_spinbox.setValue(1)min_layout.addWidget(min_label)min_layout.addWidget(self.min_spinbox)settings_layout.addLayout(min_layout)# 最大值设置max_layout = QVBoxLayout()max_label = QLabel("最大值:")self.max_spinbox = QSpinBox()self.max_spinbox.setRange(10, 1000)self.max_spinbox.setValue(100)max_layout.addWidget(max_label)max_layout.addWidget(self.max_spinbox)settings_layout.addLayout(max_layout)# 尝试次数设置attempts_layout = QVBoxLayout()attempts_label = QLabel("最大尝试次数:")self.attempts_spinbox = QSpinBox()self.attempts_spinbox.setRange(3, 20)self.attempts_spinbox.setValue(7)self.attempts_spinbox.setSpecialValueText("自动") # 表示自动计算最优尝试次数attempts_layout.addWidget(attempts_label)attempts_layout.addWidget(self.attempts_spinbox)settings_layout.addLayout(attempts_layout)# 难度设置difficulty_layout = QVBoxLayout()difficulty_label = QLabel("难度:")self.difficulty_combo = QComboBox()self.difficulty_combo.addItems(["简单", "中等", "困难", "极难"])self.difficulty_combo.setCurrentIndex(1) # 默认中等难度difficulty_layout.addWidget(difficulty_label)difficulty_layout.addWidget(self.difficulty_combo)settings_layout.addLayout(difficulty_layout)# 设置选项按钮options_layout = QVBoxLayout()self.dynamic_difficulty_check = QRadioButton("动态难度")self.dynamic_difficulty_check.setChecked(True)self.fixed_difficulty_check = QRadioButton("固定难度")difficulty_group = QButtonGroup(self)difficulty_group.addButton(self.dynamic_difficulty_check)difficulty_group.addButton(self.fixed_difficulty_check)options_layout.addWidget(self.dynamic_difficulty_check)options_layout.addWidget(self.fixed_difficulty_check)settings_layout.addLayout(options_layout)# 设置组完成settings_group.setLayout(settings_layout)main_layout.addWidget(settings_group)# 游戏状态区域game_group = QGroupBox("游戏状态")game_layout = QVBoxLayout()# 当前状态显示status_layout = QHBoxLayout()self.status_label = QLabel("准备开始")self.status_label.setFont(QFont("Arial", 12))self.timer_label = QLabel("时间: 0秒")self.attempts_label = QLabel("尝试: 0/0")status_layout.addWidget(self.status_label)status_layout.addStretch()status_layout.addWidget(self.timer_label)status_layout.addWidget(self.attempts_label)game_layout.addLayout(status_layout)# 范围指示条range_layout = QVBoxLayout()range_label = QLabel("当前范围:")self.range_progress = QProgressBar()self.range_progress.setTextVisible(False)self.range_min_label = QLabel("1")self.range_max_label = QLabel("100")range_labels_layout = QHBoxLayout()range_labels_layout.addWidget(self.range_min_label)range_labels_layout.addStretch()range_labels_layout.addWidget(self.range_max_label)range_layout.addWidget(range_label)range_layout.addWidget(self.range_progress)range_layout.addLayout(range_labels_layout)game_layout.addLayout(range_layout)# 输入区域input_layout = QHBoxLayout()guess_label = QLabel("你的猜测:")self.guess_input = QLineEdit()self.guess_input.setPlaceholderText("输入一个数字")self.guess_input.setValidator(QIntValidator())self.guess_button = QPushButton("猜测")self.guess_button.setDefault(True)input_layout.addWidget(guess_label)input_layout.addWidget(self.guess_input)input_layout.addWidget(self.guess_button)game_layout.addLayout(input_layout)# 历史记录history_layout = QVBoxLayout()history_label = QLabel("猜测历史:")self.history_text = QTextEdit()self.history_text.setReadOnly(True)self.history_text.setMaximumHeight(150)history_layout.addWidget(history_label)history_layout.addWidget(self.history_text)game_layout.addLayout(history_layout)# 提示区域hint_layout = QVBoxLayout()hint_label = QLabel("提示:")self.hint_text = QLabel("使用二分法策略可以最快猜到正确数字")self.hint_text.setWordWrap(True)self.hint_text.setStyleSheet("color: blue;")self.hotness_bar = QProgressBar()self.hotness_bar.setRange(0, 10)self.hotness_bar.setValue(0)hint_layout.addWidget(hint_label)hint_layout.addWidget(self.hint_text)hint_layout.addWidget(self.hotness_bar)game_layout.addLayout(hint_layout)# 游戏组完成game_group.setLayout(game_layout)main_layout.addWidget(game_group)# 按钮区域button_layout = QHBoxLayout()self.start_button = QPushButton("开始游戏")self.new_game_button = QPushButton("新游戏")self.statistics_button = QPushButton("查看统计")button_layout.addWidget(self.start_button)button_layout.addWidget(self.new_game_button)button_layout.addWidget(self.statistics_button)main_layout.addLayout(button_layout)# 初始状态设置self.new_game_button.setEnabled(False)self.guess_button.setEnabled(False)self.guess_input.setEnabled(False)def connect_signals(self):"""连接信号和槽"""self.start_button.clicked.connect(self.start_game)self.new_game_button.clicked.connect(self.prepare_new_game)self.guess_button.clicked.connect(self.process_guess)self.guess_input.returnPressed.connect(self.process_guess)self.statistics_button.clicked.connect(self.show_statistics)self.difficulty_combo.currentIndexChanged.connect(self.update_difficulty)self.min_spinbox.valueChanged.connect(self.update_range)self.max_spinbox.valueChanged.connect(self.update_range)def update_difficulty(self):"""根据难度设置更新游戏参数"""index = self.difficulty_combo.currentIndex()# 根据难度调整参数if index == 0: # 简单self.max_spinbox.setValue(50)self.attempts_spinbox.setValue(8)elif index == 1: # 中等self.max_spinbox.setValue(100)self.attempts_spinbox.setValue(7)elif index == 2: # 困难self.max_spinbox.setValue(500)self.attempts_spinbox.setValue(9)elif index == 3: # 极难self.max_spinbox.setValue(1000)self.attempts_spinbox.setValue(10)def update_range(self):"""更新范围设置"""# 确保最小值比最大值小if self.min_spinbox.value() >= self.max_spinbox.value():self.max_spinbox.setValue(self.min_spinbox.value() + 10)# 更新尝试次数 (如果是自动模式)if self.attempts_spinbox.value() == 3: # 特殊值表示自动min_val = self.min_spinbox.value()max_val = self.max_spinbox.value()optimal = math.ceil(math.log2(max_val - min_val + 1))self.attempts_spinbox.setValue(optimal)def prepare_new_game(self):"""准备新游戏"""# 更新UI状态self.start_button.setEnabled(True)self.new_game_button.setEnabled(False)self.guess_button.setEnabled(False)self.guess_input.setEnabled(False)# 清空游戏记录self.history_text.clear()self.hint_text.setText("使用二分法策略可以最快猜到正确数字")self.hotness_bar.setValue(0)# 更新状态self.game_active = Falseself.status_label.setText("准备开始")self.timer_label.setText("时间: 0秒")self.attempts_label.setText("尝试: 0/0")# 重置范围条min_val = self.min_spinbox.value()max_val = self.max_spinbox.value()self.range_progress.setRange(min_val, max_val)self.range_progress.setValue(min_val)self.range_progress.setFormat(f"{min_val} - {max_val}")self.range_min_label.setText(str(min_val))self.range_max_label.setText(str(max_val))# 停止计时器self.timer.stop()def start_game(self):"""开始新游戏"""# 更新配置self.config.min_number = self.min_spinbox.value()self.config.max_number = self.max_spinbox.value()self.config.max_attempts = self.attempts_spinbox.value()self.config.enable_dynamic_difficulty = self.dynamic_difficulty_check.isChecked()# 初始化引擎self.engine = GameEngine(self.config)self.engine.start_new_game()# 更新UI状态self.start_button.setEnabled(False)self.new_game_button.setEnabled(True)self.guess_button.setEnabled(True)self.guess_input.setEnabled(True)self.guess_input.setFocus()# 更新游戏状态self.game_active = Trueself.status_label.setText("游戏进行中")self.attempts_label.setText(f"尝试: 0/{self.config.max_attempts}")# 更新范围min_val = self.config.min_numbermax_val = self.config.max_numberself.range_progress.setRange(min_val, max_val)self.range_progress.setValue(min_val)self.range_min_label.setText(str(min_val))self.range_max_label.setText(str(max_val))# 开始计时self.start_time = time.time()self.last_guess_time = self.start_timeself.timer.start(100) # 100毫秒更新一次# 清空历史记录self.history_text.clear()# 添加初始提示optimal = math.ceil(math.log2(max_val - min_val + 1))self.hint_text.setText(f"理论最优猜测次数: {optimal}。首次猜测建议从中间值 {(min_val + max_val) // 2} 开始。")def process_guess(self):"""处理用户猜测"""if not self.game_active:return# 获取输入try:guess = int(self.guess_input.text())except ValueError:self.show_message("错误", "请输入一个有效的整数!")self.guess_input.clear()return# 验证猜测validation = self.engine.validate_guess(guess)if not validation['valid']:self.show_message("无效猜测", validation['error'])return# 处理猜测feedback = self.engine.process_guess(guess)# 更新分析系统self.analytics.update_strategy_analysis(guess, self.engine.game_state)# 更新界面self.update_ui_after_guess(feedback)# 清空输入框self.guess_input.clear()self.guess_input.setFocus()# 检查游戏是否结束if not self.engine.game_state.is_active():self.end_game()def update_ui_after_guess(self, feedback: Dict[str, Any]):"""猜测后更新UI"""guess = feedback['guess']diff = feedback['diff']attempts = self.engine.game_state.attemptsmax_attempts = self.config.max_attempts# 更新尝试次数self.attempts_label.setText(f"尝试: {attempts}/{max_attempts}")# 添加历史记录history_entry = f"猜测 {attempts}: {guess} "if diff == 0:history_entry += "✓ 正确!"history_entry = f"<span style='color:green; font-weight:bold;'>{history_entry}</span>"elif diff > 0:history_entry += "↑ 太小了"history_entry = f"<span style='color:blue;'>{history_entry}</span>"else:history_entry += "↓ 太大了"history_entry = f"<span style='color:red;'>{history_entry}</span>"self.history_text.append(history_entry)# 更新范围条curr_min = self.engine.game_state.current_mincurr_max = self.engine.game_state.current_maxself.range_min_label.setText(str(curr_min))self.range_max_label.setText(str(curr_max))# 计算动画self.animate_range_indicator(curr_min, curr_max)# 更新提示self.update_hints(feedback)# 计算热度self.update_hotness(feedback)def animate_range_indicator(self, min_val: int, max_val: int):"""动画更新范围指示条"""self.range_progress.setRange(self.config.min_number, self.config.max_number)full_range = self.config.max_number - self.config.min_numbercurrent_range = max_val - min_val# 计算百分比percent_left = (min_val - self.config.min_number) / full_range * 100percent_right = (max_val - self.config.min_number) / full_range * 100# 设置自定义样式style = f"""QProgressBar::chunk {{background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0,stop:0 transparent,stop:{percent_left/100} transparent,stop:{percent_left/100} rgba(0, 120, 210, 200),stop:{percent_right/100} rgba(0, 120, 210, 200),stop:{percent_right/100} transparent,stop:1 transparent);}}"""self.range_progress.setStyleSheet(style)self.range_progress.setValue(max_val) # 只是为了触发刷新def update_hints(self, feedback: Dict[str, Any]):"""更新提示信息"""attempts = self.engine.game_state.attemptscurr_min = self.engine.game_state.current_mincurr_max = self.engine.game_state.current_max# 范围提示始终显示range_hint = f"当前范围: {curr_min} - {curr_max},共 {curr_max - curr_min + 1} 个可能的数字。"# 根据尝试次数提供渐进式提示if attempts >= 1 and attempts <= 3:# 基本提示optimal_guess = (curr_min + curr_max) // 2hint = f"{range_hint}<br>二分法建议: 尝试猜测 {optimal_guess}"elif attempts >= 4 and attempts <= 5:# 质数提示target = self.engine.game_state.target_numberif target in self.engine.primes:hint = f"{range_hint}<br>提示: 目标数字是一个质数"else:# 找到最近的质数closest_primes = sorted([p for p in self.engine.primes if curr_min <= p <= curr_max],key=lambda x: abs(x - target))if closest_primes:closest = closest_primes[0]diff = abs(closest - target)hint = f"{range_hint}<br>提示: 目标数字距离质数 {closest} 相差 {diff}"else:hint = f"{range_hint}<br>提示: 在当前范围内没有质数"elif attempts >= 6:# 更详细的提示target = self.engine.game_state.target_numberlast_guess = feedback['guess']if target % 2 == 0:parity = "偶数"else:parity = "奇数"# 提供数字特性提示if target < 10:size_hint = "个位数"elif target < 100:size_hint = "两位数"else:size_hint = "三位数或更大"hint = f"{range_hint}<br>提示: 目标是一个{parity}。<br>提示: 目标是{size_hint}。"# 如果还没猜到,给出更多提示if attempts >= self.config.max_attempts - 1:# 最后的提示digit_sum = sum(int(d) for d in str(target))hint += f"<br>最终提示: 目标数字的各位数字之和是 {digit_sum}。"else:hint = range_hint# 设置提示文本self.hint_text.setText(hint)def update_hotness(self, feedback: Dict[str, Any]):"""更新热度指示器"""# 只有在尝试次数足够时显示热度if self.engine.game_state.attempts < 3:self.hotness_bar.setValue(0)returntarget = self.engine.game_state.target_numberlast_guess = feedback['guess']# 计算温度 (0-10),接近目标温度越高max_diff = self.config.max_number - self.config.min_numbertemp = 10 - min(10, int(abs(last_guess - target) / max_diff * 100))# 设置热度条颜色if temp < 3:self.hotness_bar.setStyleSheet("QProgressBar::chunk { background-color: blue; }")elif temp < 7:self.hotness_bar.setStyleSheet("QProgressBar::chunk { background-color: orange; }")else:self.hotness_bar.setStyleSheet("QProgressBar::chunk { background-color: red; }")# 设置值self.hotness_bar.setValue(temp)def update_game_timer(self):"""更新游戏计时器"""if not self.game_active:returnelapsed = time.time() - self.start_timeself.timer_label.setText(f"时间: {int(elapsed)}秒")def end_game(self):"""结束游戏"""self.game_active = Falseself.timer.stop()# 计算总时间total_time = time.time() - self.start_time# 禁用猜测self.guess_button.setEnabled(False)self.guess_input.setEnabled(False)# 更新UIif self.engine.game_state.is_won():self.status_label.setText("游戏胜利!")self.status_label.setStyleSheet("color: green; font-weight: bold;")# 显示胜利信息target = self.engine.game_state.target_numberattempts = self.engine.game_state.attemptsmessage = f"恭喜你猜对了! 目标数字是 {target}。\n"message += f"你用了 {attempts} 次尝试,耗时 {total_time:.1f} 秒。\n"# 评价表现optimal = math.ceil(math.log2(self.config.max_number - self.config.min_number + 1))if attempts <= optimal:message += f"太棒了! 你达到了理论最优解 ({optimal} 次)!"elif attempts <= optimal + 2:message += f"表现优秀! 接近最优解 ({optimal} 次)!"else:message += f"还不错! 最优解应该是 {optimal} 次。"# 检测策略strategy = self.analytics.detect_strategy()if strategy == StrategyType.BINARY:message += "\n\n你使用了二分法策略,这是最有效的策略!"elif strategy == StrategyType.LINEAR:message += "\n\n你使用了线性搜索策略,试试二分法会更快!"elif strategy == StrategyType.RANDOM:message += "\n\n你的猜测看起来很随机,有策略会更有效!"else:self.status_label.setText("游戏失败!")self.status_label.setStyleSheet("color: red; font-weight: bold;")# 显示失败信息target = self.engine.game_state.target_numberattempts = self.engine.game_state.attemptsmessage = f"很遗憾,你没有猜出正确数字。\n"message += f"目标数字是 {target}。\n"message += f"你已经尝试了 {attempts} 次,达到了最大尝试次数限制。\n"message += "要不要再来一局,尝试使用二分法策略?"# 显示结果对话框QMessageBox.information(self, "游戏结束", message)# 记录游戏结果game_result = {'target_number': self.engine.game_state.target_number,'attempts': self.engine.game_state.attempts,'history': self.engine.game_state.guess_history,'duration': total_time,'success': self.engine.game_state.is_won(),'strategy': self.analytics.detect_strategy()}self.analytics.record_game(game_result)def show_statistics(self):"""显示游戏统计数据"""stats = self.analytics.get_statistics()# 构建统计信息if stats['total_games'] == 0:QMessageBox.information(self, "统计", "还没有游戏记录!")returnmessage = "===== 游戏统计 =====\n\n"message += f"总游戏次数: {stats['total_games']}\n"message += f"胜率: {stats['win_rate']:.1f}%\n"message += f"平均尝试次数: {stats['avg_attempts']:.1f}\n"message += f"平均游戏时长: {stats['avg_duration']:.1f}秒\n"message += f"检测到的主要策略: {stats['main_strategy']}\n\n"# 策略分布message += "策略分布:\n"for strategy, count in stats['strategy_distribution'].items():if count > 0:message += f"- {strategy}: {count} 次\n"QMessageBox.information(self, "游戏统计", message)def show_message(self, title: str, message: str):"""显示消息对话框"""QMessageBox.information(self, title, message)def main():app = QApplication(sys.argv)game = NumberGuessGame()game.show()sys.exit(app.exec())if __name__ == "__main__":main()