我将为您开发一个功能完整的AI猜拳游戏系统,包含多种博弈策略和统计分析功能。
项目结构
ai_rock_paper_scissors/
├── main.py # 主程序入口
├── game_engine.py # 游戏引擎模块
├── ai_strategies.py # AI策略模块
├── statistics.py # 统计分析模块
├── player.py # 玩家类模块
├── utils.py # 工具函数模块
├── data_manager.py # 数据管理模块
├── config.py # 配置文件
├── requirements.txt # 依赖包列表
├── README.md # 项目说明
├── knowledge_cards.md # 核心知识点卡片
└── data/ # 数据存储目录
├── game_history.json
└── player_stats.json
1. requirements.txt
pandas>=1.3.0
numpy>=1.21.0
matplotlib>=3.5.0
seaborn>=0.11.0
tqdm>=4.64.0
collections-extended>=2.0.0
2. config.py - 配置文件
"""
AI猜拳游戏配置文件
包含游戏参数、AI策略配置、界面设置等
"""
# 游戏基础配置
GAME_CONFIG = {
"choices": ["石头", "剪刀", "布"],
"choice_symbols": {"石头": "✊", "剪刀": "✌️", "布": "✋"},
"win_rules": {
"石头": "剪刀", # 石头赢剪刀
"剪刀": "布", # 剪刀赢布
"布": "石头" # 布赢石头
},
"rounds_default": 10,
"save_history": True,
"show_animation": True
}
# AI策略配置
AI_STRATEGIES = {
"random": {
"name": "随机策略",
"description": "完全随机选择,作为基准策略",
"weight": 1.0
},
"frequency": {
"name": "频率分析策略",
"description": "分析对手历史选择频率,预测并克制",
"weight": 1.2,
"learning_rate": 0.1
},
"pattern": {
"name": "模式识别策略",
"description": "识别对手的选择模式,预测下一步",
"weight": 1.3,
"pattern_length": 3
},
"counter": {
"name": "反击策略",
"description": "针对对手的优势选择进行反击",
"weight": 1.1
},
"mixed": {
"name": "混合策略",
"description": "结合多种策略,动态调整权重",
"weight": 1.4,
"strategies": ["frequency", "pattern", "counter"]
}
}
# 统计分析配置
STATS_CONFIG = {
"track_detailed": True,
"save_interval": 10, # 每多少局保存一次数据
"charts_enabled": True,
"export_formats": ["json", "csv", "txt"]
}
# 难度等级配置
DIFFICULTY_LEVELS = {
"easy": {
"name": "简单",
"ai_strategy": "random",
"win_rate_target": 0.3
},
"normal": {
"name": "普通",
"ai_strategy": "frequency",
"win_rate_target": 0.5
},
"hard": {
"name": "困难",
"ai_strategy": "mixed",
"win_rate_target": 0.7
},
"expert": {
"name": "专家",
"ai_strategy": "pattern",
"win_rate_target": 0.8
}
}
3. utils.py - 工具函数模块
"""
工具函数模块
提供游戏所需的各种辅助函数
"""
import random
import time
import json
from typing import List, Dict, Tuple, Optional
from collections import Counter, defaultdict
from datetime import datetime
import numpy as np
class GameUtils:
"""游戏工具类"""
@staticmethod
def get_choice_index(choice: str) -> int:
"""
获取选择对应的索引
Args:
choice: 选择名称 ("石头", "剪刀", "布")
Returns:
对应的索引 (0, 1, 2)
"""
choices = ["石头", "剪刀", "布"]
try:
return choices.index(choice)
except ValueError:
raise ValueError(f"无效选择: {choice},有效选择为: {choices}")
@staticmethod
def get_choice_name(index: int) -> str:
"""
获取索引对应的选择名称
Args:
index: 索引 (0, 1, 2)
Returns:
选择名称
"""
choices = ["石头", "剪刀", "布"]
if 0 <= index < len(choices):
return choices[index]
else:
raise ValueError(f"无效索引: {index}")
@staticmethod
def determine_winner(player_choice: str, ai_choice: str,
win_rules: Dict[str, str]) -> str:
"""
判断胜负
Args:
player_choice: 玩家选择
ai_choice: AI选择
win_rules: 胜负规则
Returns:
"player": 玩家获胜, "ai": AI获胜, "tie": 平局
"""
if player_choice == ai_choice:
return "tie"
# 检查玩家是否获胜
if win_rules[player_choice] == ai_choice:
return "player"
else:
return "ai"
@staticmethod
def calculate_win_rate(wins: int, total_games: int) -> float:
"""
计算胜率
Args:
wins: 获胜次数
total_games: 总游戏次数
Returns:
胜率 (0.0-1.0)
"""
if total_games == 0:
return 0.0
return wins / total_games
@staticmethod
def format_percentage(value: float) -> str:
"""
格式化百分比显示
Args:
value: 小数形式的比例
Returns:
格式化的百分比字符串
"""
return f"{value:.1%}"
@staticmethod
def animate_text(text: str, delay: float = 0.05):
"""
文字动画效果
Args:
text: 要显示的文本
delay: 字符间延迟时间
"""
for char in text:
print(char, end='', flush=True)
time.sleep(delay)
print()
class DataUtils:
"""数据处理工具类"""
@staticmethod
def save_json(data: Dict, filename: str):
"""
保存数据到JSON文件
Args:
data: 要保存的数据
filename: 文件名
"""
try:
with open(filename, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
except Exception as e:
print(f"保存文件失败: {e}")
@staticmethod
def load_json(filename: str) -> Dict:
"""
从JSON文件加载数据
Args:
filename: 文件名
Returns:
加载的数据字典
"""
try:
with open(filename, 'r', encoding='utf-8') as f:
return json.load(f)
except FileNotFoundError:
return {}
except Exception as e:
print(f"加载文件失败: {e}")
return {}
@staticmethod
def calculate_trend(values: List[float], window_size: int = 5) -> float:
"""
计算数值趋势
Args:
values: 数值列表
window_size: 滑动窗口大小
Returns:
趋势值 (-1到1,负值表示下降趋势,正值表示上升趋势)
"""
if len(values) < window_size:
return 0.0
recent_values = values[-window_size:]
x = np.arange(len(recent_values))
y = np.array(recent_values)
# 计算线性回归斜率
slope = np.polyfit(x, y, 1)[0]
# 归一化到[-1, 1]范围
normalized_slope = max(-1.0, min(1.0, slope * 10))
return normalized_slope
class StrategyUtils:
"""策略工具类"""
@staticmethod
def detect_pattern(sequence: List[str], pattern_length: int = 3) -> Optional[str]:
"""
检测序列中的模式
Args:
sequence: 选择序列
pattern_length: 模式长度
Returns:
预测的下一项,如果没有检测到模式则返回None
"""
if len(sequence) < pattern_length * 2:
return None
# 查找最近的模式
recent_pattern = sequence[-pattern_length:]
pattern_str = ''.join(recent_pattern)
# 在历史中查找相同模式后的选择
occurrences = []
for i in range(len(sequence) - pattern_length * 2):
if sequence[i:i+pattern_length] == recent_pattern:
next_choice = sequence[i + pattern_length]
occurrences.append(next_choice)
if occurrences:
# 返回最常见的后续选择
counter = Counter(occurrences)
return counter.most_common(1)[0][0]
return None
@staticmethod
def calculate_frequency_distribution(sequence: List[str]) -> Dict[str, float]:
"""
计算频率分布
Args:
sequence: 选择序列
Returns:
各选择的频率字典
"""
if not sequence:
return {"石头": 0.33, "剪刀": 0.33, "布": 0.34}
counter = Counter(sequence)
total = len(sequence)
return {
choice: count / total
for choice, count in counter.items()
}
@staticmethod
def get_counter_choice(target_choice: str) -> str:
"""
获取克制指定选择的选择
Args:
target_choice: 目标选择
Returns:
能克制目标选择的选择
"""
counter_map = {
"石头": "布", # 布克石头
"剪刀": "石头", # 石头克剪刀
"布": "剪刀" # 剪刀克布
}
return counter_map.get(target_choice, "石头")
class ValidationUtils:
"""数据验证工具类"""
@staticmethod
def validate_player_choice(choice: str) -> bool:
"""
验证玩家选择是否有效
Args:
choice: 玩家选择
Returns:
是否有效
"""
valid_choices = ["石头", "剪刀", "布", "1", "2", "3"]
return choice in valid_choices
@staticmethod
def normalize_choice(choice: str) -> str:
"""
标准化选择输入
Args:
choice: 原始输入
Returns:
标准化后的选择
"""
choice_map = {
"1": "石头",
"2": "剪刀",
"3": "布",
"石头": "石头",
"剪刀": "剪刀",
"布": "布"
}
return choice_map.get(choice, choice)
@staticmethod
def validate_game_config(config: Dict) -> bool:
"""
验证游戏配置是否有效
Args:
config: 配置字典
Returns:
是否有效
"""
required_keys = ["choices", "win_rules", "rounds_default"]
return all(key in config for key in required_keys)
4. player.py - 玩家类模块
"""
玩家类模块
定义玩家和AI的行为和属性
"""
from typing import List, Dict, Optional
from dataclasses import dataclass, field
from utils import GameUtils, StrategyUtils, ValidationUtils
@dataclass
class Player:
"""玩家基类"""
name: str
player_type: str = "human" # "human" 或 "ai"
stats: Dict[str, int] = field(default_factory=lambda: {
"wins": 0, "losses": 0, "ties": 0, "total_games": 0
})
choice_history: List[str] = field(default_factory=list)
win_rate_history: List[float] = field(default_factory=list)
def make_choice(self, **kwargs) -> str:
"""
做出选择(由子类实现)
Args:
**kwargs: 额外参数
Returns:
选择结果
"""
raise NotImplementedError("子类必须实现此方法")
def update_stats(self, result: str):
"""
更新统计数据
Args:
result: 游戏结果 ("win", "lose", "tie")
"""
self.stats["total_games"] += 1
if result == "win":
self.stats["wins"] += 1
elif result == "lose":
self.stats["losses"] += 1
elif result == "tie":
self.stats["ties"] += 1
# 更新胜率历史
current_win_rate = GameUtils.calculate_win_rate(
self.stats["wins"], self.stats["total_games"]
)
self.win_rate_history.append(current_win_rate)
def get_current_win_rate(self) -> float:
"""
获取当前胜率
Returns:
当前胜率
"""
return GameUtils.calculate_win_rate(
self.stats["wins"], self.stats["total_games"]
)
def get_choice_frequency(self) -> Dict[str, float]:
"""
获取选择频率
Returns:
各选择的频率
"""
return StrategyUtils.calculate_frequency_distribution(self.choice_history)
def add_choice_to_history(self, choice: str):
"""
添加选择到历史记录
Args:
choice: 选择结果
"""
self.choice_history.append(choice)
# 限制历史记录长度,避免内存占用过多
max_history = 1000
if len(self.choice_history) > max_history:
self.choice_history = self.choice_history[-max_history:]
class HumanPlayer(Player):
"""人类玩家类"""
def __init__(self, name: str = "玩家"):
super().__init__(name=name, player_type="human")
def make_choice(self, **kwargs) -> str:
"""
人类玩家做出选择
Args:
**kwargs: 额外参数,包括可用选择列表
Returns:
选择结果
"""
available_choices = kwargs.get("choices", ["石头", "剪刀", "布"])
while True:
try:
print(f"\n{self.name},请选择:")
for i, choice in enumerate(available_choices, 1):
print(f" {i}. {choice}")
user_input = input("\n请输入选择 (1-3 或 石头/剪刀/布): ").strip()
if ValidationUtils.validate_player_choice(user_input):
choice = ValidationUtils.normalize_choice(user_input)
# 验证选择是否在可用选项中
if choice in available_choices:
self.add_choice_to_history(choice)
return choice
else:
print("❌ 无效选择,请重试")
else:
print("❌ 输入格式错误,请重试")
except KeyboardInterrupt:
print("\n\n游戏被用户中断")
raise
except Exception as e:
print(f"❌ 发生错误: {e},请重试")
class AIPlayer(Player):
"""AI玩家类"""
def __init__(self, name: str = "AI", strategy: str = "random"):
super().__init__(name=name, player_type="ai")
self.strategy = strategy
self.strategy_weights = kwargs.get("strategy_weights", {})
self.opponent_history = []
self.pattern_memory = defaultdict(list)
def make_choice(self, **kwargs) -> str:
"""
AI根据策略做出选择
Args:
**kwargs: 额外参数,包括对手历史、游戏规则等
Returns:
选择结果
"""
opponent_history = kwargs.get("opponent_history", [])
available_choices = kwargs.get("choices", ["石头", "剪刀", "布"])
win_rules = kwargs.get("win_rules", {})
# 根据策略选择
if self.strategy == "random":
choice = self._random_strategy(available_choices)
elif self.strategy == "frequency":
choice = self._frequency_strategy(opponent_history, available_choices)
elif self.strategy == "pattern":
choice = self._pattern_strategy(opponent_history, available_choices)
elif self.strategy == "counter":
choice = self._counter_strategy(opponent_history, available_choices)
elif self.strategy == "mixed":
choice = self._mixed_strategy(opponent_history, available_choices, kwargs)
else:
choice = self._random_strategy(available_choices)
self.add_choice_to_history(choice)
return choice
def _random_strategy(self, available_choices: List[str]) -> str:
"""随机策略"""
return random.choice(available_choices)
def _frequency_strategy(self, opponent_history: List[str],
available_choices: List[str]) -> str:
"""
频率分析策略
分析对手历史选择,预测并克制最常出现的选择
"""
if not opponent_history:
return self._random_strategy(available_choices)
# 计算对手选择频率
freq_dist = StrategyUtils.calculate_frequency_distribution(opponent_history)
# 找出对手最常选择的选项
most_frequent = max(freq_dist.items(), key=lambda x: x[1])[0]
# 选择能克制对手最常选择项的选项
counter_choice = StrategyUtils.get_counter_choice(most_frequent)
# 确保选择可用
if counter_choice in available_choices:
return counter_choice
else:
return self._random_strategy(available_choices)
def _pattern_strategy(self, opponent_history: List[str],
available_choices: List[str]) -> str:
"""
模式识别策略
识别对手的选择模式,预测下一步
"""
if len(opponent_history) < 6: # 需要足够的历史数据
return self._frequency_strategy(opponent_history, available_choices)
# 尝试检测模式
predicted_choice = StrategyUtils.detect_pattern(opponent_history, pattern_length=3)
if predicted_choice:
# 如果检测到模式,选择克制预测选择的选项
counter_choice = StrategyUtils.get_counter_choice(predicted_choice)
if counter_choice in available_choices:
return counter_choice
# 如果没检测到模式,回退到频率策略
return self._frequency_strategy(opponent_history, available_choices)
def _counter_strategy(self, opponent_history: List[str],
available_choices: List[str]) -> str:
"""
反击策略
针对对手的优势选择进行反击
"""
if not opponent_history:
return self._random_strategy(available_choices)
# 分析对手的"优势"(即经常获胜的选择)
# 这里简化处理,直接找对手最近的选择趋势
recent_choices = opponent_history[-5:] if len(opponent_history) >= 5 else opponent_history
if recent_choices:
# 选择克制对手最近选择的选项
last_choice = recent_choices[-1]
counter_choice = StrategyUtils.get_counter_choice(last_choice)
if counter_choice in available_choices:
return counter_choice
return self._random_strategy(available_choices)
def _mixed_strategy(self, opponent_history: List[str],
available_choices: List[str],
kwargs: Dict) -> str:
"""
混合策略
结合多种策略,动态调整权重
"""
strategies = ["frequency", "pattern", "counter"]
weights = [0.4, 0.4, 0.2] # 默认权重
# 根据历史数据调整权重
if len(opponent_history) > 10:
# 如果有足够数据,增加模式识别的权重
weights = [0.3, 0.5, 0.2]
elif len(opponent_history) < 5:
# 如果数据较少,主要使用频率和反击策略
weights = [0.5, 0.2, 0.3]
# 随机选择策略(根据权重)
chosen_strategy = random.choices(strategies, weights=weights)[0]
# 调用对应策略
if chosen_strategy == "frequency":
return self._frequency_strategy(opponent_history, available_choices)
elif chosen_strategy == "pattern":
return self._pattern_strategy(opponent_history, available_choices)
elif chosen_strategy == "counter":
return self._counter_strategy(opponent_history, available_choices)
else:
return self._random_strategy(available_choices)
def update_opponent_history(self, opponent_choice: str):
"""
更新对手历史记录
Args:
opponent_choice: 对手的选择
"""
self.opponent_history.append(opponent_choice)
# 限制历史记录长度
max_history = 500
if len(self.opponent_history) > max_history:
self.opponent_history = self.opponent_history[-max_history:]
def set_strategy(self, strategy: str):
"""
设置AI策略
Args:
strategy: 策略名称
"""
self.strategy = strategy
def get_strategy_description(self) -> str:
"""
获取策略描述
Returns:
策略描述
"""
from config import AI_STRATEGIES
strategy_info = AI_STRATEGIES.get(self.strategy, {})
return strategy_info.get("description", "未知策略")
5. ai_strategies.py - AI策略模块
"""
AI策略模块
实现各种高级AI策略算法
"""
import numpy as np
from typing import List, Dict, Tuple, Optional
from collections import defaultdict, deque
from utils import StrategyUtils, GameUtils
import random
class AdvancedAIStrategies:
"""高级AI策略类"""
def __init__(self):
self.strategy_performance = defaultdict(list)
self.adaptation_threshold = 0.1
def markov_chain_strategy(self, history: List[str], order: int = 1) -> Optional[str]:
"""
马尔可夫链策略
基于状态转移概率预测对手下一步
Args:
history: 历史选择序列
order: 马尔可夫链阶数
Returns:
预测的下一项
"""
if len(history) < order + 1:
return None
# 构建状态转移矩阵
transitions = defaul
关注我,有更多实用程序等着你!