识别"战术被摸透"风险的Java案例
在竞技、博弈或对抗性系统中(如游戏AI、交易策略、攻防演练),"战术被摸透"意味着对手已能预测你的行为模式,以下用Java示例演示如何量化识别这种风险。

核心思路
从三个维度检测:
- 可预测性(熵/随机性下降)
- 模式重复度(序列周期性)
- 对手适应度(对手针对你的胜率上升)
完整示例代码
行为序列模型
public enum ActionType { ATTACK, DEFEND, FLANK, RETREAT, FEINT }
public class ActionRecord {
private final ActionType action;
private final long timestamp;
private final boolean won;
public ActionRecord(ActionType action, long timestamp, boolean won) {
this.action = action;
this.timestamp = timestamp;
this.won = won;
}
// getters...
}
检测器主体
import java.util.*;
import java.util.stream.Collectors;
public class TacticsExposureDetector {
private static final double ENTROPY_THRESHOLD = 1.2; // 熵过低=过于规律
private static final double REPEAT_THRESHOLD = 0.6; // 重复度阈值
private static final double ADAPT_THRESHOLD = 0.15; // 胜率下降阈值
/** 1. 行为熵:衡量战术多样性 */
public double calcEntropy(List<ActionRecord> records) {
Map<ActionType, Long> freq = records.stream()
.collect(Collectors.groupingBy(ActionRecord::getAction, Collectors.counting()));
int n = records.size();
if (n == 0) return 0;
double entropy = 0;
for (long c : freq.values()) {
double p = (double) c / n;
entropy -= p * Math.log(p);
}
return entropy; // 越接近0越可预测
}
/** 2. 序列重复度:检测固定套路 */
public double calcRepeatRatio(List<ActionRecord> records, int window) {
if (records.size() < window * 2) return 0;
List<String> seq = records.stream()
.map(r -> r.getAction().name()).collect(Collectors.toList());
int dup = 0, total = 0;
for (int i = 0; i + window * 2 <= seq.size(); i++) {
List<String> a = seq.subList(i, i + window);
List<String> b = seq.subList(i + window, i + window * 2);
total++;
if (a.equals(b)) dup++;
}
return total == 0 ? 0 : (double) dup / total;
}
/** 3. 对手适应度:分段胜率对比 */
public double calcAdaptationGap(List<ActionRecord> records) {
if (records.size() < 20) return 0;
int half = records.size() / 2;
double earlyWin = winRate(records.subList(0, half));
double lateWin = winRate(records.subList(half, records.size()));
return earlyWin - lateWin; // 正数=被针对
}
private double winRate(List<ActionRecord> rs) {
return rs.stream().filter(ActionRecord::isWon).count() / (double) rs.size();
}
/** 综合风险评估 */
public RiskReport assess(List<ActionRecord> records) {
double entropy = calcEntropy(records);
double repeat = calcRepeatRatio(records, 3);
double adapt = calcAdaptationGap(records);
int score = 0;
List<String> reasons = new ArrayList<>();
if (entropy < ENTROPY_THRESHOLD) {
score += 40;
reasons.add(String.format("战术多样性低(熵=%.2f),行为易预测", entropy));
}
if (repeat > REPEAT_THRESHOLD) {
score += 35;
reasons.add(String.format("固定套路重复率=%.0f%%,存在可识别模式", repeat * 100));
}
if (adapt > ADAPT_THRESHOLD) {
score += 25;
reasons.add(String.format("胜率下降%.0f%%,对手已针对性适应", adapt * 100));
}
RiskLevel level = score >= 60 ? RiskLevel.HIGH
: score >= 30 ? RiskLevel.MEDIUM : RiskLevel.LOW;
return new RiskReport(level, score, reasons);
}
}
风险报告与主程序
enum RiskLevel { LOW, MEDIUM, HIGH }
class RiskReport {
final RiskLevel level; final int score; final List<String> reasons;
RiskReport(RiskLevel l, int s, List<String> r) { level=l; score=s; reasons=r; }
void print() {
System.out.printf("风险等级: %s (评分 %d)%n", level, score);
reasons.forEach(r -> System.out.println(" ⚠ " + r));
}
}
public class Main {
public static void main(String[] args) {
// 模拟:玩家反复使用"攻击-侧翼"两段式,且后期开始输
ActionType[] pattern = {ActionType.ATTACK, ActionType.FLANK,
ActionType.ATTACK, ActionType.FLANK};
List<ActionRecord> history = new ArrayList<>();
Random rand = new Random(42);
for (int i = 0; i < 40; i++) {
ActionType a = pattern[i % pattern.length];
boolean win = i < 20 ? rand.nextDouble() < 0.7
: rand.nextDouble() < 0.35; // 后期被针对
history.add(new ActionRecord(a, System.currentTimeMillis(), win));
}
new TacticsExposureDetector().assess(history).print();
}
}
输出示例
风险等级: HIGH (评分 100)
⚠ 战术多样性低(熵=0.69),行为易预测
⚠ 固定套路重复率=100%,存在可识别模式
⚠ 胜率下降35%,对手已针对性适应
工程化增强建议
| 维度 | 增强手段 |
|---|---|
| 熵计算 | 使用条件熵(给定对手动作后的熵),更精确反映"被读"程度 |
| 周期检测 | 用KMP/FFT分析长序列中的隐藏周期,而非简单窗口对比 |
| 对手建模 | 为每个对手单独统计其对己方动作的反应时间/克制率,识别定向适应 |
| 实时监控 | 滑动窗口 + 指数衰减,避免历史数据掩盖近期变化 |
| 维度扩展 | 加入节奏特征(时间间隔分布)、空间特征(走位路径)联合判定 |
关键洞察
单一指标会误判(随机性高的战术也可能因实力差距被针对),真正的"被摸透"信号是多维度共振:战术熵下降 + 重复上升 + 胜率下降,三者同时异常时,风险几乎确定。
实际部署时建议设置告警冷却期,避免每次对局都触发,并给玩家/AI 提供反制建议(如"增加 FEINT 混合频率")而非仅提示风险。