一、任务描述
设计一款赛事管理系统,实现赛务相关的数据管理及信息服务,该系统能够为省级赛事管理解决以下问题:
1、队伍信息管理:
能够管理各参赛队的基本信息(包含参赛作品名称、参赛学校、赛事类别、参赛者和初赛成绩信息),赛事类别共11项;包括增加、删除、修改参赛队伍的信息。
2、队伍信息查询:
从team.txt中读取参赛队伍的基本信息,设计合适的数据结构存储,能实现对参赛队伍的增加、修改和浏览。为参赛队伍分配一个分数为60~100之间的初赛成绩,并能实现参赛队伍的成绩查询(实现基于二叉排序树的查找)。设计合适的输入输出,根据提示输入参赛队编号,查询队伍的初赛成绩。
3、赛事活动规划:
首先进行决赛分组,生成决赛秩序册,供参赛队查询。根据赛事类别将参赛队伍分配到17个决赛室(编号为1~17)。秩序册中每个决赛室的进场顺序为初赛成绩降序排列。(排序算法从选择排序、插入排序、希尔排序、归并排序、堆排序中选择一种,并为选择该算法的原因做出说明)然后,模拟决赛秩序。比赛现场会设置大型候赛区,场地中有大屏以时间线动态展示各决赛室中正在决赛的队伍,侯赛的队伍及比赛结束的队伍信息。请编写程序模拟候赛区大屏上动态展示各参赛队候场、比赛中、比赛结束的状态。
4、赛事地图查询:
为参赛者提供决赛主办地的各种路径导航的查询服务,以我校长山校区提供比赛场地为例,为参赛者提供不少于12个目标地的导航。为参赛者提供校园地图中任意目标地(建筑物)相关信息的查询;提供图中任意目标地(建筑物)的问路查询。
二、任务要求
1、请根据任务描述的问题,设计合理的菜单,菜单交互设计要合理,便于用户根据提示使用系统的所有功能。
2、赛事数据要求从文件(txt或excel)读入,修改后的信息能存入文件。
3、第三个任务赛地目的地查询,需输出目的地(建筑物)名称、代号、简介等信息;最短路径的输出需包含途经地及最短路径值;并分析主要算法的时间复杂度。
4、请自行设计测试数据。使用全部合法数据,整体非法数据,局部非法数据对程序测试,以保证程序的健壮性。
5、编码时请注意规范代码结构,重要的变量,函数要有清晰的注释;注重代码的效率和可重用性,实现低耦合、高内聚,不要将各种功能混在一个方法中编写。
三、代码实现
1、信息初始化和构建二叉排序树
用结构体class类来创建队伍的基本信息对象,先定义一个结构体Team来定义参赛队编号,参赛作品名称、参赛学校、赛事类别、参赛者和初赛成绩信息等基本信息。
代码如下:
2、实行文件操作
代码如下:
3、队伍管理
代码如下:
4、队伍查询
代码如下:
5、决赛叫号
代码如下:
6、校园导游
1、创建一张校园地图(带权无向图)
校园地图:
带权无向图:
代码如下:
7、主菜单代码
四、实验结果
五、源代码
#include <iostream>
#include <cstdlib> // for std::system
int main() {
int choice;
while (true) {
std::cout << "主菜单:\n";
std::cout << "1. 赛事信息管理系统\n";
std::cout << "2. 决赛秩序查询系统\n";
std::cout << "3. 决赛地图导览\n";
std::cout << "4. 退出\n";
std::cout << "请输入您的选择: ";
std::cin >> choice;
switch (choice) {
case 1:
std::system("\"C:\\Users\\LIU\\CLionProjects\\demo\\Competition information.exe\"");
break;
case 2:
std::system("\"C:\\Users\\LIU\\CLionProjects\\demo\\Mock final.exe\"");
break;
case 3:
std::system("\"C:\\Users\\LIU\\CLionProjects\\demo\\CampusMap.exe\"");
break;
case 4:
std::cout << "退出程序。\n";
return 0;
default:
std::cout << "无效的选择,请重新输入。\n";
break;
}
}
return 0;
}
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
struct TeamInfo {
int teamNumber;
std::string projectName;
std::string schoolName;
std::string category;
std::string participants;
int prelimScore;
TeamInfo* left;
TeamInfo* right;
TeamInfo(int number, const std::string& project, const std::string& school, const std::string& cat, const std::string& participants, int score)
: teamNumber(number), projectName(project), schoolName(school), category(cat), participants(participants), prelimScore(score), left(nullptr), right(nullptr) {}
};
class TeamManager {
private:
TeamInfo* root;
double totalASL;
int totalCount;
public:
TeamManager() : root(nullptr), totalASL(0), totalCount(0) {}
// 添加参赛队伍信息
void addTeam(int number, const std::string& project, const std::string& school, const std::string& cat, const std::string& participants, int score) {
root = insert(root, number, project, school, cat, participants, score);
}
// 修改参赛队伍信息
void updateTeam(int number, int newScore) {
root = update(root, number, newScore);
// 读取旧文件内容并更新相应队伍的信息,然后写回文件中
std::ifstream inputFile("team.txt");
if (inputFile.is_open()) {
std::string line;
std::string updatedContent;
getline(inputFile, line); // 读取并跳过标题行
updatedContent += line + "\n"; // 保留标题行
while (getline(inputFile, line)) {
std::istringstream iss(line);
int existingNumber;
std::string temp;
getline(iss, temp, '\t'); // 读取队伍编号
existingNumber = stoi(temp);
if (existingNumber == number) {
updatedContent += std::to_string(number) + "\t#\t" + temp + "\t#\t" + temp + "\t#\t" + temp + "\t#\t" + temp + "\t#\t" + std::to_string(newScore) + "\n";
} else {
updatedContent += line + "\n";
}
}
inputFile.close();
// 打开文件以写回更新后的内容
std::ofstream outputFile("team.txt");
if (outputFile.is_open()) {
outputFile << updatedContent;
outputFile.close();
} else {
std::cout << "无法打开team.txt文件以写回更新后的内容。" << std::endl;
}
} else {
std::cout << "无法打开team.txt文件。" << std::endl;
}
}
// 浏览所有参赛队伍信息
void browseTeams() {
inorderTraversal(root);
}
// 查询参赛队伍的初赛成绩
bool searchTeam(int number) {
TeamInfo* result = search(root, number);
if (result) {
std::cout << "队伍编号: " << result->teamNumber << std::endl;
std::cout << "参赛作品名称: " << result->projectName << std::endl;
std::cout << "参赛学校: " << result->schoolName << std::endl;
std::cout << "赛事类别: " << result->category << std::endl;
std::cout << "参赛者: " << result->participants << std::endl;
std::cout << "初赛成绩: " << result->prelimScore << std::endl;
return true;
} else {
std::cout << "未找到队伍编号为 " << number << " 的队伍。" << std::endl;
return false;
}
}
// 计算平均查找长度(ASL)
double calculateASL() {
totalASL = 0;
totalCount = 0;
calculateASL(root, 1);
if (totalCount == 0) return 0;
return totalASL / totalCount;
}
private:
TeamInfo* insert(TeamInfo* node, int number, const std::string& project, const std::string& school, const std::string& cat, const std::string& participants, int score) {
if (node == nullptr) {
return new TeamInfo(number, project, school, cat, participants, score);
}
if (number < node->teamNumber) {
node->left = insert(node->left, number, project, school, cat, participants, score);
} else if (number > node->teamNumber) {
node->right = insert(node->right, number, project, school, cat, participants, score);
}
return node;
}
TeamInfo* update(TeamInfo* node, int number, int newScore) {
if (node == nullptr) {
std::cout << "未找到队伍编号为 " << number << " 的队伍。" << std::endl;
return nullptr;
}
if (number < node->teamNumber) {
node->left = update(node->left, number, newScore);
} else if (number > node->teamNumber) {
node->right = update(node->right, number, newScore);
} else {
node->prelimScore = newScore;
std::cout << "成功更新队伍编号 " << number << " 的初赛成绩为 " << newScore << std::endl;
}
return node;
}
void inorderTraversal(TeamInfo* node) {
if (node == nullptr) return;
inorderTraversal(node->left);
std::cout << "队伍编号: " << node->teamNumber << ", 参赛作品名称: " << node->projectName << ", 初赛成绩: " << node->prelimScore << std::endl;
inorderTraversal(node->right);
}
TeamInfo* search(TeamInfo* node, int number) {
if (node == nullptr || node->teamNumber == number) {
return node;
}
if (number < node->teamNumber) {
return search(node->left, number);
} else {
return search(node->right, number);
}
}
void calculateASL(TeamInfo* node, int depth) {
if (node == nullptr) return;
totalASL += depth;
totalCount++;
calculateASL(node->left, depth + 1);
calculateASL(node->right, depth + 1);
}
};
int main() {
TeamManager manager;
// 从team.txt文件中读取参赛队伍信息并添加到管理系统中
std::ifstream inputFile("team.txt");
if (inputFile.is_open()) {
std::string line;
getline(inputFile, line); // 读取并跳过标题行
while (getline(inputFile, line)) {
std::istringstream iss(line);
int number, score;
std::string project, school, category, participants;
std::string temp;
getline(iss, temp, '\t'); // 读取队伍编号
number = stoi(temp);
getline(iss, temp, '\t'); // 跳过 #
getline(iss, project, '\t'); // 读取参赛作品名称
getline(iss, temp, '\t'); // 跳过 #
getline(iss, school, '\t'); // 读取参赛学校
getline(iss, temp, '\t'); // 跳过 #
getline(iss, category, '\t'); // 读取赛事类别
getline(iss, temp, '\t'); // 跳过 #
getline(iss, participants, '\t'); // 读取参赛者
getline(iss, temp, '\t'); // 跳过 #
getline(iss, temp, '\t'); // 读取初赛成绩
score = stoi(temp);
manager.addTeam(number, project, school, category, participants, score);
}
inputFile.close();
} else {
std::cout << "无法打开team.txt文件。" << std::endl;
}
int choice;
do {
std::cout << "赛事信息管理系统" << std::endl;
std::cout << "1. 添加参赛队伍" << std::endl;
std::cout << "2. 修改参赛队伍初赛成绩" << std::endl;
std::cout << "3. 浏览所有参赛队伍" << std::endl;
std::cout << "4. 查询参赛队伍初赛成绩" << std::endl;
std::cout << "5. 计算平均查找长度(ASL)" << std::endl;
std::cout << "6. 退出" << std::endl;
std::cout << "请选择操作: ";
std::cin >> choice;
switch (choice) {
case 1: {
int number, score;
std::string project, school, category, participants;
std::cout << "请输入队伍编号: ";
std::cin >> number;
std::cout << "请输入参赛作品名称: ";
std::cin >> project;
std::cout << "请输入参赛学校: ";
std::cin >> school;
std::cout << "请输入赛事类别: ";
std::cin >> category;
std::cout << "请输入参赛者: ";
std::cin >> participants;
std::cout << "请输入初赛成绩: ";
std::cin >> score;
manager.addTeam(number, project, school, category, participants, score);
break;
}
case 2: {
int number, newScore;
std::cout << "请输入要修改的队伍编号: ";
std::cin >> number;
std::cout << "请输入新的初赛成绩: ";
std::cin >> newScore;
manager.updateTeam(number, newScore);
break;
}
case 3: {
manager.browseTeams();
break;
}
case 4: {
int number;
std::cout << "请输入要查询的队伍编号: ";
std::cin >> number;
manager.searchTeam(number);
break;
}
case 5: {
double asl = manager.calculateASL();
std::cout << "平均查找长度(ASL): " << asl << std::endl;
break;
}
case 6: {
std::cout << "退出程序。" << std::endl;
break;
}
default: {
std::cout << "无效的选项,请重新选择。" << std::endl;
break;
}
}
} while (choice != 6);
return 0;
}
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <map>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <thread>
#include <chrono>
// 定义一个枚举类型来表示队伍的状态
enum class Status {
Waiting, // 候场
Playing, // 比赛中
Finished // 比赛结束
};
std::string statusToString(Status status) {
switch (status) {
case Status::Waiting: return "候场";
case Status::Playing: return "比赛中";
case Status::Finished: return "比赛结束";
default: return "未知状态";
}
}
struct TeamInfo {
int teamNumber;
std::string projectName;
std::string schoolName;
std::string category;
std::string participants;
int prelimScore;
int finalRoom;
Status status; // 使用枚举类型来表示状态
TeamInfo* left;
TeamInfo* right;
TeamInfo(int number, const std::string& project, const std::string& school,
const std::string& cat, const std::string& participants, int score, Status initialStatus)
: teamNumber(number), projectName(project), schoolName(school),
category(cat), participants(participants), prelimScore(score),
finalRoom(0), status(initialStatus), left(nullptr), right(nullptr) {}
};
class FinalRoundManager {
private:
TeamInfo* root;
std::map<int, std::vector<TeamInfo*>> finalRooms;
public:
FinalRoundManager() : root(nullptr) {}
void addTeam(int number, const std::string& project, const std::string& school,
const std::string& cat, const std::string& participants, int score, int finalRoomNumber) {
TeamInfo* newTeam = new TeamInfo(number, project, school, cat, participants, score, Status::Waiting);
newTeam->finalRoom = finalRoomNumber;
root = insert(root, newTeam);
finalRooms[finalRoomNumber].push_back(newTeam);
}
void queryFinalRoundOrder(int teamNumber) {
TeamInfo* team = search(root, teamNumber);
if (team) {
std::cout << "队伍编号: " << team->teamNumber << ", 决赛室编号: " << team->finalRoom << std::endl;
} else {
std::cout << "未找到队伍编号为 " << teamNumber << " 的队伍。" << std::endl;
}
}
// 在 FinalRoundManager 类中
void displayFinalRoomInfo(int roomNumber) {
auto it = finalRooms.find(roomNumber);
if (it != finalRooms.end()) {
for (TeamInfo* team : it->second) {
// 随机设置状态
int randomStatus = std::rand() % 3; // 生成一个0到2的随机数
team->status = static_cast<Status>(randomStatus);
std::cout << "队伍编号: " << team->teamNumber
<< ", 状态: " << statusToString(team->status) << std::endl;
// 暂停一段时间
std::this_thread::sleep_for(std::chrono::seconds(1));
}
} else {
std::cout << "没有编号为 " << roomNumber << " 的决赛室。" << std::endl;
}
}
// 根据输入的决赛室编号和状态更新所有队伍的状态
void setTeamsStatus(int roomNumber, Status newStatus) {
auto it = finalRooms.find(roomNumber);
if (it != finalRooms.end()) {
for (TeamInfo* team : it->second) {
team->status = newStatus;
}
}
}
void loadTeamsFromFile(const std::string& filename) {
std::ifstream inputFile(filename);
if (!inputFile.is_open()) {
std::cout << "无法打开文件 " << filename << "。" << std::endl;
return;
}
std::string line;
getline(inputFile, line); // 跳过标题行
while (getline(inputFile, line)) {
std::istringstream iss(line);
std::string token;
std::vector<std::string> tokens;
// 使用逗号作为分隔符读取数据
while (getline(iss, token, ',')) {
tokens.push_back(token);
}
// 检查确保每行有正确数量的数据
if (tokens.size() == 7) {
int finalRoomNumber = std::stoi(tokens[0]);
int number = std::stoi(tokens[1]);
std::string& project = tokens[2];
std::string& school = tokens[3];
std::string& category = tokens[4];
std::string& participants = tokens[5];
int score = std::stoi(tokens[6]);
// 在这里添加队伍
addTeam(number, project, school, category, participants, score, finalRoomNumber);
}
}
inputFile.close();
}
private:
TeamInfo* insert(TeamInfo* node, TeamInfo* newTeam) {
if (node == nullptr) {
return newTeam;
} else if (newTeam->teamNumber < node->teamNumber) {
node->left = insert(node->left, newTeam);
} else if (newTeam->teamNumber > node->teamNumber) {
node->right = insert(node->right, newTeam);
}
return node;
}
TeamInfo* search(TeamInfo* node, int number) {
if (node == nullptr) return nullptr;
if (number == node->teamNumber) return node;
if (number < node->teamNumber) return search(node->left, number);
return search(node->right, number);
}
};
int main() {
std::srand(static_cast<unsigned int>(std::time(nullptr))); // 初始化随机数生成器
FinalRoundManager manager;
manager.loadTeamsFromFile("end.csv");
int choice;
do {
std::cout << "\n决赛秩序查询系统\n";
std::cout << "1. 查询决赛秩序册\n";
std::cout << "2. 展示决赛室信息\n";
std::cout << "3. 退出\n";
std::cout << "请选择操作: ";
std::cin >> choice;
switch (choice) {
case 1: {
int teamNumber;
std::cout << "请输入队伍编号: ";
std::cin >> teamNumber;
manager.queryFinalRoundOrder(teamNumber);
break;
}
case 2: {
int roomNumber;
std::cout << "请输入决赛室编号: ";
std::cin >> roomNumber;
// 在这里可以调用setTeamsStatus更新状态
// 例如: manager.setTeamsStatus(roomNumber, Status::Playing);
manager.displayFinalRoomInfo(roomNumber);
break;
}
case 3:
std::cout << "退出程序。" << std::endl;
break;
default:
std::cout << "无效的选项,请重新选择。" << std::endl;
break;
}
} while (choice != 3);
return 0;
}
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <queue>
#include <climits>
using namespace std;
struct Vertex {
string name;
string description;
};
struct Edge {
int length;
Edge() : length(0) {} // 默认构造函数,初始化长度为 0
};
class CampusMap {
public:
CampusMap(int numNodes) {
adjacencyMatrix.resize(numNodes, vector<Edge>(numNodes)); // 初始化邻接矩阵大小
}
CampusMap() {
adjacencyMatrix.resize(100); // 假设校园最多有 100 个地点
for (auto &row : adjacencyMatrix) {
row.resize(100);
}
}
void addLocation(int id, const string& name, const string& description) {
// 确保 id 不超过邻接矩阵的大小
if (id >= adjacencyMatrix.size()) {
cout << "ID 超出最大限制,添加地点失败。" << endl;
return;
}
vertices[id] = {name, description};
}
void addPath(int startNode, int targetNode, int pathLength) {
if (startNode >= adjacencyMatrix.size() || targetNode >= adjacencyMatrix.size()) {
cout << "节点编号超出范围,添加路径失败。" << endl;
return;
}
adjacencyMatrix[startNode][targetNode].length = pathLength;
adjacencyMatrix[targetNode][startNode].length = pathLength; // 假设双向路径
}
void removePath(int startNode, int targetNode) {
if (startNode >= adjacencyMatrix.size() || targetNode >= adjacencyMatrix.size()) {
cout << "节点编号超出范围,删除路径失败。" << endl;
return;
}
adjacencyMatrix[startNode][targetNode].length = 0;
adjacencyMatrix[targetNode][startNode].length = 0; // 假设双向路径
}
void displayLocationInfo(int id) {
if (vertices.find(id) != vertices.end()) {
// 在输出名称时包括 ID
cout << "编号: " << id << ", 名称: " << vertices[id].name << endl;
cout << "描述: " << vertices[id].description << endl;
} else {
cout << "未找到该地点信息。" << endl;
}
}
string getLocationName(int id) {
if (vertices.find(id) != vertices.end()) {
// 在名称字符串中包括 ID
return "编号: " + to_string(id) + ", 名称: " + vertices[id].name;
} else {
return "未找到地点";
}
}
void findShortestPath(int startNode, int targetNode) {
if (startNode >= adjacencyMatrix.size() || targetNode >= adjacencyMatrix.size()) {
cout << "节点编号超出范围,无法找到最短路径。" << endl;
return;
}
vector<int> distance(adjacencyMatrix.size(), INT_MAX);
vector<int> path(adjacencyMatrix.size(), -1);
vector<bool> visited(adjacencyMatrix.size(), false);
distance[startNode] = 0;
for (int i = 0; i < adjacencyMatrix.size() - 1; ++i) {
int u = shortestDistance(distance, visited);
visited[u] = true;
for (int v = 0; v < adjacencyMatrix.size(); ++v) {
if (!visited[v] && adjacencyMatrix[u][v].length != 0 &&
distance[u] != INT_MAX && distance[u] + adjacencyMatrix[u][v].length < distance[v]) {
distance[v] = distance[u] + adjacencyMatrix[u][v].length;
path[v] = u;
}
}
}
cout << "从 " << vertices[startNode].name << " 到 " << vertices[targetNode].name << " 的最短路径:" << endl;
displayPath(targetNode, path);
cout << "总距离: " << distance[targetNode] << " 米" << endl;
}
private:
unordered_map<int, Vertex> vertices;
vector<vector<Edge>> adjacencyMatrix;
int shortestDistance(const vector<int>& distance, const vector<bool>& visited) {
int shortestDist = INT_MAX, shortestIndex = -1;
for (int v = 0; v < adjacencyMatrix.size(); ++v) {
if (!visited[v] && distance[v] <= shortestDist) {
shortestDist = distance[v];
shortestIndex = v;
}
}
return shortestIndex;
}
void displayPath(int node, const vector<int>& path) {
if (node == -1) {
return;
}
displayPath(path[node], path);
if (node != path[node]) { // 防止打印起点两次
cout << " -> " << vertices[node].name;
}
}
};
int main() {
CampusMap campus(20); // 假设校园有 20 个地点
campus.addLocation(1, "3号组团D楼", "·······");
campus.addLocation(2, "好又多超市", "·······");
campus.addLocation(3, "明德园", "·······");
campus.addLocation(4, "大学生活动中心", "·······");
campus.addLocation(5, "足球场", "·······");
campus.addLocation(6, "扬帆广场", "·······");
campus.addLocation(7, "经管学院楼", "·······");
campus.addLocation(8, "求索园", "·······");
campus.addLocation(9, "东苑食堂", "·······");
campus.addLocation(10, "图书馆", "·······");
campus.addLocation(11, "计算机学院楼", "·······");
campus.addLocation(12, "能动学院楼", "·······");
// Add more locations...
campus.addPath(1,2 , 100); // Example path 图书馆到紫金湖
campus.addPath(1, 4, 200);
campus.addPath(2, 4, 150);
campus.addPath(2, 3, 80);
campus.addPath(4, 5, 50);
campus.addPath(3, 5, 120);
campus.addPath(3, 6, 110);
campus.addPath(5, 8, 150);
campus.addPath(5, 9, 230);
campus.addPath(6, 8, 60);
campus.addPath(6, 7, 80);
campus.addPath(8, 9, 90);
campus.addPath(8, 10, 70);
campus.addPath(7, 10, 100);
campus.addPath(10, 9, 50);
// Add more paths...
int choice;
do {
cout << "决赛地图导览:" << endl;
cout << "1. 查询景点信息" << endl;
cout << "2. 查询最短路径" << endl;
cout << "3. 退出" << endl;
cout << "请输入您的选择: ";
cin >> choice;
switch (choice) {
case 1: {
int locationID;
cout << "请输入景点编号: ";
cin >> locationID;
campus.displayLocationInfo(locationID);
break;
}
case 2: {
int startLocation, targetLocation;
cout << "请输入起始景点编号: ";
cin >> startLocation;
cout << "请输入目标景点编号: ";
cin >> targetLocation;
campus.findShortestPath(startLocation, targetLocation);
break;
}
case 3:
cout << "退出程序。" << endl;
break;
default:
cout << "无效的选择。请重试。" << endl;
}
} while (choice != 4);
return 0;
}