java案例统计门球短传配合成功率?

wen java案例 1

门球短传配合成功率统计 - Java 案例

下面是一个完整的 Java 案例,用于统计门球比赛中短传配合的成功率,包含数据模型、统计逻辑和测试示例。

java案例统计门球短传配合成功率?


需求分析

门球短传配合统计需要记录:

  • 传球方(球员编号)
  • 接球方
  • 传球距离(短传一般 ≤ 5 米)
  • 传球结果(成功 / 失败)
  • 失败原因(可选:出界、被截、接球失误等)

统计指标:

  • 总短传次数
  • 成功次数 / 失败次数
  • 成功率 = 成功次数 / 总次数 × 100%
  • 按球员细分成功率
  • 失败原因分布

代码实现

1 枚举与实体类

import java.util.*;
import java.util.stream.Collectors;
// 传球结果枚举
enum PassResult {
    SUCCESS("成功"),
    FAIL_OUT("出界"),
    FAIL_INTERCEPT("被截"),
    FAIL_RECEIVE("接球失误");
    private final String desc;
    PassResult(String desc) { this.desc = desc; }
    public String getDesc() { return desc; }
    public boolean isSuccess() { return this == SUCCESS; }
}
// 短传记录
class ShortPass {
    private final String passer;      // 传球球员
    private final String receiver;    // 接球球员
    private final double distance;    // 距离(米)
    private final PassResult result;
    public ShortPass(String passer, String receiver, double distance, PassResult result) {
        this.passer = passer;
        this.receiver = receiver;
        this.distance = distance;
        this.result = result;
    }
    public String getPasser() { return passer; }
    public String getReceiver() { return receiver; }
    public double getDistance() { return distance; }
    public PassResult getResult() { return result; }
    public boolean isSuccess() { return result.isSuccess(); }
}

2 统计器

class ShortPassStatistics {
    private static final double SHORT_PASS_MAX = 5.0; // 短传阈值(米)
    private final List<ShortPass> records = new ArrayList<>();
    /** 添加一条传球记录(自动过滤非短传) */
    public void addRecord(ShortPass pass) {
        if (pass.getDistance() <= SHORT_PASS_MAX) {
            records.add(pass);
        }
    }
    public void addRecords(List<ShortPass> list) {
        list.forEach(this::addRecord);
    }
    /** 总次数 */
    public int totalCount() { return records.size(); }
    /** 成功次数 */
    public long successCount() {
        return records.stream().filter(ShortPass::isSuccess).count();
    }
    /** 整体成功率(%) */
    public double successRate() {
        if (records.isEmpty()) return 0.0;
        return successCount() * 100.0 / records.size();
    }
    /** 按球员统计成功率 */
    public Map<String, Double> successRateByPlayer() {
        Map<String, List<ShortPass>> grouped = records.stream()
                .collect(Collectors.groupingBy(ShortPass::getPasser));
        Map<String, Double> result = new LinkedHashMap<>();
        grouped.forEach((player, list) -> {
            long ok = list.stream().filter(ShortPass::isSuccess).count();
            result.put(player, ok * 100.0 / list.size());
        });
        return result;
    }
    /** 失败原因分布 */
    public Map<PassResult, Long> failureDistribution() {
        return records.stream()
                .filter(p -> !p.isSuccess())
                .collect(Collectors.groupingBy(ShortPass::getResult, Collectors.counting()));
    }
    /** 打印完整报告 */
    public void printReport() {
        System.out.println("===== 门球短传配合统计报告 =====");
        System.out.printf("总短传次数 : %d%n", totalCount());
        System.out.printf("成功次数   : %d%n", successCount());
        System.out.printf("失败次数   : %d%n", totalCount() - successCount());
        System.out.printf("整体成功率 : %.2f%%%n", successRate());
        System.out.println("\n--- 球员成功率 ---");
        successRateByPlayer().forEach((p, r) ->
                System.out.printf("%-6s : %.2f%%%n", p, r));
        System.out.println("\n--- 失败原因分布 ---");
        failureDistribution().forEach((reason, cnt) ->
                System.out.printf("%-8s : %d 次%n", reason.getDesc(), cnt));
    }
}

3 测试示例

public class GateBallDemo {
    public static void main(String[] args) {
        List<ShortPass> data = Arrays.asList(
            new ShortPass("张1", "李2", 3.5, PassResult.SUCCESS),
            new ShortPass("张1", "王3", 4.2, PassResult.SUCCESS),
            new ShortPass("张1", "李2", 2.8, PassResult.FAIL_OUT),
            new ShortPass("李2", "张1", 4.5, PassResult.SUCCESS),
            new ShortPass("李2", "王3", 1.9, PassResult.FAIL_INTERCEPT),
            new ShortPass("王3", "张1", 3.0, PassResult.SUCCESS),
            new ShortPass("王3", "李2", 4.8, PassResult.FAIL_RECEIVE),
            new ShortPass("王3", "张1", 2.2, PassResult.SUCCESS),
            new ShortPass("张1", "王3", 4.9, PassResult.SUCCESS),
            // 下面这条距离 6.5 米,属于中长传,会被过滤
            new ShortPass("李2", "王3", 6.5, PassResult.SUCCESS)
        );
        ShortPassStatistics stats = new ShortPassStatistics();
        stats.addRecords(data);
        stats.printReport();
    }
}

运行结果

===== 门球短传配合统计报告 =====
总短传次数 : 9
成功次数   : 6
失败次数   : 3
整体成功率 : 66.67%
--- 球员成功率 ---
张1    : 75.00%
李2    : 50.00%
王3    : 66.67%
--- 失败原因分布 ---
出界     : 1 次
被截     : 1 次
接球失误 : 1 次

第 10 条记录(距离 6.5 米)被自动过滤,符合"短传 ≤ 5 米"的定义。


扩展建议

若想做成完整系统,可考虑:

扩展方向 说明
文件读取 从 CSV/Excel 读取比赛记录,用 BufferedReader 或 Apache POI
时间段统计 给记录加 LocalDateTime,按半场、加时统计
双人配合排行 用 passer + receiver 作为 key 统计默契度
可视化 导出 JSON,用 ECharts 展示成功率趋势图
异常校验 校验传球双方不能相同、距离非负
数据库 用 MyBatis / JPA 持久化,支持历史对抗查询

核心思路:把每条短传建模为对象 → 用 Stream 按整体 / 按球员 / 按失败原因分组聚合 → 成功数 / 总数 × 100 得到成功率,逻辑清晰,易于扩展。

如果需要我把它改成从文件读取数据或按半场分段统计的版本,可以告诉我 😊

抱歉,评论功能暂时关闭!