You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

仿世界杯淘汰赛制的球队积分统计与晋级实现方案咨询

问题描述

我正在尝试实现一个能统计各球队总进球数,并确定哪些球队晋级1/4决赛、半决赛和决赛的程序。目前已经完成了球队随机分组、随机生成球队进球数(包含直接胜负或点球决胜)的功能。现在需要实现仿世界杯的淘汰赛制,让程序能根据随机生成的分数把球队送入后续轮次,同时还要统计各队的总进球数。作为编程新手,我考虑用struct来实现,但不确定具体操作方式和代码编写方法。

当前代码
#include <iostream>
#include <string>
#include <ctime>
#include <random>
#include <algorithm>
#include <thread>
#include <chrono>
#include <cmath>
#include <fstream>
#include <cstdlib>
 
using namespace std;

struct Values{
    int win;
    int loss;
    int penalty;
    int randomNumber;
    int randomDigit;
}myNum;


void draw(string teams[],size_t num_teams ) ;

int main()
{
    using namespace std;
    cout << "Welcome to the FIFA World Cup draw\n"
         << "\nThe draw will include the following teams:\n\n" ;

    const size_t NTEAMS = 16 ;
    string teams[NTEAMS] =
    {
       "Argentina", 
        "Portugal", 
        "England",
        "Germany", 
        "United States", 
        "France", 
        "Spain", 
        "Japan", 
        "Canada", 
        "Mexico", 
        "Poland", 
        "South Korea", 
        "Uruguay", 
        "Wales", 
        "Switzerland", 
        "Croatia"
    };
    
    
    for( const string& team_name : teams ) cout << '\t' << team_name << '\n' ;

    cout << "\nThere are no rules in regards to which team can play who.\n"
              << "Anyone can draw anyone!\n\n"
              << "To start the draw, please press s and enter!\n"
              << "Good luck to all teams!\n\n";

    char start ;
    std::cin >> start;

    if ( (start == 's') || (start == 'S') ) draw( teams, NTEAMS ) ;
    else
    {
        std::cout << "\nInvalid entry! the program will now close!\n"
                  << "Open again and only press s to start the draw!\n" ;
    }
}

void draw( std::string teams[], std::size_t num_teams )
{
    // random number engine, seeded with the current time
    
    std::mt19937 rng( std::time(nullptr) ) ;

    // shuffle the teams in the array like we would shuffle a pack of cards
    
    std::shuffle( teams, teams+num_teams, rng ) ;

    // print out the pairings
    for( std::size_t i = 0 ; i < num_teams ; i += 2 )
    {
        
        std::this_thread::sleep_for( std::chrono::seconds(1) ) ;
        std::cout << "\n\t" << teams[i] << " vs. " << teams[i+1] << '\n' ;

        srand((unsigned) time(0));
        
        int randomNumber;
        int randomDigit;
        string win;
        string penalty;
        string loss;

        for(int i=0; i<1; i++){
            randomNumber=(rand() % 10);
            randomDigit=(rand() % 10);
            win = "Direct Win";
            penalty = "By Penalty";
            loss = "Direct Loss";
            
            std::cout <<"Round scores: " <<randomNumber << " vs. " << randomDigit << '\n';
            if (randomNumber > randomDigit ){  
                std::cout << win;

            } else if ( randomNumber <= randomDigit ) {
            std::cout << penalty;
            }
        
        }   
        
    
     }
    
 }
实现方案建议

1. 重构球队数据结构

原来的Values结构体未针对球队属性设计,应重新定义Team结构体来统一存储每个球队的核心信息:

struct Team {
    string name;
    int total_goals = 0; // 初始化总进球数为0
    bool is_eliminated = false; // 标记球队是否被淘汰
};

用这个结构体的容器(比如vector<Team>)替代原有的字符串数组,方便后续管理球队的进球数和晋级状态。

2. 封装单场比赛逻辑

编写独立函数处理单场比赛,负责生成合理比分、判断胜负、更新球队总进球数,并返回晋级球队。需修正原代码中的点球逻辑(仅常规时间平局才触发点球):

Team playMatch(Team& teamA, Team& teamB, mt19937& rng) {
    // 生成常规时间进球数(0-4更符合实际比赛情况)
    uniform_int_distribution<int> goalDist(0, 4);
    int goalsA = goalDist(rng);
    int goalsB = goalDist(rng);

    // 更新两队总进球数
    teamA.total_goals += goalsA;
    teamB.total_goals += goalsB;

    cout << "\t" << teamA.name << " " << goalsA << " vs " << teamB.name << " " << goalsB;

    // 判断常规时间胜负
    if (goalsA > goalsB) {
        cout << " - " << teamA.name << "直接晋级\n";
        teamB.is_eliminated = true;
        return teamA;
    } else if (goalsB > goalsA) {
        cout << " - " << teamB.name << "直接晋级\n";
        teamA.is_eliminated = true;
        return teamB;
    } else {
        // 点球决胜逻辑
        uniform_int_distribution<int> penaltyDist(0, 5);
        int pensA = penaltyDist(rng);
        int pensB = penaltyDist(rng);
        cout << " 常规时间平局,点球大战:" << pensA << " vs " << pensB;

        // 确保点球分出胜负(可循环直到结果不同,这里简化处理)
        if (pensA > pensB) {
            cout << " - " << teamA.name << "点球晋级\n";
            teamB.is_eliminated = true;
            return teamA;
        } else {
            cout << " - " << teamB.name << "点球晋级\n";
            teamA.is_eliminated = true;
            return teamB;
        }
    }
}

注意统一使用mt19937随机引擎,避免混用rand(),保证随机性一致。

3. 分阶段执行淘汰赛

世界杯淘汰赛分为四轮:1/8决赛(16进8)、1/4决赛(8进4)、半决赛(4进2)、决赛(2进1)。编写函数处理每一轮比赛,收集晋级球队进入下一轮:

void runKnockoutRound(vector<Team>& currentTeams, mt19937& rng, const string& roundName) {
    cout << "\n=== " << roundName << " ===\n";
    vector<Team> nextRoundTeams;

    // 两两配对比赛
    for (size_t i = 0; i < currentTeams.size(); i += 2) {
        this_thread::sleep_for(chrono::seconds(1));
        Team winner = playMatch(currentTeams[i], currentTeams[i+1], rng);
        nextRoundTeams.push_back(winner);
    }

    // 更新球队列表为下一轮参赛队伍
    currentTeams = move(nextRoundTeams);
}

4. 主函数整合逻辑

在主函数中初始化球队、打乱分组、依次执行各轮淘汰赛,并最终输出冠军和总进球统计:

int main() {
    cout << "Welcome to the FIFA World Cup Knockout Simulator\n\n";

    // 初始化所有球队
    vector<Team> allTeams = {
        {"Argentina"}, {"Portugal"}, {"England"}, {"Germany"},
        {"United States"}, {"France"}, {"Spain"}, {"Japan"},
        {"Canada"}, {"Mexico"}, {"Poland"}, {"South Korea"},
        {"Uruguay"}, {"Wales"}, {"Switzerland"}, {"Croatia"}
    };

    // 复制一份用于后续总进球统计(避免被淘汰后丢失数据)
    vector<Team> originalTeams = allTeams;

    // 随机打乱分组
    mt19937 rng(time(nullptr));
    shuffle(allTeams.begin(), allTeams.end(), rng);

    // 执行各轮淘汰赛
    runKnockoutRound(allTeams, rng, "1/8决赛");
    runKnockoutRound(allTeams, rng, "1/4决赛");
    runKnockoutRound(allTeams, rng, "半决赛");
    runKnockoutRound(allTeams, rng, "决赛");

    // 输出冠军
    cout << "\n=== 世界杯冠军:" << allTeams[0].name << " ===" << endl;

    // 输出所有球队总进球统计
    cout << "\n所有球队总进球统计:\n";
    for (const auto& team : originalTeams) {
        cout << "\t" << team.name << ": " << team.total_goals << "球\n";
    }

    return 0;
}

关键注意事项

  • 避免全局使用using namespace std;,可在函数内使用或添加std::前缀,减少命名冲突风险。
  • 随机引擎只需初始化一次,不要在循环中重复初始化,否则会导致随机数重复。
  • 保留原始球队列表用于总进球统计,避免仅保留当前轮次球队导致数据丢失。

内容的提问来源于stack exchange,提问作者user20566606

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 11:45:45