news 2026/4/15 10:19:01

开发简易AI猜拳游戏,机器随机出拳,记录对战胜胜率,探索简单博弈策略。

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
开发简易AI猜拳游戏,机器随机出拳,记录对战胜胜率,探索简单博弈策略。

我将为您开发一个功能完整的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

关注我,有更多实用程序等着你!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/13 6:59:47

为什么你的泛型代码不安全?C17类型检查机制全剖析

第一章&#xff1a;C17泛型类型安全的核心挑战C17标准虽未直接引入泛型编程语法&#xff0c;但在现代C语言实践中&#xff0c;开发者常借助宏与类型推导技巧模拟泛型行为。这种模式在提升代码复用性的同时&#xff0c;也带来了显著的类型安全挑战。由于缺乏编译时类型检查机制&…

作者头像 李华
网站建设 2026/4/9 2:42:31

YOLOFuse验证集评估指标展示:precision、recall、mAP含义说明

YOLOFuse验证集评估指标解析&#xff1a;深入理解precision、recall与mAP 在智能监控系统调试过程中&#xff0c;你是否曾遇到这样的困惑&#xff1a;模型输出的 mAP0.5 达到了95%&#xff0c;但实际部署时仍频繁漏检行人&#xff1f;或者 precision 很高&#xff0c;却不断将路…

作者头像 李华
网站建设 2026/4/12 17:32:20

YOLOFuse垃圾投放识别引导系统

YOLOFuse垃圾投放识别引导系统&#xff1a;多模态融合检测技术深度解析 在城市智能治理的浪潮中&#xff0c;垃圾分类早已不再是简单的“贴标签”运动。当清晨的雾气尚未散去&#xff0c;或是深夜楼道灯光昏暗时&#xff0c;传统基于可见光摄像头的识别系统常常陷入“失明”状…

作者头像 李华
网站建设 2026/4/12 13:29:14

YOLOFuse无人机巡检系统整合方案

YOLOFuse无人机巡检系统整合方案 在电力线路深夜巡查中&#xff0c;操作员盯着屏幕却难以分辨&#xff1a;远处那团模糊的热源是过载电缆还是飞鸟&#xff1f;白天阳光直射下&#xff0c;反光的绝缘子又频繁触发误报。这类“看得见但认不准”的困境&#xff0c;正是传统单模态视…

作者头像 李华
网站建设 2026/4/12 18:55:26

YOLOFuse消防救援现场感知增强

YOLOFuse&#xff1a;消防救援场景下的多模态感知增强实践 在浓烟滚滚的火灾现场&#xff0c;能见度可能不足一米。传统摄像头几乎失效&#xff0c;而被困人员的生命体征却正随着时间流逝悄然消失。如何让机器“看穿”烟雾&#xff1f;这不仅是影视作品中的科技幻想&#xff0…

作者头像 李华
网站建设 2026/4/8 0:11:34

YOLOFuse CoreML导出实验:iOS设备部署初探

YOLOFuse CoreML导出实验&#xff1a;iOS设备部署初探 在夜间监控摄像头一片漆黑、自动驾驶车辆驶入浓雾、消防员冲进烟尘弥漫的建筑时&#xff0c;传统视觉系统往往“失明”。而与此同时&#xff0c;智能手机却早已具备运行复杂AI模型的能力——这正是边缘智能的转折点&#x…

作者头像 李华