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

规则梳理
足球中常见的出牌逻辑:
| 判罚 | 触发条件 |
|---|---|
| 黄牌 | 战术犯规、鲁莽动作、拖延时间、异议等 |
| 红牌 | 暴力行为、严重犯规、破坏明显进球机会(DOGSO)、两黄变一红 |
| 无牌 | 普通犯规、无意手球等 |
基础版本代码
def judge_card(foul_type, is_dangerous, is_dogso,
is_violent, already_yellow, is_last_defender):
"""
判断犯规该不该吃牌
foul_type: 犯规类型
is_dangerous: 是否危险动作
is_dogso: 是否破坏明显进球机会
is_violent: 是否暴力行为
already_yellow: 是否已有黄牌
is_last_defender: 是否最后一名防守球员
"""
# 1. 暴力行为 → 直接红牌
if is_violent:
return "红牌", "暴力行为,直接罚下"
# 2. 破坏明显进球机会 → 红牌
if is_dogso and is_last_defender:
return "红牌", "破坏明显进球机会(DOGSO)"
# 3. 危险动作 / 战术犯规 → 黄牌
if is_dangerous or foul_type in ["战术犯规", "拖延时间", "异议"]:
if already_yellow:
return "红牌", "两黄变一红"
return "黄牌", "鲁莽/战术犯规"
# 4. 已有黄牌再犯 → 红牌
if already_yellow:
return "红牌", "两黄变一红"
# 5. 普通犯规
return "无牌", "普通犯规,口头警告"
# 测试案例
cases = [
# (犯规类型, 危险, DOGSO, 暴力, 已有黄牌, 最后防守人)
("普通犯规", False, False, False, False, False),
("战术犯规", False, False, False, False, False),
("背后铲球", True, False, False, False, False),
("推搡对手", False, False, True, False, False),
("禁区拉人", False, True, False, False, True),
("普通犯规", False, False, False, True, False),
]
for c in cases:
card, reason = judge_card(*c)
print(f"犯规: {c[0]:<8} → 判罚: {card:<4} ({reason})")
输出结果:
犯规: 普通犯规 → 判罚: 无牌 (普通犯规,口头警告)
犯规: 战术犯规 → 判罚: 黄牌 (鲁莽/战术犯规)
犯规: 背后铲球 → 判罚: 黄牌 (鲁莽/战术犯规)
犯规: 推搡对手 → 判罚: 红牌 (暴力行为,直接罚下)
犯规: 禁区拉人 → 判罚: 红牌 (破坏明显进球机会(DOGSO))
犯规: 普通犯规 → 判罚: 红牌 (两黄变一红)
面向对象版本(更适合真实场景)
from dataclasses import dataclass
from enum import Enum
class Card(Enum):
NONE = "无牌"
YELLOW = "黄牌"
RED = "红牌"
@dataclass
class Foul:
player: str
foul_type: str # 铲球/推人/手球/战术犯规...
is_dangerous: bool = False
is_violent: bool = False
is_dogso: bool = False # 破坏明显进球机会
is_last_defender: bool = False
has_yellow: bool = False
in_penalty_area: bool = False
def decide_card(foul: Foul) -> tuple[Card, str]:
# 红牌判定(优先级最高)
if foul.is_violent:
return Card.RED, "暴力行为"
if foul.is_dogso and foul.is_last_defender:
return Card.RED, "破坏明显进球机会"
# 黄牌判定
yellow_reasons = []
if foul.foul_type in {"战术犯规", "拖延时间", "异议", "假摔"}:
yellow_reasons.append(foul.foul_type)
if foul.is_dangerous:
yellow_reasons.append("危险动作")
if yellow_reasons:
if foul.has_yellow:
return Card.RED, "两黄变一红"
return Card.YELLOW, " + ".join(yellow_reasons)
if foul.has_yellow:
return Card.RED, "两黄变一红"
return Card.NONE, "普通犯规"
# 模拟几个真实场景
fouls = [
Foul("梅西", "战术犯规", has_yellow=False),
Foul("拉莫斯", "背后铲人", is_dangerous=True),
Foul("佩佩", "推搡", is_violent=True),
Foul("后卫A", "拉拽", is_dogso=True, is_last_defender=True),
Foul("中场B", "普通犯规", has_yellow=True),
]
for f in fouls:
card, reason = decide_card(f)
print(f"{f.player:<8} 犯规[{f.foul_type}] → {card.value} ({reason})")
输出:
梅西 犯规[战术犯规] → 黄牌 (战术犯规)
拉莫斯 犯规[背后铲人] → 黄牌 (危险动作)
佩佩 犯规[推搡] → 红牌 (暴力行为)
后卫A 犯规[拉拽] → 红牌 (破坏明显进球机会)
中场B 犯规[普通犯规] → 红牌 (两黄变一红)
加入置信度(进阶:VAR式判断)
实际比赛中裁判有主观判断,可以引入权重打分:
def var_judge(foul: Foul) -> dict:
score = 0
reasons = []
weights = {
"is_violent": 100,
"is_dogso": 80,
"is_last_defender": 40,
"is_dangerous": 50,
"战术犯规": 30,
"拖延时间": 20,
"异议": 20,
}
if foul.is_violent:
score += weights["is_violent"]; reasons.append("暴力")
if foul.is_dogso:
score += weights["is_dogso"]; reasons.append("DOGSO")
if foul.is_last_defender:
score += weights["is_last_defender"]; reasons.append("最后防守人")
if foul.is_dangerous:
score += weights["is_dangerous"]; reasons.append("危险动作")
if foul.foul_type in weights:
score += weights[foul.foul_type]; reasons.append(foul.foul_type)
if foul.has_yellow:
score += 60; reasons.append("已有黄牌")
if score >= 80:
card = "红牌"
elif score >= 30:
card = "黄牌"
else:
card = "无牌"
return {"player": foul.player, "score": score,
"card": card, "reasons": reasons}
f = Foul("测试球员", "背后铲球", is_dangerous=True, is_last_defender=True)
print(var_judge(f))
# {'player': '测试球员', 'score': 90, 'card': '红牌', 'reasons': ['危险动作', '最后防守人']}
判断"该不该吃牌"本质是一个规则 + 权重决策树问题:
- 先判断红牌条件(暴力、DOGSO、两黄)
- 再判断黄牌条件(危险、战术犯规、异议)
- 否则无牌
- 实际场景中可加权重打分模拟裁判主观判断
⚠️ 真实裁判还会考虑:比赛重要性、球员意图、是否首次犯规、场上局势等,代码只是规则框架,不能完全替代裁判。
需要我基于某个具体真实争议判罚案例(如某场比赛的红牌)写一个专门的判断程序吗?