基于jQuery Bracket生成世界杯式8组循环赛及数据库存储指南问询
基于jQuery Bracket复刻世界杯赛制教程
一、赛制整体说明
世界杯赛制分为两个核心阶段:
- 小组赛阶段:8个小组,每组4支球队进行单循环赛(每队与组内其他3队各赛一场),每组前两名晋级淘汰赛。
- 淘汰赛阶段:16支晋级球队采用单败淘汰制,对阵规则为小组第一对阵其他小组第二(同小组球队首轮不相遇),直至决出冠军。
二、搭建小组赛阶段
1. HTML结构
添加8个小组的比赛与排名展示区域,以及触发排名计算的按钮:
<div class="group-container"> <div class="group" id="groupA"> <h3>A组</h3> <table class="group-matches"> <thead> <tr><th>主队</th><th>比分</th><th>客队</th></tr> </thead> <tbody></tbody> </table> <table class="group-standings"> <thead> <tr><th>排名</th><th>球队</th><th>场次</th><th>胜</th><th>平</th><th>负</th><th>进球</th><th>失球</th><th>净胜球</th><th>积分</th></tr> </thead> <tbody></tbody> </table> </div> <!-- 重复B-H组结构,id依次为groupB至groupH --> </div> <button id="calculateStandings">计算排名并生成淘汰赛</button> <div id="knockoutBracket"></div>
2. 初始化小组比赛
在JS中定义各小组球队,并自动生成所有单循环对阵:
$(document).ready(function() { // 定义8个小组的参赛球队 var groupsData = { groupA: ['卡塔尔', '厄瓜多尔', '塞内加尔', '荷兰'], groupB: ['英格兰', '伊朗', '美国', '威尔士'], groupC: ['阿根廷', '沙特阿拉伯', '墨西哥', '波兰'], groupD: ['法国', '澳大利亚', '丹麦', '突尼斯'], groupE: ['西班牙', '哥斯达黎加', '德国', '日本'], groupF: ['比利时', '加拿大', '摩洛哥', '克罗地亚'], groupG: ['巴西', '塞尔维亚', '瑞士', '喀麦隆'], groupH: ['葡萄牙', '加纳', '乌拉圭', '韩国'] }; // 生成单循环对阵的工具函数 function generateRoundRobinMatches(teams) { var matches = []; for (var i = 0; i < teams.length; i++) { for (var j = i + 1; j < teams.length; j++) { matches.push([teams[i], teams[j]]); } } return matches; } // 为每个小组渲染比赛表格 $.each(groupsData, function(groupId, teams) { var matches = generateRoundRobinMatches(teams); var $tbody = $('#' + groupId + ' .group-matches tbody'); matches.forEach(function(match) { var row = `<tr><td>${match[0]}</td><td><input type="number" class="goals" min="0" value="0"> - <input type="number" class="goals" min="0" value="0"></td><td>${match[1]}</td></tr>`; $tbody.append(row); }); }); });
3. 计算小组排名
实现符合世界杯规则的排名逻辑(积分优先,净胜球次之,进球数次之):
function calculateGroupStandings(groupId) { var teams = groupsData[groupId]; // 初始化各队数据 var standings = teams.map(function(team) { return { name: team, played: 0, won: 0, drawn: 0, lost: 0, goalsFor: 0, goalsAgainst: 0, goalDifference: 0, points: 0 }; }); // 读取所有比赛结果并更新数据 var $matches = $('#' + groupId + ' .group-matches tbody tr'); $matches.each(function() { var homeTeam = $(this).find('td:first').text(); var awayTeam = $(this).find('td:last').text(); var homeGoals = parseInt($(this).find('.goals:first').val()); var awayGoals = parseInt($(this).find('.goals:last').val()); var homeStanding = standings.find(s => s.name === homeTeam); var awayStanding = standings.find(s => s.name === awayTeam); // 更新场次与进球数据 homeStanding.played++; awayStanding.played++; homeStanding.goalsFor += homeGoals; homeStanding.goalsAgainst += awayGoals; awayStanding.goalsFor += awayGoals; awayStanding.goalsAgainst += homeGoals; // 更新胜负与积分 if (homeGoals > awayGoals) { homeStanding.won++; homeStanding.points += 3; awayStanding.lost++; } else if (homeGoals === awayGoals) { homeStanding.drawn++; homeStanding.points += 1; awayStanding.drawn++; awayStanding.points += 1; } else { awayStanding.won++; awayStanding.points += 3; homeStanding.lost++; } }); // 计算净胜球并排序 standings.forEach(function(s) { s.goalDifference = s.goalsFor - s.goalsAgainst; }); standings.sort(function(a, b) { if (b.points !== a.points) return b.points - a.points; if (b.goalDifference !== a.goalDifference) return b.goalDifference - a.goalDifference; if (b.goalsFor !== a.goalsFor) return b.goalsFor - a.goalsFor; return 0; }); // 更新排名表格 var $standingsTbody = $('#' + groupId + ' .group-standings tbody'); $standingsTbody.empty(); standings.forEach(function(s, index) { var row = `<tr><td>${index+1}</td><td>${s.name}</td><td>${s.played}</td><td>${s.won}</td><td>${s.drawn}</td><td>${s.lost}</td><td>${s.goalsFor}</td><td>${s.goalsAgainst}</td><td>${s.goalDifference}</td><td>${s.points}</td></tr>`; $standingsTbody.append(row); }); // 返回小组前两名 return [standings[0].name, standings[1].name]; }
三、搭建淘汰赛阶段
1. 生成淘汰赛对阵
绑定按钮点击事件,计算所有小组排名后生成符合世界杯规则的淘汰赛 bracket:
$('#calculateStandings').click(function() { // 获取所有小组的晋级球队 var groupQualifiers = { groupA: calculateGroupStandings('groupA'), groupB: calculateGroupStandings('groupB'), groupC: calculateGroupStandings('groupC'), groupD: calculateGroupStandings('groupD'), groupE: calculateGroupStandings('groupE'), groupF: calculateGroupStandings('groupF'), groupG: calculateGroupStandings('groupG'), groupH: calculateGroupStandings('groupH') }; // 按照世界杯规则生成1/8决赛对阵 var knockoutTeams = [ [groupQualifiers.groupA[0], groupQualifiers.groupB[1]], [groupQualifiers.groupC[0], groupQualifiers.groupD[1]], [groupQualifiers.groupE[0], groupQualifiers.groupF[1]], [groupQualifiers.groupG[0], groupQualifiers.groupH[1]], [groupQualifiers.groupB[0], groupQualifiers.groupA[1]], [groupQualifiers.groupD[0], groupQualifiers.groupC[1]], [groupQualifiers.groupF[0], groupQualifiers.groupE[1]], [groupQualifiers.groupH[0], groupQualifiers.groupG[1]] ]; // 初始化淘汰赛 bracket $('#knockoutBracket').bracket({ init: { teams: knockoutTeams, results: [] }, skipConsolationRound: true, onMatchUpdate: function(match) { // 比赛结果更新时触发保存逻辑 saveMatchData(match); } }); // 保存小组赛数据 saveGroupMatches(); });
四、赛事数据保存到数据库
1. 数据库表设计(MySQL示例)
创建两个表分别存储小组赛与淘汰赛数据:
-- 小组赛数据表 CREATE TABLE group_matches ( id INT AUTO_INCREMENT PRIMARY KEY, group_id VARCHAR(10) NOT NULL, home_team VARCHAR(50) NOT NULL, away_team VARCHAR(50) NOT NULL, home_goals INT NOT NULL, away_goals INT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); -- 淘汰赛数据表 CREATE TABLE knockout_matches ( id INT AUTO_INCREMENT PRIMARY KEY, round INT NOT NULL, -- 1:1/8决赛, 2:1/4决赛, 3:半决赛,4:决赛 match_index INT NOT NULL, home_team VARCHAR(50), away_team VARCHAR(50), home_goals INT, away_goals INT, winner VARCHAR(50), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );
2. 前端AJAX保存逻辑
编写函数将比赛结果发送至后端:
// 保存所有小组赛数据 function saveGroupMatches() { $.each(groupsData, function(groupId, teams) { var $matches = $('#' + groupId + ' .group-matches tbody tr'); $matches.each(function() { var homeTeam = $(this).find('td:first').text(); var awayTeam = $(this).find('td:last').text(); var homeGoals = parseInt($(this).find('.goals:first').val()); var awayGoals = parseInt($(this).find('.goals:last').val()); $.ajax({ url: 'save_group_match.php', method: 'POST', data: { group_id: groupId, home_team: homeTeam, away_team: awayTeam, home_goals: homeGoals, away_goals: awayGoals }, success: function() { console.log('小组赛数据保存成功'); }, error: function() { console.error('小组赛数据保存失败'); } }); }); }); } // 保存淘汰赛数据 function saveMatchData(match) { var round = match.round + 1; var matchIndex = match.index; var homeTeam = match.team1; var awayTeam = match.team2; var homeGoals = match.score1; var awayGoals = match.score2; var winner = homeGoals > awayGoals ? homeTeam : awayTeam; $.ajax({ url: 'save_knockout_match.php', method: 'POST', data: { round: round, match_index: matchIndex, home_team: homeTeam, away_team: awayTeam, home_goals: homeGoals, away_goals: awayGoals, winner: winner }, success: function() { console.log('淘汰赛数据保存成功'); }, error: function() { console.error('淘汰赛数据保存失败'); } }); }
3. 后端处理脚本(PHP示例)
save_group_match.php:
<?php $conn = new mysqli('localhost', '用户名', '密码', '数据库名'); if ($conn->connect_error) die("连接失败: " . $conn->connect_error); $groupId = $_POST['group_id']; $homeTeam = $_POST['home_team']; $awayTeam = $_POST['away_team']; $homeGoals = $_POST['home_goals']; $awayGoals = $_POST['away_goals']; // 检查是否已存在该比赛,存在则更新,否则插入 $sql = "SELECT id FROM group_matches WHERE group_id = ? AND home_team = ? AND away_team = ?"; $stmt = $conn->prepare($sql); $stmt->bind_param("sss", $groupId, $homeTeam, $awayTeam); $stmt->execute(); $result = $stmt->get_result(); if ($result->num_rows > 0) { $sql = "UPDATE group_matches SET home_goals = ?, away_goals = ? WHERE group_id = ? AND home_team = ? AND away_team = ?"; $stmt = $conn->prepare($sql); $stmt->bind_param("iisss", $homeGoals, $awayGoals, $groupId, $homeTeam, $awayTeam); } else { $sql = "INSERT INTO group_matches (group_id, home_team, away_team, home_goals, away_goals) VALUES (?, ?, ?, ?, ?)"; $stmt = $conn->prepare($sql); $stmt->bind_param("sssii", $groupId, $homeTeam, $awayTeam, $homeGoals, $awayGoals); } $stmt->execute(); $stmt->close(); $conn->close(); echo "保存成功"; ?>
save_knockout_match.php逻辑类似,处理淘汰赛数据的插入与更新。
内容的提问来源于stack exchange,提问作者NoGodButAllah
相关产品推荐
相关产品推荐

