本文目录导读:

下面我为您设计一个Java案例,用于统计门球(冰壶/地掷球类运动)比赛中短传配合的成功率。
系统设计
核心类结构
// 枚举:传球类型
enum PassType {
SHORT_PASS("短传"), // 短距离传球
LONG_PASS("长传"), // 长距离传球
CROSS_PASS("横传"); // 横传
private String desc;
PassType(String desc) { this.desc = desc; }
public String getDesc() { return desc; }
}
// 枚举:传球结果
enum PassResult {
SUCCESS("成功"),
FAILURE("失败"),
INTERCEPTED("被拦截");
private String desc;
PassResult(String desc) { this.desc = desc; }
public String getDesc() { return desc; }
}
// 球员类
class Player {
private int id;
private String name;
private String position; // 位置:前锋、中场、后卫
public Player(int id, String name, String position) {
this.id = id;
this.name = name;
this.position = position;
}
// getters and setters
public int getId() { return id; }
public String getName() { return name; }
public String getPosition() { return position; }
}
// 传球事件类
class PassEvent {
private Player passer; // 传球者
private Player receiver; // 接球者
private PassType passType; // 传球类型
private PassResult result; // 传球结果
private int distance; // 传球距离(米)
private String timestamp; // 时间戳
public PassEvent(Player passer, Player receiver, PassType passType,
PassResult result, int distance, String timestamp) {
this.passer = passer;
this.receiver = receiver;
this.passType = passType;
this.result = result;
this.distance = distance;
this.timestamp = timestamp;
}
// getters
public Player getPasser() { return passer; }
public Player getReceiver() { return receiver; }
public PassType getPassType() { return passType; }
public PassResult getResult() { return result; }
public int getDistance() { return distance; }
public String getTimestamp() { return timestamp; }
}
// 球队类
class Team {
private String teamName;
private List<Player> players;
private List<PassEvent> passEvents;
public Team(String teamName) {
this.teamName = teamName;
this.players = new ArrayList<>();
this.passEvents = new ArrayList<>();
}
public void addPlayer(Player player) {
players.add(player);
}
public void addPassEvent(PassEvent event) {
passEvents.add(event);
}
public String getTeamName() { return teamName; }
public List<Player> getPlayers() { return players; }
public List<PassEvent> getPassEvents() { return passEvents; }
}
统计服务类
import java.util.*;
import java.util.stream.Collectors;
public class PassStatisticsService {
private Team team;
public PassStatisticsService(Team team) {
this.team = team;
}
// 获取短传成功率的统计算法
public Map<String, Object> getShortPassStatistics() {
Map<String, Object> stats = new HashMap<>();
// 1. 获取所有短传事件
List<PassEvent> shortPasses = team.getPassEvents().stream()
.filter(event -> event.getPassType() == PassType.SHORT_PASS)
.collect(Collectors.toList());
// 2. 统计总数和成功数
int totalPasses = shortPasses.size();
long successfulPasses = shortPasses.stream()
.filter(event -> event.getResult() == PassResult.SUCCESS)
.count();
long failedPasses = shortPasses.stream()
.filter(event -> event.getResult() == PassResult.FAILURE)
.count();
long interceptedPasses = shortPasses.stream()
.filter(event -> event.getResult() == PassResult.INTERCEPTED)
.count();
// 3. 计算成功率
double successRate = 0;
if (totalPasses > 0) {
successRate = (double) successfulPasses / totalPasses * 100;
}
// 4. 按传球者统计
Map<String, Integer> passerStats = new HashMap<>();
Map<String, Integer> passerSuccessful = new HashMap<>();
for (PassEvent event : shortPasses) {
String passerName = event.getPasser().getName();
passerStats.merge(passerName, 1, Integer::sum);
if (event.getResult() == PassResult.SUCCESS) {
passerSuccessful.merge(passerName, 1, Integer::sum);
}
}
// 5. 按距离段统计
Map<String, Integer> distanceStats = new HashMap<>();
Map<String, Integer> distanceSuccessful = new HashMap<>();
for (PassEvent event : shortPasses) {
String distanceRange = getDistanceRange(event.getDistance());
distanceStats.merge(distanceRange, 1, Integer::sum);
if (event.getResult() == PassResult.SUCCESS) {
distanceSuccessful.merge(distanceRange, 1, Integer::sum);
}
}
// 组装统计结果
stats.put("totalShortPasses", totalPasses);
stats.put("successfulPasses", successfulPasses);
stats.put("failedPasses", failedPasses);
stats.put("interceptedPasses", interceptedPasses);
stats.put("successRate", String.format("%.2f%%", successRate));
stats.put("passerStats", passerStats);
stats.put("passerSuccessful", passerSuccessful);
stats.put("distanceStats", distanceStats);
stats.put("distanceSuccessful", distanceSuccessful);
return stats;
}
// 按球员统计短传成功率
public Map<String, Object> getPlayerShortPassStats() {
Map<String, Object> playerStats = new HashMap<>();
Map<String, Integer> totalPasses = new HashMap<>();
Map<String, Integer> successfulPasses = new HashMap<>();
Map<String, Integer> failedPasses = new HashMap<>();
Map<String, Integer> interceptedPasses = new HashMap<>();
for (PassEvent event : team.getPassEvents()) {
if (event.getPassType() != PassType.SHORT_PASS) {
continue;
}
String playerName = event.getPasser().getName();
// 统计总数
totalPasses.merge(playerName, 1, Integer::sum);
// 统计结果
switch (event.getResult()) {
case SUCCESS:
successfulPasses.merge(playerName, 1, Integer::sum);
break;
case FAILURE:
failedPasses.merge(playerName, 1, Integer::sum);
break;
case INTERCEPTED:
interceptedPasses.merge(playerName, 1, Integer::sum);
break;
}
}
// 计算每个球员的成功率
for (String playerName : totalPasses.keySet()) {
int total = totalPasses.get(playerName);
int success = successfulPasses.getOrDefault(playerName, 0);
double rate = total > 0 ? (double) success / total * 100 : 0;
Map<String, Object> playerInfo = new HashMap<>();
playerInfo.put("total", total);
playerInfo.put("success", success);
playerInfo.put("failed", failedPasses.getOrDefault(playerName, 0));
playerInfo.put("intercepted", interceptedPasses.getOrDefault(playerName, 0));
playerInfo.put("successRate", String.format("%.2f%%", rate));
playerStats.put(playerName, playerInfo);
}
return playerStats;
}
// 按传球组合统计
public Map<String, Object> getPassCombinationStats() {
Map<String, Object> combinationStats = new HashMap<>();
Map<String, Integer> combinations = new HashMap<>();
Map<String, Integer> successfulCombinations = new HashMap<>();
for (PassEvent event : team.getPassEvents()) {
if (event.getPassType() != PassType.SHORT_PASS) {
continue;
}
String combination = event.getPasser().getName() + " -> " +
event.getReceiver().getName();
combinations.merge(combination, 1, Integer::sum);
if (event.getResult() == PassResult.SUCCESS) {
successfulCombinations.merge(combination, 1, Integer::sum);
}
}
// 计算组合成功率
Map<String, Double> combinationRates = new HashMap<>();
for (Map.Entry<String, Integer> entry : combinations.entrySet()) {
int total = entry.getValue();
int success = successfulCombinations.getOrDefault(entry.getKey(), 0);
double rate = total > 0 ? (double) success / total * 100 : 0;
combinationRates.put(entry.getKey(), rate);
}
combinationStats.put("totalCombinations", combinations);
combinationStats.put("successfulCombinations", successfulCombinations);
combinationStats.put("combinationRates", combinationRates);
return combinationStats;
}
// 辅助方法:获取距离范围
private String getDistanceRange(int distance) {
if (distance <= 5) return "0-5米";
if (distance <= 10) return "5-10米";
if (distance <= 15) return "10-15米";
return "15米以上";
}
}
主程序示例
import java.util.*;
import java.text.SimpleDateFormat;
public class Main {
public static void main(String[] args) {
// 创建球队
Team team = new Team("门球一队");
// 创建球员
Player player1 = new Player(1, "张伟", "前锋");
Player player2 = new Player(2, "李强", "前锋");
Player player3 = new Player(3, "王浩", "中场");
Player player4 = new Player(4, "赵明", "后卫");
Player player5 = new Player(5, "孙立", "中场");
team.addPlayer(player1);
team.addPlayer(player2);
team.addPlayer(player3);
team.addPlayer(player4);
team.addPlayer(player5);
// 模拟传球数据
addSamplePassEvents(team, player1, player2, player3, player4, player5);
// 创建统计服务
PassStatisticsService service = new PassStatisticsService(team);
// 输出统计结果
printStatistics(service, team);
}
private static void addSamplePassEvents(Team team, Player p1, Player p2,
Player p3, Player p4, Player p5) {
// 模拟一些短传事件
addPass(team, p1, p2, PassType.SHORT_PASS, PassResult.SUCCESS, 5, "12:00:01");
addPass(team, p1, p3, PassType.SHORT_PASS, PassResult.SUCCESS, 8, "12:00:05");
addPass(team, p2, p3, PassType.SHORT_PASS, PassResult.SUCCESS, 12, "12:00:10");
addPass(team, p3, p1, PassType.SHORT_PASS, PassResult.FAILURE, 6, "12:00:15");
addPass(team, p3, p4, PassType.SHORT_PASS, PassResult.SUCCESS, 10, "12:00:20");
addPass(team, p4, p5, PassType.SHORT_PASS, PassResult.SUCCESS, 4, "12:00:25");
addPass(team, p5, p1, PassType.SHORT_PASS, PassResult.INTERCEPTED, 9, "12:00:30");
addPass(team, p1, p4, PassType.LONG_PASS, PassResult.SUCCESS, 20, "12:00:35");
addPass(team, p2, p5, PassType.SHORT_PASS, PassResult.SUCCESS, 7, "12:00:40");
addPass(team, p3, p2, PassType.SHORT_PASS, PassResult.SUCCESS, 11, "12:00:45");
addPass(team, p4, p1, PassType.SHORT_PASS, PassResult.FAILURE, 13, "12:00:50");
addPass(team, p5, p3, PassType.SHORT_PASS, PassResult.SUCCESS, 6, "12:00:55");
addPass(team, p1, p5, PassType.SHORT_PASS, PassResult.SUCCESS, 10, "12:01:00");
addPass(team, p2, p1, PassType.SHORT_PASS, PassResult.SUCCESS, 9, "12:01:05");
addPass(team, p3, p4, PassType.SHORT_PASS, PassResult.INTERCEPTED, 14, "12:01:10");
addPass(team, p4, p2, PassType.SHORT_PASS, PassResult.SUCCESS, 8, "12:01:15");
addPass(team, p5, p4, PassType.SHORT_PASS, PassResult.SUCCESS, 12, "12:01:20");
addPass(team, p2, p3, PassType.SHORT_PASS, PassResult.SUCCESS, 7, "12:01:25");
addPass(team, p4, p5, PassType.LONG_PASS, PassResult.SUCCESS, 25, "12:01:30");
addPass(team, p5, p2, PassType.SHORT_PASS, PassResult.FAILURE, 5, "12:01:35");
addPass(team, p1, p2, PassType.SHORT_PASS, PassResult.SUCCESS, 10, "12:01:40");
addPass(team, p3, p5, PassType.SHORT_PASS, PassResult.SUCCESS, 11, "12:01:45");
addPass(team, p4, p1, PassType.SHORT_PASS, PassResult.SUCCESS, 13, "12:01:50");
addPass(team, p2, p4, PassType.SHORT_PASS, PassResult.SUCCESS, 9, "12:01:55");
}
private static void addPass(Team team, Player passer, Player receiver,
PassType type, PassResult result, int distance, String time) {
team.addPassEvent(new PassEvent(passer, receiver, type, result, distance, time));
}
private static void printStatistics(PassStatisticsService service, Team team) {
System.out.println("========== 门球短传配合成功率统计 ==========");
System.out.println("球队: " + team.getTeamName());
// 总统计
Map<String, Object> generalStats = service.getShortPassStatistics();
System.out.println("\n【总体统计】");
System.out.println("总短传次数: " + generalStats.get("totalShortPasses"));
System.out.println("成功次数: " + generalStats.get("successfulPasses"));
System.out.println("失败次数: " + generalStats.get("failedPasses"));
System.out.println("被拦截次数: " + generalStats.get("interceptedPasses"));
System.out.println("总体短传成功率: " + generalStats.get("successRate"));
// 球员统计
System.out.println("\n【球员短传数据】");
Map<String, Object> playerStats = service.getPlayerShortPassStats();
System.out.printf("%-15s %-10s %-10s %-10s %-15s %s%n",
"球员", "总传球", "成功", "失败", "被拦截", "成功率");
for (Map.Entry<String, Object> entry : playerStats.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// 传球组合统计
System.out.println("\n【传球组合数据】");
Map<String, Object> combinationStats = service.getPassCombinationStats();
Map<String, Integer> total = (Map<String, Integer>) combinationStats.get("totalCombinations");
Map<String, Integer> success = (Map<String, Integer>) combinationStats.get("successfulCombinations");
Map<String, Double> rates = (Map<String, Double>) combinationStats.get("combinationRates");
System.out.printf("%-25s %-10s %-10s %s%n", "组合", "总次数", "成功次数", "成功率");
for (Map.Entry<String, Integer> entry : total.entrySet()) {
String comb = entry.getKey();
int totalCount = entry.getValue();
int successCount = success.getOrDefault(comb, 0);
double rate = rates.get(comb);
System.out.printf("%-25s %-10s %-10s %.2f%%%n",
comb, totalCount, successCount, rate);
}
// 距离统计
System.out.println("\n【距离段成功率】");
Map<String, Integer> distanceStats = (Map<String, Integer>) generalStats.get("distanceStats");
Map<String, Integer> distanceSuccessful = (Map<String, Integer>) generalStats.get("distanceSuccessful");
for (Map.Entry<String, Integer> entry : distanceStats.entrySet()) {
String range = entry.getKey();
int totalCount = entry.getValue();
int successCount = distanceSuccessful.getOrDefault(range, 0);
double rate = totalCount > 0 ? (double) successCount / totalCount * 100 : 0;
System.out.printf("%-15s 总传球: %-5d 成功: %-5d 成功率: %.2f%%%n",
range, totalCount, successCount, rate);
}
}
}
扩展功能建议
添加实时监控
// 实时监控短传成功率
public class RealTimeMonitor {
private Timer timer;
private PassStatisticsService service;
public void startMonitoring() {
timer = new Timer(true);
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
Map<String, Object> stats = service.getShortPassStatistics();
// 实时显示统计结果
displayStats(stats);
}
}, 0, 5000); // 每5秒更新一次
}
}
数据持久化(MySQL)
// 数据库存储示例
public class PassDataDAO {
private Connection connection;
// 保存传球记录
public void savePassEvent(PassEvent event) throws SQLException {
String sql = "INSERT INTO pass_events " +
"(passer_id, receiver_id, pass_type, result, distance) " +
"VALUES (?, ?, ?, ?, ?)";
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
pstmt.setInt(1, event.getPasser().getId());
pstmt.setInt(2, event.getReceiver().getId());
pstmt.setInt(3, event.getPassType().ordinal());
pstmt.setInt(4, event.getResult().ordinal());
pstmt.setInt(5, event.getDistance());
pstmt.executeUpdate();
}
}
}
图形化展示(JFreeChart)
// 绘制成功率图表
public class ChartGenerator {
public JFreeChart createSuccessRateChart(PassStatisticsService service) {
Map<String, Object> stats = service.getShortPassStatistics();
// 创建柱状图显示各球员成功率
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
// ...填充数据...
JFreeChart chart = ChartFactory.createBarChart(
"短传成功率统计",
"球员",
"成功率(%)",
dataset
);
return chart;
}
}
使用说明
-
编译运行:
javac Main.java java Main
-
预期输出:
- 总体统计信息
- 各球员的短传数据
- 不同传球组合的成功率
- 不同距离段的成功率
这个案例提供了完整的短传配合成功率统计功能,可以根据实际需求扩展更多功能,如添加更多维度的统计、可视化展示、数据库持久化等。