问题描述:采用胜一场得3分,平局各得1分,负一场得0分,排名以积分多者在前,当两队(或多队)积分相同时,则净胜球(即进球数与失球数之差)多者在前,若净胜球相同,则进球数多者在前,若仍相同,则并列。试编一程序统计最近一轮比赛后,各队积分及排名。
具体要求:
设积分表结构如下:队名,赢的场数,平的场数,负的场数,进球数,失球数,积分。积分表放在正文文件中。最近一轮的结果从键盘输入,其形式为:主队名(可用代码),客队名(可用代码),主队得分(即进球数),客队得分(即进球数)。程序应根据此轮结果修改各队的积分和名次,所得的最新记分表仍在原积分文件中并同时在屏幕上显示。
程序实现如下:
#include <iostream>
#include <list>
#include <string>
#include <fstream>
#include <map>
#include <vector>
#include <stdexcept>
#include <iomanip>
class Team {
public:
std::string name;
int matchesPlayed;
int wins;
int draws;
int losses;
int goalsFor;
int goalsAgainst;
int points;
int ranking;
Team() : name(""), matchesPlayed(0), wins(0), draws(0), losses(0), goalsFor(0), goalsAgainst(0), points(0), ranking(0) {}
int goalDifference() const {
return goalsFor - goalsAgainst;
}
void updateMatchResult(int scored, int conceded, int result) {
goalsFor += scored;
goalsAgainst += conceded;
matchesPlayed++;
if (result == 1) {
wins++;
points += 3;
}
else if (result == 0) {
draws++;
points += 1;
}
else {
losses++;
}
}
};
bool compareTeams(const Team& a, const Team& b) {
if (a.points != b.points)
return a.points > b.points;
if (a.goalDifference() != b.goalDifference())
return a.goalDifference() > b.goalDifference();
return a.goalsFor > b.goalsFor;
}
void readTeamsFromInput(std::list<Team>& teams) {
int numberOfTeams;
std::cout << "输入参赛球队数量: ";
if (!(std::cin >> numberOfTeams) || numberOfTeams <= 0) {
throw std::invalid_argument("无效的球队数量。请输入一个正整数。");
}
std::cin.ignore();
for (int i = 0; i < numberOfTeams; ++i) {
Team team;
std::cout << "输入第 " << (i + 1) << " 支球队的名称: ";
std::getline(std::cin, team.name);
teams.push_back(team);
}
}
void writeTeamsToFile(const std::list<Team>& teams, const std::string& filename) {
std::ofstream file(filename);
for (const auto& team : teams) {
file << team.name << " " << team.matchesPlayed << " " << team.wins << " " << team.draws << " "
<< team.losses << " " << team.goalsFor << " " << team.goalsAgainst << " " << team.points << std::endl;
}
file.close();
}
void updateRankings(std::list<Team>& teams) {
int rank = 1;
for (auto& team : teams) {
team.ranking = rank;
rank++;
}
}
void updateAndSortTeams(std::list<Team>& teams, const std::string& homeTeam, const std::string& awayTeam, int homeScore, int awayScore) {
bool homeTeamFound = false;
bool awayTeamFound = false;
for (auto& team : teams) {
if (team.name == homeTeam) {
team.updateMatchResult(homeScore, awayScore, (homeScore > awayScore) ? 1 : ((homeScore == awayScore) ? 0 : 2));
homeTeamFound = true;
}
if (team.name == awayTeam) {
team.updateMatchResult(awayScore, homeScore, (awayScore > homeScore) ? 1 : ((awayScore == homeScore) ? 0 : 2));
awayTeamFound = true;
}
}
if (!homeTeamFound || !awayTeamFound) {
throw std::invalid_argument("未找到指定的球队名称。请检查输入的球队名称是否正确。");
}
teams.sort(compareTeams);
updateRankings(teams);
}
void displayTeams(const std::list<Team>& teams) {
std::cout << std::left << std::setw(6) << "排名"
<< std::setw(20) << "球队"
<< std::setw(12) << "比赛场数"
<< std::setw(6) << "胜"
<< std::setw(6) << "平"
<< std::setw(6) << "负"
<< std::setw(10) << "进球数"
<< std::setw(12) << "失球数"
<< std::setw(10) << "总得分" << std::endl;
for (const auto& team : teams) {
std::cout << std::left << std::setw(6) << team.ranking
<< std::setw(20) << team.name
<< std::setw(12) << team.matchesPlayed
<< std::setw(6) << team.wins
<< std::setw(6) << team.draws
<< std::setw(6) << team.losses
<< std::setw(10) << team.goalsFor
<< std::setw(12) << team.goalsAgainst
<< std::setw(10) << team.points << std::endl;
}
}
int main() {
try {
std::list<Team> teams;
std::string filename = "teams.txt";
readTeamsFromInput(teams);
while (true) {
std::string matchDateInput;
std::string homeTeam, awayTeam;
int homeScore, awayScore;
std::cout << "输入比赛日期 (YYYY-MM-DD),输入 'exit' 退出: ";
std::cin >> matchDateInput;
if (matchDateInput == "exit") break;
std::cin.ignore();
std::cout << "输入主队名称: ";
std::getline(std::cin, homeTeam);
std::cout << "输入客队名称: ";
std::getline(std::cin, awayTeam);
std::cout << "输入主队进球数: ";
std::cin >> homeScore;
std::cout << "输入客队进球数: ";
std::cin >> awayScore;
updateAndSortTeams(teams, homeTeam, awayTeam, homeScore, awayScore);
displayTeams(teams);
}
writeTeamsToFile(teams, filename);
return 0;
}
catch (const std::exception& e) {
std::cerr << "错误: " << e.what() << std::endl;
return 1;
}
}
在 `main` 函数中,首先创建一个空的 `std::list<Team>` 类型的 `teams` 容器,用于存储球队信息,并指定一个文件名 `filename`。
调用 `readTeamsFromInput` 函数,该函数要求输入参赛球队的数量以及每支球队的名称。输入的球队信息被添加到 `teams` 容器中。
创建了一个空的 `std::map<std::string, int>` 类型的 `matchCount` 容器,用于记录每天比赛数量的映射,以及一个空的 `std::vector<std::string>` 类型的 `matchDate` 容器,用于记录比赛日期的向量。
进入主循环,该循环允许输入比赛信息,直到输入 "exit" 为止。
在每次循环迭代中,程序要求输入比赛日期(格式为 "YYYY-MM-DD")以及主队和客队的名称,主队和客队的进球数。然后,程序调用 `updateAndSortTeams` 函数来更新球队的比赛结果和积分。
updateAndSortTeams` 函数根据主队和客队的进球数判断比赛结果,并根据比赛结果更新球队的积分信息。如果输入的球队名称无效,将抛出异常。
每次比赛信息输入后,程序会调用 `displayTeams` 函数来显示更新后的球队排名和数据。
可以继续输入更多的比赛信息,或者输入 "exit" 来退出程序。
当选择退出程序时,程序将调用 `writeTeamsToFile` 函数将最终的球队信息写入文件 "teams.txt"。