本文目录导读:

我来为您设计一个Java案例,用于统计足球比赛中高球传中争顶成功率。
整体设计思路
// 主要实体类 // 1. 球员类 (Player) // 2. 传中事件类 (CrossEvent) // 3. 争顶事件类 (AerialDuel) // 4. 统计服务类 (AerialDuelStatisticsService)
核心代码实现
基础实体类
import java.time.LocalDateTime;
import java.util.*;
// 球员类
class Player {
private String id;
private String name;
private String team;
private String position;
public Player(String id, String name, String team, String position) {
this.id = id;
this.name = name;
this.team = team;
this.position = position;
}
// Getters and Setters
public String getId() { return id; }
public String getName() { return name; }
public String getTeam() { return team; }
public String getPosition() { return position; }
}
// 传中事件类
class CrossEvent {
private String id;
private Player crosser; // 传中球员
private Player receiver; // 可能的接应球员
private double x; // 传中位置x坐标
private double y; // 传中位置y坐标
private LocalDateTime timestamp;
private String crossType; // 高球传中、低平球传中、45度传中等
private boolean isSuccessful; // 传中是否成功
public CrossEvent(String id, Player crosser, Player receiver,
double x, double y, String crossType) {
this.id = id;
this.crosser = crosser;
this.receiver = receiver;
this.x = x;
this.y = y;
this.timestamp = LocalDateTime.now();
this.crossType = crossType;
}
// Getters and Setters
public String getId() { return id; }
public Player getCrosser() { return crosser; }
public Player getReceiver() { return receiver; }
public double getX() { return x; }
public double getY() { return y; }
public String getCrossType() { return crossType; }
public boolean isSuccessful() { return isSuccessful; }
public void setSuccessful(boolean successful) { isSuccessful = successful; }
}
// 争顶事件类
class AerialDuel {
private String id;
private CrossEvent crossEvent;
private Player attacker; // 进攻球员(争顶球员)
private Player defender; // 防守球员
private boolean isWonByAttacker; // 进攻方是否赢得争顶
private boolean ledToShooting; // 争顶后是否形成射门
private double height; // 争顶高度
private LocalDateTime timestamp;
public AerialDuel(String id, CrossEvent crossEvent, Player attacker,
Player defender, double height) {
this.id = id;
this.crossEvent = crossEvent;
this.attacker = attacker;
this.defender = defender;
this.height = height;
this.timestamp = LocalDateTime.now();
}
// Getters and Setters
public String getId() { return id; }
public CrossEvent getCrossEvent() { return crossEvent; }
public Player getAttacker() { return attacker; }
public Player getDefender() { return defender; }
public boolean isWonByAttacker() { return isWonByAttacker; }
public void setWonByAttacker(boolean wonByAttacker) { isWonByAttacker = wonByAttacker; }
public boolean isLedToShooting() { return ledToShooting; }
public void setLedToShooting(boolean ledToShooting) { this.ledToShooting = ledToShooting; }
public double getHeight() { return height; }
}
统计服务类
class AerialDuelStatisticsService {
// 存储所有争顶事件
private List<AerialDuel> aerialDuels = new ArrayList<>();
// 添加争顶事件
public void addAerialDuel(AerialDuel duel) {
aerialDuels.add(duel);
}
// 计算整体争顶成功率
public double calculateOverallSuccessRate() {
if (aerialDuels.isEmpty()) {
return 0.0;
}
long successfulDuels = aerialDuels.stream()
.filter(AerialDuel::isWonByAttacker)
.count();
return (double) successfulDuels / aerialDuels.size() * 100;
}
// 按球队统计争顶成功率
public Map<String, Double> calcularTeamSuccessRate() {
Map<String, List<AerialDuel>> teamDuels = new HashMap<>();
for (AerialDuel duel : aerialDuels) {
String team = duel.getAttacker().getTeam();
teamDuels.computeIfAbsent(team, k -> new ArrayList<>()).add(duel);
}
Map<String, Double> result = new HashMap<>();
for (Map.Entry<String, List<AerialDuel>> entry : teamDuels.entrySet()) {
long total = entry.getValue().size();
long won = entry.getValue().stream()
.filter(AerialDuel::isWonByAttacker)
.count();
result.put(entry.getKey(), (double) won / total * 100);
}
return result;
}
// 按球员统计争顶成功率
public Map<String, Double> calculatePlayerSuccessRate() {
Map<String, List<AerialDuel>> playerDuels = new HashMap<>();
for (AerialDuel duel : aerialDuels) {
String playerId = duel.getAttacker().getId();
playerDuels.computeIfAbsent(playerId, k -> new ArrayList<>()).add(duel);
}
Map<String, Double> result = new HashMap<>();
for (Map.Entry<String, List<AerialDuel>> entry : playerDuels.entrySet()) {
long total = entry.getValue().size();
long won = entry.getValue().stream()
.filter(AerialDuel::isWonByAttacker)
.count();
result.put(entry.getKey(), (double) won / total * 100);
}
return result;
}
// 按传中类型统计争顶成功率
public Map<String, Double> calculateSuccessRateByCrossType() {
Map<String, List<AerialDuel>> crossTypeDuels = new HashMap<>();
for (AerialDuel duel : aerialDuels) {
String crossType = duel.getCrossEvent().getCrossType();
crossTypeDuels.computeIfAbsent(crossType, k -> new ArrayList<>()).add(duel);
}
Map<String, Double> result = new HashMap<>();
for (Map.Entry<String, List<AerialDuel>> entry : crossTypeDuels.entrySet()) {
long total = entry.getValue().size();
long won = entry.getValue().stream()
.filter(AerialDuel::isWonByAttacker)
.count();
result.put(entry.getKey(), (double) won / total * 100);
}
return result;
}
// 统计争顶后形成射门的效率
public double calculateShootingConversionRate() {
if (aerialDuels.isEmpty()) {
return 0.0;
}
long ledToShooting = aerialDuels.stream()
.filter(AerialDuel::isWonByAttacker)
.filter(AerialDuel::isLedToShooting)
.count();
return (double) ledToShooting / aerialDuels.size() * 100;
}
// 按球员位置统计争顶成功率
public Map<String, Double> calculateSuccessRateByPosition() {
Map<String, List<AerialDuel>> positionDuels = new HashMap<>();
for (AerialDuel duel : aerialDuels) {
String position = duel.getAttacker().getPosition();
positionDuels.computeIfAbsent(position, k -> new ArrayList<>()).add(duel);
}
Map<String, Double> result = new HashMap<>();
for (Map.Entry<String, List<AerialDuel>> entry : positionDuels.entrySet()) {
long total = entry.getValue().size();
long won = entry.getValue().stream()
.filter(AerialDuel::isWonByAttacker)
.count();
result.put(entry.getKey(), (double) won / total * 100);
}
return result;
}
// 综合统计报告
public void printDetailedStatistics() {
System.out.println("========== 高球传中争顶成功率统计报告 ==========");
System.out.println("1. 整体争顶成功率: " + String.format("%.1f%%", calculateOverallSuccessRate()));
System.out.println("2. 争顶后形成射门转化率: " + String.format("%.1f%%", calculateShootingConversionRate()));
System.out.println("\n3. 各球队争顶成功率:");
calcularTeamSuccessRate().forEach((team, rate) ->
System.out.println(" - " + team + ": " + String.format("%.1f%%", rate)));
System.out.println("\n4. 各球员争顶成功率:");
calculatePlayerSuccessRate().entrySet().stream()
.sorted(Map.Entry.<String, Double>comparingByValue().reversed())
.forEach(entry ->
System.out.println(" - 球员ID " + entry.getKey() + ": " + String.format("%.1f%%", entry.getValue())));
System.out.println("\n5. 各传中类型争顶成功率:");
calculateSuccessRateByCrossType().forEach((type, rate) ->
System.out.println(" - " + type + ": " + String.format("%.1f%%", rate)));
System.out.println("\n6. 各位置球员争顶成功率:");
calculateSuccessRateByPosition().forEach((position, rate) ->
System.out.println(" - " + position + ": " + String.format("%.1f%%", rate)));
}
}
测试主程序
import java.util.Random;
public class FootballStatisticsDemo {
public static void main(String[] args) {
// 创建球员
List<Player> players = createPlayers();
// 创建统计服务
AerialDuelStatisticsService statisticsService = new AerialDuelStatisticsService();
// 模拟比赛数据
Random random = new Random(42); // 固定种子便于测试
// 模拟100次争顶事件
for (int i = 0; i < 100; i++) {
Player attacker = players.get(random.nextInt(players.size()));
Player defender = players.get(random.nextInt(players.size()));
Player crosser = players.get(random.nextInt(players.size()));
// 确保进攻和防守不是同一个球员
while (attacker.getId().equals(defender.getId())) {
defender = players.get(random.nextInt(players.size()));
}
// 创建传中事件
String[] crossTypes = {"高球", "低平球", "45度传中", "下底传中"};
CrossEvent crossEvent = new CrossEvent(
"C" + i,
crosser,
attacker,
random.nextDouble() * 100,
random.nextDouble() * 50,
crossTypes[random.nextInt(crossTypes.length)]
);
// 创建争顶事件
AerialDuel duel = new AerialDuel(
"AD" + i,
crossEvent,
attacker,
defender,
random.nextDouble() * 2 + 1.5 // 高度1.5-3.5米
);
// 随机设置争顶结果
duel.setWonByAttacker(random.nextBoolean());
duel.setLedToShooting(random.nextDouble() < 0.3); // 30%概率形成射门
// 传中成功与否与争顶结果相关
crossEvent.setSuccessful(duel.isWonByAttacker());
statisticsService.addAerialDuel(duel);
}
// 打印详细统计报告
statisticsService.printDetailedStatistics();
// 额外示例:不同位置的争顶成功率对比
System.out.println("\n========== 位置分析 ==========");
Map<String, Double> positionStats = statisticsService.calculateSuccessRateByPosition();
positionStats.entrySet().stream()
.sorted(Map.Entry.<String, Double>comparingByValue().reversed())
.forEach(entry -> {
StringBuilder bar = new StringBuilder();
int barLength = (int) (entry.getValue() / 2);
for (int j = 0; j < barLength; j++) {
bar.append("█");
}
System.out.println(String.format("%-10s %5.1f%% %s",
entry.getKey(), entry.getValue(), bar.toString()));
});
}
// 创建示例球员
private static List<Player> createPlayers() {
List<Player> players = new ArrayList<>();
// 前锋
players.add(new Player("ST1", "罗纳尔多", "皇马", "前锋"));
players.add(new Player("ST2", "莱万", "巴萨", "前锋"));
players.add(new Player("ST3", "凯恩", "曼城", "前锋"));
// 中场
players.add(new Player("MID1", "德布劳内", "曼城", "中场"));
players.add(new Player("MID2", "克罗斯", "皇马", "中场"));
players.add(new Player("MID3", "B费", "曼联", "中场"));
// 后卫
players.add(new Player("DEF1", "范迪克", "利物浦", "后卫"));
players.add(new Player("DEF2", "拉莫斯", "巴黎", "后卫"));
players.add(new Player("DEF3", "鲁本·迪亚斯", "曼城", "后卫"));
return players;
}
}
核心功能特性
- 多维度统计:支持按球队、球员、位置、传中类型统计
- 转化率分析:分析争顶后形成射门的效率
- 可视化展示:使用条形图直观展示统计数据
- 数据模拟:提供随机数据供测试使用
扩展建议
- 添加时间序列分析:按时间段统计争顶成功率变化
- 对抗分析:分析特定球员之间的争顶对抗数据
- 空间分析:结合传中位置坐标进行热点分析
- 机器学习预测:基于历史数据预测争顶成功率
这个案例涵盖了高球传中争顶成功率统计的核心功能,可以根据实际需求进一步扩展和优化。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播