java案例统计撞墙式配合完成了几次?

wen java案例 4

Java案例:统计"撞墙式配合"完成次数

"撞墙式配合"(也叫"二过一"、"撞墙配合")是足球中的经典战术:A 传球给 B,B 不停球直接回传给 A,A 接球后继续推进,就像球打在墙上弹回来一样。

java案例统计撞墙式配合完成了几次?

下面用 Java 模拟一个简单的比赛事件流,统计该配合的成功完成次数。


思路设计

一次成功的"撞墙式配合"需要满足以下事件序列:

  1. 球员 A 传球球员 B
  2. 球员 B 不停球(一次触球)立刻回传球员 A
  3. 球员 A 接到球(接球成功)

我们只需要按顺序扫描事件流,匹配 A传球给B → B回传给A 这个模式即可。


代码实现

import java.util.*;
// 事件类型
enum EventType {
    PASS,       // 传球
    RECEIVE,    // 接球
    SHOT,       // 射门
    DRIBBLE,    // 带球
    LOSE_BALL   // 丢球
}
// 比赛事件
class MatchEvent {
    int minute;           // 比赛第几分钟
    EventType type;       // 事件类型
    String fromPlayer;    // 发起球员
    String toPlayer;      // 目标球员(若无可为 null)
    public MatchEvent(int minute, EventType type, String fromPlayer, String toPlayer) {
        this.minute = minute;
        this.type = type;
        this.fromPlayer = fromPlayer;
        this.toPlayer = toPlayer;
    }
    @Override
    public String toString() {
        return String.format("[%d'] %s: %s -> %s",
                minute, type, fromPlayer, toPlayer);
    }
}
public class OneTwoCounter {
    /**
     * 统计撞墙式配合(二过一)完成的次数
     * 匹配模式:A 传球给 B,紧接着 B 传球回给 A
     */
    public static List<String> countOneTwo(List<MatchEvent> events) {
        List<String> results = new ArrayList<>();
        for (int i = 0; i < events.size() - 1; i++) {
            MatchEvent cur  = events.get(i);
            MatchEvent next = events.get(i + 1);
            // 当前是传球,且下一次也是传球
            if (cur.type == EventType.PASS && next.type == EventType.PASS) {
                String a = cur.fromPlayer;   // 传球人 A
                String b = cur.toPlayer;     // 接球人 B
                // 判断是否为A->B 紧接着 B->A
                if (b != null
                        && b.equals(next.fromPlayer)
                        && a.equals(next.toPlayer)) {
                    results.add(String.format("%d'-%d' 分钟: %s 与 %s 完成一次撞墙配合",
                            cur.minute, next.minute, a, b));
                    i++; // 跳过下一事件,避免重复计数
                }
            }
        }
        return results;
    }
    public static void main(String[] args) {
        // 模拟一段比赛事件流
        List<MatchEvent> events = Arrays.asList(
                new MatchEvent(10, EventType.PASS,    "梅西",  "苏亚雷斯"),
                new MatchEvent(10, EventType.PASS,    "苏亚雷斯", "梅西"),   // ✅ 撞墙1
                new MatchEvent(12, EventType.DRIBBLE, "梅西",  null),
                new MatchEvent(20, EventType.PASS,    "内马尔", "阿尔维斯"),
                new MatchEvent(21, EventType.DRIBBLE, "阿尔维斯", null),
                new MatchEvent(30, EventType.PASS,    "哈维",  "伊涅斯塔"),
                new MatchEvent(30, EventType.PASS,    "伊涅斯塔", "哈维"),   // ✅ 撞墙2
                new MatchEvent(45, EventType.PASS,    "布斯克茨", "皮克"),
                new MatchEvent(45, EventType.PASS,    "皮克",  "布斯克茨"),   // ✅ 撞墙3
                new MatchEvent(60, EventType.SHOT,    "梅西",  null)
        );
        List<String> result = countOneTwo(events);
        System.out.println("=== 撞墙式配合统计 ===");
        result.forEach(System.out::println);
        System.out.println("总计完成: " + result.size() + " 次");
    }
}

运行结果

=== 撞墙式配合统计 ===
10'-10' 分钟: 梅西 与 苏亚雷斯 完成一次撞墙配合
30'-30' 分钟: 哈维 与 伊涅斯塔 完成一次撞墙配合
45'-45' 分钟: 布斯克茨 与 皮克 完成一次撞墙配合
总计完成: 3 次

进阶优化:用正则/栈的思想处理复杂场景

实际比赛中可能存在干扰事件(如带球、接球记录等),可以采用状态机方式更健壮地判断:

public static int countOneTwoByStateMachine(List<MatchEvent> events) {
    int count = 0;
    MatchEvent firstPass = null;   // 暂存第一次传球
    for (MatchEvent e : events) {
        if (e.type != EventType.PASS) {
            firstPass = null;      // 非传球事件打断连续判定
            continue;
        }
        if (firstPass == null) {
            firstPass = e;         // 记下第一次传球
        } else {
            // 检查是否构成 A->B B->A
            boolean isOneTwo = Objects.equals(firstPass.toPlayer, e.fromPlayer)
                            && Objects.equals(firstPass.fromPlayer, e.toPlayer);
            if (isOneTwo) {
                count++;
                firstPass = null;  // 计数后重置
            } else {
                firstPass = e;     // 不匹配则把当前当作新的起点
            }
        }
    }
    return count;
}

关键点 说明
核心逻辑 检测连续两个传球事件 A→BB→A
数据来源 可用足球数据 API(如 Opta、StatsBomb)生成事件流
扩展方向 加入时间窗口限制(如两次传球间隔 < 3 秒)、位置信息判断
算法复杂度 O(n),一次遍历即可

如果需要接入真实比赛数据(JSON/CSV) 或做成 Spring Boot 接口,可以进一步告诉我,我帮你扩展。

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