Python案例:这次犯规该不该吃牌?
下面我用一个足球犯规判罚系统的Python案例,来演示如何用代码逻辑判断犯规是否该出牌。

判罚规则梳理
| 情况 | 判罚 |
|---|---|
| 普通犯规(无恶意) | 口头警告 |
| 战术犯规 / 危险动作 | 黄牌 |
| 暴力动作 / 破坏明显得分机会(DOGSO) | 红牌 |
| 禁区内严重犯规 | 黄牌或红牌 + 点球 |
Python 实现
def judge_foul(
in_penalty_area: bool, # 是否在禁区内
is_dogso: bool, # 是否破坏明显得分机会
is_violent: bool, # 是否暴力动作
is_tactical: bool, # 是否战术犯规
is_dangerous: bool, # 是否危险动作(如抬脚过高)
is_last_defender: bool, # 是否是最后一名防守球员
contact_level: int # 接触程度 0-10
):
card = "无牌(口头警告)"
reasons = []
# 1. 暴力动作 -> 直接红牌
if is_violent:
card = "红牌"
reasons.append("暴力动作/严重犯规")
# 2. 破坏明显得分机会(DOGSO)
elif is_dogso:
if in_penalty_area and not is_last_defender:
# 禁区内且非最后一人犯规,通常判点球+黄牌
card = "黄牌"
reasons.append("禁区内破坏得分机会(判点球+黄牌)")
else:
card = "红牌"
reasons.append("破坏明显得分机会(DOGSO)")
# 3. 战术犯规 / 危险动作 -> 黄牌
elif is_tactical or is_dangerous:
card = "黄牌"
if is_tactical:
reasons.append("战术犯规")
if is_dangerous:
reasons.append("危险动作")
# 4. 接触程度过高,即使不算暴力也升级
elif contact_level >= 7:
card = "黄牌"
reasons.append(f"接触程度过高({contact_level}/10)")
# 5. 其他情况:口头警告
else:
reasons.append("普通犯规")
# 禁区内普通犯规附加点球提示
penalty = in_penalty_area and card != "无牌(口头警告)"
return {
"判罚": card,
"理由": reasons,
"是否判点球": penalty
}
# ====== 测试案例 ======
cases = [
{"name": "案例1:中场战术拉人",
"args": dict(in_penalty_area=False, is_dogso=False, is_violent=False,
is_tactical=True, is_dangerous=False,
is_last_defender=False, contact_level=4)},
{"name": "案例2:禁区内背后铲倒单刀球员",
"args": dict(in_penalty_area=True, is_dogso=True, is_violent=False,
is_tactical=False, is_dangerous=True,
is_last_defender=True, contact_level=8)},
{"name": "案例3:抬脚过高踢到对方头部",
"args": dict(in_penalty_area=False, is_dogso=False, is_violent=True,
is_tactical=False, is_dangerous=True,
is_last_defender=False, contact_level=9)},
{"name": "案例4:轻微身体接触",
"args": dict(in_penalty_area=False, is_dogso=False, is_violent=False,
is_tactical=False, is_dangerous=False,
is_last_defender=False, contact_level=2)},
]
for c in cases:
result = judge_foul(**c["args"])
print(f"【{c['name']}】")
print(f" 判罚: {result['判罚']}")
print(f" 理由: {', '.join(result['理由'])}")
print(f" 点球: {'是' if result['是否判点球'] else '否'}")
print("-" * 40)
运行结果
【案例1:中场战术拉人】
判罚: 黄牌
理由: 战术犯规
点球: 否
----------------------------------------
【案例2:禁区内背后铲倒单刀球员】
判罚: 红牌
理由: 破坏明显得分机会(DOGSO)
点球: 是
----------------------------------------
【案例3:抬脚过高踢到对方头部】
判罚: 红牌
理由: 暴力动作/严重犯规
点球: 否
----------------------------------------
【案例4:轻微身体接触】
判罚: 无牌(口头警告)
理由: 普通犯规
点球: 否
----------------------------------------
判罚逻辑要点
- 红牌优先级最高:暴力动作、DOGSO(禁区外或最后一名防守球员)直接红牌。
- 黄牌情形:战术犯规、危险动作、接触程度≥7。
- 点球判定:只要在禁区内且构成犯规,就判点球。
- 禁区内DOGSO的特殊处理:如果抢球意图明显(非最后一人),近年规则倾向"点球+黄牌"而非红牌。
可扩展方向
- 加入球员历史累积黄牌判断是否两黄变一红
- 引入VAR回看模拟(接触程度、慢动作重放权重)
- 用
enum定义牌的类型,用dataclass封装犯规信息 - 结合真实比赛数据集训练一个犯规判罚模型
要不要我进一步做一个两黄变一红的完整版本,模拟一场比赛?