一、项目要求

  • 学校举办一场演讲比赛,共有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.退出比赛系统
请输入你的选项:21届成绩:
编号:,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
01-28 00:15