目錄
- 猜數字游戲:從數學原理到交互體驗的完整設計指南
- 引言
- 第一章 游戲數學原理
- 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?=?log2?N?
當 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∑log2?N?N2k?1?k
第二章 游戲系統設計
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=?log2?N?×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=1104?I(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()