本文目录导读:

这是一个关于统计克鲁伊夫转身(Cruyff Turn)次数的经典Java编程案例,通常这个案例用于教学,核心是状态机或模式识别的思维。
由于“克鲁伊夫转身”在足球中是一个连贯动作(先拉球,再变向),在程序模拟中,它通常被定义为一组特定动作序列。
通用规则定义:
如果你有一个动作字符串("左右左左右" 或 "A-B-A" 模式),我们统计这个特定模式出现了多少次。
简单字符串匹配(如果动作是连续字符串)
假设我们用字母代表动作:
A= 左脚拉球B= 右脚拉球- 转身定义为:触球脚迅速切换到另一只脚,即
"AB"或"BA"的连续组合,但更严格的定义是 “拉球 + 转身” 两个动作的连续。
Java代码示例(统计"AB"模式):
public class CruyffTurnCounter {
public static void main(String[] args) {
// 示例动作序列:L代表左脚,R代表右脚
String actions = "LRLRLLRRLR";
// 定义克鲁伊夫转身模式:左脚拉球后紧接右脚(LR)或右脚拉球后紧接左脚(RL)
String pattern1 = "LR";
String pattern2 = "RL";
int count = countOccurrences(actions, pattern1) + countOccurrences(actions, pattern2);
System.out.println("克鲁伊夫转身次数: " + count);
}
// 统计子串出现次数(不重叠)
public static int countOccurrences(String text, String pattern) {
int count = 0;
int index = 0;
while ((index = text.indexOf(pattern, index)) != -1) {
count++;
index += pattern.length(); // 移动到模式之后,避免重复计算
}
return count;
}
}
状态机模拟(更符合实战逻辑)
如果动作是时时生成的(例如从传感器读取),你需要检测上一次动作和当前动作是否构成转身。
Java代码示例(实时状态检测):
public class RealTimeCruyffCounter {
// 定义动作常量(模拟)
enum Action {
LEFT_TOUCH, // 左脚触球
RIGHT_TOUCH, // 右脚触球
TURN, // 转向动作(通常这个不单独算,是结果)
DRIBBLE // 普通带球
}
public static void main(String[] args) {
// 模拟动作流(数组)
Action[] actionStream = {
Action.DRIBBLE,
Action.LEFT_TOUCH,
Action.RIGHT_TOUCH, // 这里 RIGHT_TOUCH 紧接 LEFT_TOUCH,算一次转身
Action.DRIBBLE,
Action.RIGHT_TOUCH,
Action.LEFT_TOUCH, // 这里 LEFT_TOUCH 紧接 RIGHT_TOUCH,算一次
Action.LEFT_TOUCH,
Action.RIGHT_TOUCH // 再算一次
};
int cruyffCount = 0;
Action previousAction = null;
for (Action currentAction : actionStream) {
// 关键逻辑:如果上一次是左脚,这次是右脚(或反之),则计为转身
if (previousAction != null &&
((previousAction == Action.LEFT_TOUCH && currentAction == Action.RIGHT_TOUCH) ||
(previousAction == Action.RIGHT_TOUCH && currentAction == Action.LEFT_TOUCH))) {
cruyffCount++;
System.out.println("检测到一次转身!");
}
// 更新上一步状态(只关注触球脚,忽略 DRIBBLE)
if (currentAction == Action.LEFT_TOUCH || currentAction == Action.RIGHT_TOUCH) {
previousAction = currentAction;
}
}
System.out.println("总计: " + cruyffCount + " 次克鲁伊夫转身");
}
}
复杂形态(包含“拨球”和“拉球”)
更进阶的模拟中,转身包含三个子动作:拉球 (Pull)、转身 (Turn)、拨球 (Push)。 此时需要检测三个连续状态的匹配。
public class AdvancedCruyffTurn {
public static void main(String[] args) {
// 动作编码:1=拉左,2=拉右,3=转身,4=拨右,5=拨左
int[] sequence = {1, 3, 4, 1, 3, 5, 2, 3, 4};
// 定义克鲁伊夫转身模板
int[][] patterns = {
{1, 3, 4}, // 拉左 -> 转身 -> 拨右
{2, 3, 5} // 拉右 -> 转身 -> 拨左
};
int count = 0;
for (int i = 0; i < sequence.length - 2; i++) {
int[] window = {sequence[i], sequence[i+1], sequence[i+2]};
if (matches(window, patterns[0]) || matches(window, patterns[1])) {
count++;
i += 2; // 跳过已匹配的部分
}
}
System.out.println("高级统计结果:" + count);
}
private static boolean matches(int[] a, int[] b) {
return a[0] == b[0] && a[1] == b[1] && a[2] == b[2];
}
}
运行结果说明
如果你运行上面的代码,会得到不同的输出,因为输入数据不同。
关键点总结:
- 如果是字符串:用
indexOf或正则表达式。 - 如果是状态流:用
previousAction变量进行状态比较。 - 如果是多步动作:用滑动窗口比较数组。
你可以根据你的实际数据格式(是文本、数组还是实时流)选择合适的方案,如果你有具体的动作数据格式,可以发给我,我帮你写一个精确的统计逻辑。