文章目录
一、项目要求
- 学校举办一场演讲比赛,共有12个人参加,比赛共两轮,第一轮为淘汰赛,第二轮为决赛
- 每名选手都有对应的编号,如10001~10012
- 比赛方式:分组比赛,每组6个人
- 第一轮分为两个小组,整体按照选手编号进行抽签后顺序演讲
- 是个评委分别给每个选手打分,去除最高分和最低分,求的平均分为本轮选手的成绩
- 当小组演讲完后,淘汰组内排名最后的三个选手,前三名晋级,进入下一轮的比赛
- 第二轮为决赛,前三名胜出
- 每轮比赛过后需要显示晋级选手的信息
二、需求分析
首先,选手可以抽象成一个类,属性有编号和分数,选手可以放在一个vector容器中,淘汰赛容器放12个人,抽签就相当于打乱顺序。之后将前6个人移动到一个容器中,后六个人移动到另外一个容器中。评委打分可以创建一个deque容器,排序后去除一个最高分和最低分,求和后除以8得到平均分,赋值给对应的选手分数属性。用sort方法分别对两个容器进行排序,取前三名移动到决赛的vector容器中,打乱顺序,重复上面的操作,为减少代码的重复性,可以将评委打分创建成一个函数,传入一个vector容器即可,最后排序后打印前三名的信息。将最终的结果保存在csv文件中。
三、代码实现
3.1 选手类
class Person {
public:
Person() {};
Person(string id,float score) {
m_id = id;
m_score = score;
}
string m_id;
float m_score;
};
3.2 打印函数
class Myprint {
public:
void operator()(Person &p){
cout << "编号:" << p.m_id << " 平均分:" <<fixed << setprecision(2)<<p.m_score << endl;
}
};
// 显示选手信息
void showPerson(vector<Person> &v) {
for_each(v.begin(), v.end(), Myprint());
}
// 打印抽签顺序
class Printid {
public:
void operator()(Person& p) {
cout << p.m_id << " ";
}
};
3.3 显示菜单
// 显示选项菜单
void showmanu() {
cout << "———欢迎来到演讲比赛流程管理系统———" << endl;
cout << " 1.开始演讲比赛" << endl;
cout << " 2.查看往届记录" << endl;
cout << " 3.清空比赛记录" << endl;
cout << " 4.退出比赛系统" << endl;
}
3.4 仿函数
class Transfor {
public:
Person operator()(Person p) {
return p;
}
};
class Sortscore {
public:
bool operator()(Person& p1, Person& p2) {
return p1.m_score > p2.m_score;
}
};
3.5 打分函数
// 打分函数
void addScore(vector<Person> &v) {
// 将评委打分放入deque容器中
for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) {
// 创建评委打分
deque<int> dq;
for (int i = 0; i < 10; i++) {
int score = rand() % 41 + 60; // 60-100
dq.push_back(score);
}
// 去除最高分和最低分
sort(dq.begin(), dq.end());
dq.pop_back();
dq.pop_front();
// 计算平均分
float avracore = ((float)accumulate(dq.begin(), dq.end(), 0) / 8);
// 添加平均分
(*it).m_score = avracore;
}
}
3.6 保存分数
// 保存分数
void saveCSV(vector<Person>& v,int &count) {
ofstream ofs;
// 打开文件
ofs.open("speech.csv", ios::out | ios::app);
vector<Person>::iterator it = v.begin();
ofs << "第"<<count<<"届成绩: ";
for (int i = 0; i < 3; it++,i++) {
ofs <<"编号:" << "," << (*it).m_id << "," <<"分数:" << "," << (*it).m_score << ",";
}
count++;
ofs << endl;
ofs.close();
cout << "保存完毕!" << endl;
}
3.7 查看往届记录
void showCSV() {
ifstream ifs;
// 打开文件
ifs.open("speech.csv", ios::in);
char buf[1024] = { 0 };
while (ifs >> buf) {
cout << buf << endl;
}
}
3.8 清空往届记录
// 清空往届记录
void delCSV() {
ofstream ofs;
// 打开文件
ofs.open("speech.csv", ios::trunc); // 先删除再创建
ofs.close();
cout << "删除完毕!" << endl;
}
3.9 开始比赛
void startSpeech(int &count) {
// 创建12个选手,全部放到vector容器中
vector<Person> v1;
for (int i = 0; i < 12; i++) {
// 创建编号
string name = to_string(10000 + i);
float score = 0.0;
Person p(name, score);
v1.push_back(p); // 添加
}
system("pause");
// 开始抽签
cout << "开始抽签!" << endl;
random_shuffle(v1.begin(), v1.end());
cout << "抽签顺序为:" << endl;
for_each(v1.begin(), v1.end(), Printid());
cout<<endl;
system("pause");
// 开始第一轮比赛
cout << "开始第一轮比赛!" << endl;
// 将前6个和后6个分别放入不同的vector容器
vector<Person> v2;
vector<Person> v3;
// 扩容
v2.resize(v1.size()/2);
v3.resize(v1.size()/2);
// 找到v1第六个迭代器
vector<Person>::iterator midId = v1.begin();
for (int i = 0; i < v1.size() / 2; i++) {
midId++;
}
// v1的前六个搬到v2中,v1的后六个搬到v3中去
transform(v1.begin(), midId, v2.begin(), Transfor());
transform(midId, v1.end(), v3.begin(), Transfor());
//cout << "v1" << endl;
//showPerson(v1);
//cout << "v2" << endl;
//showPerson(v2);
//cout << "v3" << endl;
//showPerson(v3);
// 调用评委打分函数
addScore(v2);
addScore(v3);
cout << "第一组成绩:" << endl;
sort(v2.begin(), v2.end(), Sortscore());
showPerson(v2);
cout << "第二组成绩:" << endl;
sort(v3.begin(), v3.end(), Sortscore());
showPerson(v3);
system("pause");
// 开始决赛
cout << "开始决赛!" << endl;
vector<Person> v4;
// 分别取出两组的前3个
vector<Person>::iterator it2 = v2.begin(), it3 = v3.begin();
for (int i=0; i < 3; it2++,it3++,i++) {
v4.push_back(*(it2));
v4.push_back(*(it3));
}
addScore(v4);
sort(v4.begin(), v4.end(), Sortscore());
cout << "决赛成绩:" << endl;
showPerson(v4);
// 将前三名存到csv文件中
saveCSV(v4,count);
}
3.10 主函数
int main() {
int choice;
int count = 1; // 第几届比赛
while (true)
{
showmanu();
cout << "请输入你的选项:";
cin >> choice;
switch (choice) {
case 1:
startSpeech(count);
break;
case 2:
showCSV();
break;
case 3:
delCSV();
break;
case 4:
return 0;
}
}
return 0;
}
四、完整代码
#include<iostream>
using namespace std;
#include<vector>
#include<deque>
#include<string>
#include<algorithm>
#include<numeric>
#include <iomanip>
#include <fstream>
// 选手类
class Person {
public:
Person() {};
Person(string id,float score) {
m_id = id;
m_score = score;
}
string m_id;
float m_score;
};
// 打印函数
class Myprint {
public:
void operator()(Person &p){
cout << "编号:" << p.m_id << " 平均分:" <<fixed << setprecision(2)<<p.m_score << endl;
}
};
// 显示选手信息
void showPerson(vector<Person> &v) {
for_each(v.begin(), v.end(), Myprint());
}
// 打印抽签顺序
class Printid {
public:
void operator()(Person& p) {
cout << p.m_id << " ";
}
};
// 显示选项菜单
void showmanu() {
cout << "———欢迎来到演讲比赛流程管理系统———" << endl;
cout << " 1.开始演讲比赛" << endl;
cout << " 2.查看往届记录" << endl;
cout << " 3.清空比赛记录" << endl;
cout << " 4.退出比赛系统" << endl;
}
// 搬运的仿函数
class Transfor {
public:
Person operator()(Person p) {
return p;
}
};
// 打分函数
void addScore(vector<Person> &v) {
// 将评委打分放入deque容器中
for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) {
// 创建评委打分
deque<int> dq;
for (int i = 0; i < 10; i++) {
int score = rand() % 41 + 60; // 60-100
dq.push_back(score);
}
// 去除最高分和最低分
sort(dq.begin(), dq.end());
dq.pop_back();
dq.pop_front();
// 计算平均分
float avracore = ((float)accumulate(dq.begin(), dq.end(), 0) / 8);
// 添加平均分
(*it).m_score = avracore;
}
}
class Sortscore {
public:
bool operator()(Person& p1, Person& p2) {
return p1.m_score > p2.m_score;
}
};
// 保存分数
void saveCSV(vector<Person>& v,int &count) {
ofstream ofs;
// 打开文件
ofs.open("speech.csv", ios::out | ios::app);
vector<Person>::iterator it = v.begin();
ofs << "第"<<count<<"届成绩: ";
for (int i = 0; i < 3; it++,i++) {
ofs <<"编号:" << "," << (*it).m_id << "," <<"分数:" << "," << (*it).m_score << ",";
}
count++;
ofs << endl;
ofs.close();
cout << "保存完毕!" << endl;
}
// 查看往届记录
void showCSV() {
ifstream ifs;
// 打开文件
ifs.open("speech.csv", ios::in);
char buf[1024] = { 0 };
while (ifs >> buf) {
cout << buf << endl;
}
}
// 清空往届记录
void delCSV() {
ofstream ofs;
// 打开文件
ofs.open("speech.csv", ios::trunc); // 先删除再创建
ofs.close();
cout << "删除完毕!" << endl;
}
// 开始比赛
void startSpeech(int &count) {
// 创建12个选手,全部放到vector容器中
vector<Person> v1;
for (int i = 0; i < 12; i++) {
// 创建编号
string name = to_string(10000 + i);
float score = 0.0;
Person p(name, score);
v1.push_back(p); // 添加
}
system("pause");
// 开始抽签
cout << "开始抽签!" << endl;
random_shuffle(v1.begin(), v1.end());
cout << "抽签顺序为:" << endl;
for_each(v1.begin(), v1.end(), Printid());
cout<<endl;
system("pause");
// 开始第一轮比赛
cout << "开始第一轮比赛!" << endl;
// 将前6个和后6个分别放入不同的vector容器
vector<Person> v2;
vector<Person> v3;
// 扩容
v2.resize(v1.size()/2);
v3.resize(v1.size()/2);
// 找到v1第六个迭代器
vector<Person>::iterator midId = v1.begin();
for (int i = 0; i < v1.size() / 2; i++) {
midId++;
}
// v1的前六个搬到v2中,v1的后六个搬到v3中去
transform(v1.begin(), midId, v2.begin(), Transfor());
transform(midId, v1.end(), v3.begin(), Transfor());
//cout << "v1" << endl;
//showPerson(v1);
//cout << "v2" << endl;
//showPerson(v2);
//cout << "v3" << endl;
//showPerson(v3);
// 调用评委打分函数
addScore(v2);
addScore(v3);
cout << "第一组成绩:" << endl;
sort(v2.begin(), v2.end(), Sortscore());
showPerson(v2);
cout << "第二组成绩:" << endl;
sort(v3.begin(), v3.end(), Sortscore());
showPerson(v3);
system("pause");
// 开始决赛
cout << "开始决赛!" << endl;
vector<Person> v4;
// 分别取出两组的前3个
vector<Person>::iterator it2 = v2.begin(), it3 = v3.begin();
for (int i=0; i < 3; it2++,it3++,i++) {
v4.push_back(*(it2));
v4.push_back(*(it3));
}
addScore(v4);
sort(v4.begin(), v4.end(), Sortscore());
cout << "决赛成绩:" << endl;
showPerson(v4);
// 将前三名存到csv文件中
saveCSV(v4,count);
}
int main() {
int choice;
int count = 1; // 第几届比赛
while (true)
{
showmanu();
cout << "请输入你的选项:";
cin >> choice;
switch (choice) {
case 1:
startSpeech(count);
break;
case 2:
showCSV();
break;
case 3:
delCSV();
break;
case 4:
return 0;
}
}
return 0;
}
五、测试案例
———欢迎来到演讲比赛流程管理系统———
1.开始演讲比赛
2.查看往届记录
3.清空比赛记录
4.退出比赛系统
请输入你的选项:1
请按任意键继续. . .
开始抽签!
抽签顺序为:
10010 10001 10009 10002 10000 10011 10007 10003 10004 10006 10008 10005
请按任意键继续. . .
开始第一轮比赛!
第一组成绩:
编号:10000 平均分:86.12
编号:10010 平均分:82.00
编号:10001 平均分:79.00
编号:10002 平均分:77.50
编号:10009 平均分:76.62
编号:10011 平均分:74.25
第二组成绩:
编号:10003 平均分:85.25
编号:10007 平均分:80.12
编号:10006 平均分:78.38
编号:10005 平均分:78.25
编号:10008 平均分:75.88
编号:10004 平均分:74.88
请按任意键继续. . .
开始决赛!
决赛成绩:
编号:10010 平均分:85.88
编号:10001 平均分:81.50
编号:10003 平均分:80.88
编号:10007 平均分:80.00
编号:10006 平均分:77.12
编号:10000 平均分:77.00
保存完毕!
———欢迎来到演讲比赛流程管理系统———
1.开始演讲比赛
2.查看往届记录
3.清空比赛记录
4.退出比赛系统
请输入你的选项:1
请按任意键继续. . .
开始抽签!
抽签顺序为:
10002 10007 10006 10005 10009 10003 10004 10008 10011 10010 10000 10001
请按任意键继续. . .
开始第一轮比赛!
第一组成绩:
编号:10006 平均分:90.25
编号:10007 平均分:84.62
编号:10002 平均分:80.50
编号:10003 平均分:75.88
编号:10005 平均分:75.50
编号:10009 平均分:71.62
第二组成绩:
编号:10004 平均分:84.00
编号:10011 平均分:82.50
编号:10000 平均分:82.38
编号:10010 平均分:79.00
编号:10008 平均分:76.62
编号:10001 平均分:74.62
请按任意键继续. . .
开始决赛!
决赛成绩:
编号:10006 平均分:86.62
编号:10000 平均分:85.00
编号:10002 平均分:83.62
编号:10011 平均分:83.00
编号:10007 平均分:80.75
编号:10004 平均分:76.50
保存完毕!
———欢迎来到演讲比赛流程管理系统———
1.开始演讲比赛
2.查看往届记录
3.清空比赛记录
4.退出比赛系统
请输入你的选项:2
第1届成绩:
编号:,10010,分数:,85.875,编号:,10001,分数:,81.5,编号:,10003,分数:,80.875,
第2届成绩:
编号:,10006,分数:,86.625,编号:,10000,分数:,85,编号:,10002,分数:,83.625,
———欢迎来到演讲比赛流程管理系统———
1.开始演讲比赛
2.查看往届记录
3.清空比赛记录
4.退出比赛系统
请输入你的选项:3
删除完毕!
———欢迎来到演讲比赛流程管理系统———
1.开始演讲比赛
2.查看往届记录
3.清空比赛记录
4.退出比赛系统
请输入你的选项:4