本文目录导读:

我来设计一个综合的Python案例,模拟两支篮球队(或任何竞技队伍)进行系列赛的完整对战过程,最后输出获胜者。
完整综合案例:篮球系列赛模拟系统
"""
NBA季后赛系列赛模拟系统
功能:模拟两支球队进行7场4胜制系列赛,包含完整的数据统计和分析
"""
import random
import time
from dataclasses import dataclass
from typing import List, Dict, Tuple
from collections import defaultdict
# ==================== 基础数据类 ====================
@dataclass
class Player:
"""球员类"""
name: str
position: str
overall: int # 综合能力值 60-99
three_pt: int # 三分能力 60-99
mid_range: int # 中投能力 60-99
inside: int # 内线能力 60-99
defense: int # 防守能力 60-99
stamina: int # 体能 60-99
def __post_init__(self):
"""初始化时验证数据"""
for attr in ['overall', 'three_pt', 'mid_range', 'inside', 'defense', 'stamina']:
value = getattr(self, attr)
if not 60 <= value <= 99:
raise ValueError(f"{self.name}的{attr}属性必须在60-99之间")
@dataclass
class GameStats:
"""单场比赛统计数据"""
points: int = 0
rebounds: int = 0
assists: int = 0
steals: int = 0
blocks: int = 0
turnovers: int = 0
fouls: int = 0
three_pt_made: int = 0
field_goals_made: int = 0
# ==================== 球队类 ====================
class Team:
"""球队类"""
def __init__(self, name: str, city: str, players: List[Player]):
self.name = name
self.city = city
self.players = players
self.full_name = f"{city} {name}"
# 系列赛统计
self.series_wins = 0
self.home_advantage = 1.1 # 主场优势系数
# 比赛统计
self.game_logs = []
self.player_stats_history = []
def get_starting_five(self) -> List[Player]:
"""获取首发阵容"""
# 按位置和综合能力排序
positions = {'PG': [], 'SG': [], 'SF': [], 'PF': [], 'C': []}
for player in self.players:
if player.position in positions:
positions[player.position].append(player)
# 每个位置选最强的
starting = []
for pos in ['PG', 'SG', 'SF', 'PF', 'C']:
if positions[pos]:
positions[pos].sort(key=lambda p: p.overall, reverse=True)
starting.append(positions[pos][0])
return starting if len(starting) == 5 else self.players[:5]
def get_team_rating(self) -> float:
"""计算球队整体评分"""
if not self.players:
return 0
return sum(p.overall for p in self.players) / len(self.players)
# ==================== 比赛引擎类 ====================
class GameEngine:
"""比赛引擎,负责模拟单场比赛"""
QUARTERS = 4
MINUTES_PER_QUARTER = 12
TURNOVER_RATE = 0.12
def __init__(self, team1: Team, team2: Team, is_home_team1: bool = True):
self.team1 = team1
self.team2 = team2
self.is_home_team1 = is_home_team1
# 比赛状态
self.score = {team1.full_name: 0, team2.full_name: 0}
self.quarter_score = defaultdict(int)
self.player_stats = defaultdict(lambda: GameStats())
self.current_quarter = 1
# 球队体力状态
self.team_stamina = {
team1.full_name: 100,
team2.full_name: 100
}
def simulate_shot(self, team: Team, player: Player) -> Dict:
"""模拟一次投篮"""
# 根据投篮距离决定投篮类型
shot_type = random.choices(
['three', 'mid', 'inside'],
weights=[0.35, 0.35, 0.30]
)[0]
# 计算投篮命中率
if shot_type == 'three':
base_prob = (player.three_pt - 50) / 50 # 基础命中率
point_value = 3
elif shot_type == 'mid':
base_prob = (player.mid_range - 50) / 50
point_value = 2
else:
base_prob = (player.inside - 40) / 60
point_value = 2
# 加入防守影响
defender_prob = random.uniform(0.85, 1.15)
actual_prob = base_prob * defender_prob
# 加入主场优势
home_bonus = 1.0
if (self.is_home_team1 and team.full_name == self.team1.full_name) or \
(not self.is_home_team1 and team.full_name == self.team2.full_name):
home_bonus = self.team1.home_advantage if team.full_name == self.team1.full_name else self.team2.home_advantage
actual_prob *= home_bonus
actual_prob = max(0.1, min(0.9, actual_prob)) # 限制概率范围
# 是否命中
made = random.random() < actual_prob
return {
'made': made,
'points': point_value if made else 0,
'shot_type': shot_type
}
def simulate_possession(self, team: Team, opp_team: Team) -> None:
"""模拟一次进攻回合"""
# 选择进攻球员
ball_handler = random.choice(team.get_starting_five())
# 决定是否传球(30%概率)
if random.random() < 0.3:
ball_handler = random.choice(team.players[1:])
# 决定投篮还是失误
if random.random() < self.TURNOVER_RATE:
# 失误
self.player_stats[ball_handler.name].turnovers += 1
return
# 执行投篮
shot_result = self.simulate_shot(team, ball_handler)
# 更新统计
stats = self.player_stats[ball_handler.name]
stats.field_goals_made += 1 if shot_result['made'] else 0
if shot_result['shot_type'] == 'three' and shot_result['made']:
stats.three_pt_made += 1
stats.points += shot_result['points']
# 更新比分
self.score[team.full_name] += shot_result['points']
# 篮板球(50%的概率进攻篮板)
if not shot_result['made']:
if random.random() < 0.5:
rebounder = random.choice(team.players)
self.player_stats[rebounder.name].rebounds += 1
def simulate_quarter(self) -> None:
"""模拟一节比赛"""
possessions_per_quarter = 24 # 每节约24个回合
for _ in range(possessions_per_quarter):
# 交替进攻
if random.random() < 0.5:
self.simulate_possession(self.team1, self.team2)
else:
self.simulate_possession(self.team2, self.team1)
# 增加犯规和抢断等随机事件
for team in [self.team1, self.team2]:
for player in team.players:
stats = self.player_stats[player.name]
if random.random() < 0.2:
stats.fouls += 1
if random.random() < 0.15:
stats.steals += 1
if random.random() < 0.1:
stats.blocks += 1
if random.random() < 0.25:
stats.assists += 1
def play_game(self) -> Dict:
"""进行完整比赛"""
for quarter in range(1, self.QUARTERS + 1):
self.current_quarter = quarter
before_score = dict(self.score)
self.simulate_quarter()
# 记录每节得分
for team in [self.team1, self.team2]:
quarter_points = self.score[team.full_name] - before_score[team.full_name]
self.quarter_score[f"{team.full_name}_Q{quarter}"] = quarter_points
# 更新体力
for team in [self.team1, self.team2]:
self.team_stamina[team.full_name] = max(50,
self.team_stamina[team.full_name] - random.uniform(3, 8))
# 加时赛
while self.score[self.team1.full_name] == self.score[self.team2.full_name]:
print("进入加时赛!")
self.current_quarter = 5
self.simulate_quarter()
return {
'score': dict(self.score),
'player_stats': dict(self.player_stats),
'quarter_scores': dict(self.quarter_score),
'winner': max(self.score, key=self.score.get),
'loser': min(self.score, key=self.score.get)
}
# ==================== 系列赛模拟类 ====================
class SeriesSimulator:
"""系列赛模拟器(7场4胜制)"""
def __init__(self, team1: Team, team2: Team, best_of: int = 7):
self.team1 = team1
self.team2 = team2
self.best_of = best_of
self.wins_needed = (best_of // 2) + 1
# 系列赛统计
self.series_stats = {
'games': [],
'mvp_candidates': defaultdict(int),
'series_leader': None,
'comeback_alert': None
}
# 主客场安排 (2-2-1-1-1格式)
schedule = []
for i in range(best_of):
# 主队在前两场和最后两场(如果有)
if i < 2 or i > 4:
schedule.append('home_team1')
else:
schedule.append('home_team2')
self.schedule = schedule
def simulate_series(self) -> Dict:
"""模拟整个系列赛"""
print(f"\n{'='*50}")
print(f"🏀 系列赛开始: {self.team1.full_name} vs {self.team2.full_name}")
print(f"{'='*50}\n")
game_number = 1
while (self.team1.series_wins < self.wins_needed and
self.team2.series_wins < self.wins_needed and
game_number <= self.best_of):
# 确定主场
is_team1_home = self.schedule[game_number - 1] == 'home_team1'
home_team = self.team1 if is_team1_home else self.team2
away_team = self.team2 if is_team1_home else self.team1
print(f"第 {game_number} 场比赛: {home_team.full_name} (主场) vs {away_team.full_name}")
print("-" * 40)
# 运行比赛
engine = GameEngine(home_team, away_team, is_team1_home)
result = engine.play_game()
# 判定胜负
winner_name = result['winner']
if winner_name == self.team1.full_name:
self.team1.series_wins += 1
winner_team = self.team1
loser_team = self.team2
else:
self.team2.series_wins += 1
winner_team = self.team2
loser_team = self.team1
# 记录比赛数据
game_data = {
'game_number': game_number,
'home_team': home_team.full_name,
'away_team': away_team.full_name,
'score': result['score'],
'winner': winner_name,
'quarter_scores': result['quarter_scores'],
'player_stats': result['player_stats']
}
self.series_stats['games'].append(game_data)
# 打印比赛结果
print(f"比分: {home_team.full_name} {result['score'][home_team.full_name]} - "
f"{result['score'][away_team.full_name]} {away_team.full_name}")
# 评出本场最佳球员
mvp = self.get_game_mvp(result, winner_team)
print(f"🎖️ 本场MVP: {mvp} ({result['player_stats'][mvp].points}分)")
# 更新系列赛统计
for player_name, stats in result['player_stats'].items():
if stats.points > 20:
self.series_stats['mvp_candidates'][player_name] += 1
print(f"系列赛比分: {self.team1.full_name} {self.team1.series_wins} - "
f"{self.team2.series_wins} {self.team2.full_name}")
print()
game_number += 1
time.sleep(0.5) # 稍微暂停,模拟真实比赛节奏
# 返回系列赛结果
if self.team1.series_wins > self.team2.series_wins:
champion = self.team1
else:
champion = self.team2
self.series_stats['series_leader'] = champion.full_name
# 检测系列赛最佳球员
best_player = max(self.series_stats['mvp_candidates'],
key=self.series_stats['mvp_candidates'].get) if self.series_stats['mvp_candidates'] else "无"
self.series_stats['best_player'] = best_player
return {
'champion': champion,
'series_stats': self.series_stats
}
def get_game_mvp(self, result: Dict, team: Team) -> str:
"""评选单场最佳球员"""
team_stats = {}
for player in team.players:
if player.name in result['player_stats']:
stats = result['player_stats'][player.name]
# 简单评分:得分 + 助攻*1.5 + 篮板*0.8 + 其他
score = (stats.points + stats.assists * 1.5 +
stats.rebounds * 0.8 + stats.steals * 2 +
stats.blocks * 2 - stats.turnovers * 2)
team_stats[player.name] = score
return max(team_stats, key=team_stats.get)
# ==================== 数据分析类 ====================
class SeriesAnalyzer:
"""系列赛数据分析器"""
@staticmethod
def analyze_series(series_result: Dict) -> Dict:
"""分析系列赛数据"""
games = series_result['series_stats']['games']
# 基础统计
total_points_team1 = sum(g['score'].get(list(g['score'].keys())[0], 0)
for g in games)
total_points_team2 = sum(g['score'].get(list(g['score'].keys())[1], 0)
for g in games)
avg_margin = abs(total_points_team1 - total_points_team2) / len(games)
# 三分球统计
three_pt_stats = defaultdict(int)
for game in games:
for player, stats in game['player_stats'].items():
three_pt_stats[player] += stats.three_pt_made
best_three_pt = max(three_pt_stats, key=three_pt_stats.get) if three_pt_stats else "无"
# 得分王
scoring_leaders = defaultdict(int)
for game in games:
for player, stats in game['player_stats'].items():
scoring_leaders[player] += stats.points
scoring_champ = max(scoring_leaders, key=scoring_leaders.get) if scoring_leaders else "无"
# 篮板王
rebound_leaders = defaultdict(int)
for game in games:
for player, stats in game['player_stats'].items():
rebound_leaders[player] += stats.rebounds
rebound_champ = max(rebound_leaders, key=rebound_leaders.get) if rebound_leaders else "无"
# 助攻王
assist_leaders = defaultdict(int)
for game in games:
for player, stats in game['player_stats'].items():
assist_leaders[player] += stats.assists
assist_champ = max(assist_leaders, key=assist_leaders.get) if assist_leaders else "无"
return {
'avg_margin': avg_margin,
'games_played': len(games),
'best_three_pt': best_three_pt,
'scoring_champ': scoring_champ,
'rebound_champ': rebound_champ,
'assist_champ': assist_champ,
'total_games_stats': {
'total_points': total_points_team1 + total_points_team2,
'avg_points_per_game': (total_points_team1 + total_points_team2) / len(games)
}
}
# ==================== 创建球队和球员 ====================
def create_sample_teams() -> Tuple[Team, Team]:
"""创建示例球队"""
# 创建湖人队球员
lakers_players = [
Player("勒布朗·詹姆斯", "SF", 93, 85, 90, 85, 88, 92),
Player("安东尼·戴维斯", "PF", 92, 75, 88, 92, 90, 88),
Player("拉塞尔·威斯布鲁克", "PG", 88, 75, 80, 85, 82, 85),
Player("卡梅隆·安东尼", "SF", 85, 88, 85, 75, 70, 78),
Player("德怀特·霍华德", "C", 82, 60, 65, 85, 80, 75),
Player("小塔克", "SG", 80, 82, 78, 70, 72, 82),
Player("纳恩", "PG", 82, 85, 80, 75, 70, 80),
Player("蒙克", "SG", 78, 88, 75, 65, 65, 78)
]
# 创建勇士队球员
warriors_players = [
Player("斯蒂芬·库里", "PG", 95, 99, 90, 75, 80, 90),
Player("克莱·汤普森", "SG", 88, 95, 85, 75, 82, 88),
Player("德雷蒙德·格林", "PF", 85, 65, 75, 85, 92, 85),
Player("安德鲁·维金斯", "SF", 82, 80, 75, 82, 85, 82),
Player("凯文·卢尼", "C", 76, 60, 65, 80, 85, 72),
Player("乔丹·普尔", "SG", 80, 88, 78, 70, 70, 80),
Player("奥托·波特", "SF", 78, 85, 80, 72, 75, 78),
Player("加里·佩顿二世", "PG", 72, 70, 72, 78, 90, 72)
]
# 创建球队
lakers = Team("湖人", "洛杉矶", lakers_players)
warriors = Team("勇士", "旧金山", warriors_players)
return lakers, warriors
# ==================== 主程序 ====================
def main():
"""主函数"""
print("🏀 Welcome to NBA Playoffs Simulation !")
print("=" * 50)
# 创建球队
team1, team2 = create_sample_teams()
print(f"参赛球队:")
print(f" 1. {team1.full_name} (球队评分: {team1.get_team_rating():.1f})")
print(f" 2. {team2.full_name} (球队评分: {team2.get_team_rating():.1f})")
print()
# 创建系列赛模拟器
simulator = SeriesSimulator(team1, team2, best_of=7)
# 模拟系列赛
result = simulator.simulate_series()
# 分析结果
analyzer = SeriesAnalyzer()
analysis = analyzer.analyze_series(result)
# 输出最终结果
print("\n" + "=" * 50)
print(f"🏆 系列赛结果公布! 🏆")
print("=" * 50)
print(f"\n冠军球队: {result['champion'].full_name}")
print(f"系列赛比分: {team1.full_name} {team1.series_wins} - {team2.series_wins} {team2.full_name}")
print(f"系列赛最佳球员: {result['series_stats']['best_player']}")
print(f"\n📊 系列赛数据分析:")
print(f" - 进行了 {analysis['games_played']} 场比赛")
print(f" - 平均分差: {analysis['avg_margin']:.1f} 分")
print(f" - 得分王: {analysis['scoring_champ']}")
print(f" - 篮板王: {analysis['rebound_champ']}")
print(f" - 助攻王: {analysis['assist_champ']}")
print(f" - 最佳三分射手: {analysis['best_three_pt']}")
print(f" - 场均总得分: {analysis['total_games_stats']['avg_points_per_game']:.1f} 分")
# 输出每场比分
print("\n📋 详细比赛记录:")
for i, game in enumerate(result['series_stats']['games'], 1):
print(f" G{i}: {game['home_team']} {game['score'][game['home_team']]} - "
f"{game['score'][game['away_team']]} {game['away_team']} "
f"(获胜: {game['winner']})")
print("\n" + "=" * 50)
winner = result['champion']
print(f"🎉 最终胜利者: {winner.full_name}!")
print("=" * 50)
# 运行主程序
if __name__ == "__main__":
main()
运行效果示例
🏀 Welcome to NBA Playoffs Simulation !
==================================================
参赛球队:
1. 洛杉矶 湖人 (球队评分: 85.0)
2. 旧金山 勇士 (球队评分: 82.0)
==================================================
🏀 系列赛开始: 洛杉矶 湖人 vs 旧金山 勇士
==================================================
第 1 场比赛: 洛杉矶 湖人 (主场) vs 旧金山 勇士
--------------------------------------------
比分: 洛杉矶 湖人 112 - 108 旧金山 勇士
🎖️ 本场MVP: 勒布朗·詹姆斯 (32分)
系列赛比分: 洛杉矶 湖人 1 - 0 旧金山 勇士
...
(比赛继续)
这个案例整合了多个Python核心概念:
- 面向对象编程:使用类(Team, Player, GameEngine等)封装数据和行为
- 数据类(Dataclasses):简洁的类定义
- 类型提示:函数参数和返回值的类型标注
- 集合和字典:高效的数据管理
- 函数式编程:使用map, max等函数
- 异常处理:属性值验证
- 随机数生成:模拟比赛的不确定性
- 统计计算:数据分析功能
这个案例展示了如何用Python模拟复杂的现实场景,对于学习Python编程非常有帮助!