需求描述
- 学校举行一场演讲比赛,共有12个人参加。比赛共两轮,第一轮为淘汰赛,第二轮为决赛。
- 比赛方式:分组比赛,每组6个人;选手每次要随机分组,进行比赛
- 每名选手都有对应的编号,如 10001 ~ 10012
- 第一轮分为两个小组,每组6个人。 整体按照选手编号进行抽签后顺序演讲。
- 当小组演讲完后,淘汰组内排名最后的三个选手,前三名晋级,进入下一轮的比赛。
- 第二轮为决赛,前三名胜出
- 每轮比赛过后需要显示晋级选手的信息
功能实现
- 开始演讲比赛:完成整届比赛的流程,每个比赛阶段需要给用户一个提示,用户按任意键后继续下一个阶段
- 查看往届记录:查看之前比赛前三名结果,每次比赛都会记录到文件中,文件用.csv后缀名保存
- 清空比赛记录:将文件中数据清空
- 退出比赛程序:可以退出当前程序
知识点:面向对象思想、文件操作、STL
设计&&实现
在面向对象思想中,万物皆对象,要设计一个演讲比赛管理系统,最直接的是创建一个对象(类)管理比赛,这个对象包含主持比赛等一系列功能(方法)。在程序入口处(主函数)创建这个对象,然后在不同的时机使用这个对象不同的功能。
参赛队员类
在管理系统中,参赛队员也是一个对象,类的设计如下:
#include<iostream>
#include<string>
using namespace std;
class Speechers {
public:
string name;
double score[2];
};
比赛管理类
1 #include<iostream>
2 #include<vector>
3 #include<map>
4 #include<algorithm>
5 #include "speechers.h"
6 using namespace std;
7
8 class SpeechManager {
9 public:
10 SpeechManager(){
11 this->init_speechers();
12 this->create_speechers();
13 this->load_record();
14 };
15
16 ~SpeechManager(){};
17
18 void show_menu();
19 void exit_system();
20 void init_speechers(); //初始化比赛相关属性
21 void create_speechers();
22
23 // 比赛流程控制
24 void process_game();
25 // 抽签
26 void draw();
27 // 开始比赛
28 void start_game();
29 // 显示成绩
30 void show_score();
31 // 保存比赛记录
32 void save();
33 // 读取记录
34 void load_record();
35 // 展示往届记录
36 void show_record();
37 // 清空记录
38 void clear_record();
39 public:
40 // game attributes
41 int m_index;
42 vector<int> v1; // 选手编号
43 vector<int> v2; // 第一轮晋级
44 vector<int> v3; // 胜者
45 bool is_empty;
46 map<int, Speechers> m_speechers;
47 map<int, vector<string> > m_record;
48 };
实现类如下:
在这个设计类中包含一些开发小思维,比如随机数和随机种子使用,使用如何使用容器保存获胜者信息(主要逻辑在这里),文件的使用,其他的都是一些简单的操作,没啥思维性。
// show menu
void SpeechManager::show_menu() {
cout << "********************************************" << endl;
cout << "************* 欢迎参加演讲比赛 ************" << endl;
cout << "************* 1.开始演讲比赛 *************" << endl;
cout << "************* 2.查看往届记录 *************" << endl;
cout << "************* 3.清空比赛记录 *************" << endl;
cout << "************* 0.退出比赛程序 *************" << endl;
cout << "********************************************" << endl;
// cout << endl;
}
//exit
void SpeechManager::exit_system() {
cout << "欢迎下次使用" << endl;
system("read");
exit(0);
}
// init attributes
void SpeechManager::init_speechers() {
this->v1.clear();
this->v2.clear();
this->v3.clear();
this->v3.clear();
this->m_speechers.clear();
this->m_index = 1;
this->m_record.clear();
}
//create speechers
void SpeechManager::create_speechers() {
// 随机命名
string name_seed = "ABCDEFGHIJKL";
for (int i = 0; i < name_seed.size(); i++) {
string name = "选手";
name += name_seed[i];
Speechers sp;
sp.name = name;
for (int j = 0; j < 2; j++) {
sp.score[j] = 0;
}
// 选手编号
this->v1.push_back(i+10001);
// 选手编号、选手放到容器中
this->m_speechers.insert(make_pair(i+10001,sp));
}
}
// process game
void SpeechManager::process_game() {
// 第一轮比赛
// 1.抽签
this->draw();
// 2.比赛
this->start_game();
// 3.显示晋级结果
this->show_score();
// 第二轮比赛
this->m_index++;
// 1.抽签
this->draw();
// 2.比赛
this->start_game();
// 3.显示晋级结果
this->show_score();
// 保存分数
this->save();
// 重置比赛
this->init_speechers();
this->create_speechers();
this->load_record();
cout << "本届比赛结束!" << endl;
system("read");
system("clear");
cout << endl;
}
// draw
void SpeechManager::draw() {
cout << "第 << " << this->m_index << " >> 轮比赛选手正在抽签"<< endl;
cout << "---------------------" << endl;
cout << "抽签后演讲顺序如下:" << endl;
if (this->m_index == 1) {
random_shuffle(v1.begin(), v1.end());
for (vector<int>::iterator it = v1.begin(); it != v1.end(); ++it) {
cout << *it << " " << endl;
}
cout << endl;
} else {
random_shuffle(v2.begin(), v2.end());
for (vector<int>::iterator it = v2.begin(); it != v2.end(); ++it) {
cout << *it << " " << endl;
}
cout << endl;
}
cout << "---------------------" << endl;
system("read");
cout << endl;
}
// start game
void SpeechManager::start_game() {
cout << "------------- 第"<< this->m_index << "轮正式比赛开始:------------- " << endl;
multimap<double, int, greater<double> > groupScore; // 临时容器,保存分数、人员编号
int num = 0;
// 比赛人员
vector<int> competitors;
if (this->m_index == 1) {
competitors = v1;
} else {
competitors = v2;
}
// traverse competitors and give grade
for (vector<int>::iterator it = competitors.begin(); it != competitors.end(); ++it) {
num++;
deque<double> que; // save grade
for (int i = 0; i < 10; i++) {
double grade = (rand() % 401 + 600) / 10.f; // 随机生成60-100之间的分数
que.push_back(grade);
}
sort(que.begin(),que.end(),greater<double>());
que.pop_front();
que.pop_back();
double sum = accumulate(que.begin(), que.end(), 0.0f);
double avg = sum / (double)que.size();
// cout << "编号: " << *it << " 选手: " << this->m_speechers[*it].name << " 获取平均分为: " << avg << endl; //打印分数
this->m_speechers[*it].score[this->m_index-1] = avg;
// 6人一组,容器保存
groupScore.insert(make_pair(avg, *it));
if (num % 6 == 0) {
cout << "第" << num / 6 << "小组比赛名次:" << endl;
for (multimap<double, int, greater<double> >::iterator it = groupScore.begin(); it != groupScore.end(); it++) {
cout << "编号: " << it->second << " 姓名: " << this->m_speechers[it->second].name << " 成绩: " << this->m_speechers[it->second].score[this->m_index - 1] << endl;
}
int count = 0;
// 取前三名
for (multimap<double, int, greater<double> >::iterator it = groupScore.begin(); it != groupScore.end() && count < 3; ++it) {
if (this->m_index == 1) {
v2.push_back((*it).second);
} else {
v3.push_back((*it).second);
}
}
groupScore.clear();
}
}
cout << "------------- 第" << this->m_index << "轮比赛完毕 ------------- " << endl;
system("read");
}
// show score
void SpeechManager::show_score() {
cout << "---------第" << this->m_index << "轮晋级选手信息如下:-----------" << endl;
vector<int> up;
if (this->m_index == 1)
{
up = v2;
}
else
{
up = v3;
}
for (vector<int>::iterator it = up.begin(); it != up.end(); it++)
{
cout << "选手编号:" << *it << " 姓名: " << m_speechers[*it].name << " 得分: " << m_speechers[*it].score[this->m_index - 1] << endl;
}
cout << endl;
system("read");
system("clear");
this->show_menu();
}
// save to file
void SpeechManager::save() {
ofstream ofs;
ofs.open("speech.csv", ios::out | ios::app);
for (vector<int>::iterator it = v3.begin(); it != v3.end(); it++) {
ofs << *it << ":" << m_speechers[*it].score[1] << ",";
}
ofs << endl;
//关闭文件
ofs.close();
cout << "记录已经保存" << endl;
this->is_empty = true;
}
// file is empty
void SpeechManager::load_record() {
ifstream ifs("speech.csv", ios::in);
if(!ifs.is_open()) {
this->is_empty = true;
cout << "文件不存在!" << endl;
ifs.close();
return;
}
char ch;
ifs >> ch;
if (ifs.eof()) {
this->is_empty = true;
cout << "文件为空!" << endl;
ifs.close();
return;
}
//文件不为空
this->is_empty = false;
ifs.putback(ch); //读取的单个字符放回去
string data;
int index = 0;
while(ifs>>data) {
vector<string> v;
int start = 0;
int pos = -1;
while (true) {
pos = data.find(",", start);
if (-1 == pos) {
break;
}
string tmp = data.substr(start, pos-start);
v.push_back(tmp);
start = pos + 1;
}
this->m_record.insert(make_pair(index,v));
index++;
}
ifs.close();
}
// show record
void SpeechManager::show_record() {
if(this->is_empty) {
cout << "文件不存在或记录为空" << endl;
return;
}
for (int i = 0; i < this->m_record.size(); i++) {
cout << "第" << i + 1 << "届 " <<
"冠军编号:" << this->m_record[i][0] << " 得分:" << this->m_record[i][1] << " "
"亚军编号:" << this->m_record[i][2] << " 得分:" << this->m_record[i][3] << " "
"季军编号:" << this->m_record[i][4] << " 得分:" << this->m_record[i][5] << endl;
}
system("read");
system("clear");
}
// clear record
void SpeechManager::clear_record() {
cout << "确认清空?" << endl;
cout << "1、确认" << endl;
cout << "2、返回" << endl;
int select = 0;
cin >> select;
if (select == 1) {
//打开模式 ios::trunc 如果存在删除文件并重新创建
ofstream ofs("speech.csv", ios::trunc);
ofs.close();
//初始化属性
this->init_speechers();
//创建选手
this->create_speechers();
//获取往届记录
this->load_record();
cout << "清空成功!" << endl;
} else {
this->show_menu();
}
system("read");
system("clear");
}
code
tar格式,包含可执行文件a.out。(5积分,没有积分的话评论留下邮箱)
界面展示
主目录:
比赛流程:
查看往届记录