赞
踩
演讲比赛流程管理系统
比赛规则:演讲比赛共有12个人参加,比赛分两轮进行,第一轮为淘汰赛,第二轮为决赛。每名选手都有对应的编号,如10001~10012,可以根据届数的不同修改选手编号,第一轮分为两个小组,每组6个人,整体按照选手编号进行抽签后顺序演讲。十个评委分别给每名选手打分,去除最高分和最低分,平均分作为本轮选手的成绩。第一轮过后,分别淘汰两组内排名后三名的选手,每组前三名晋级。第二轮为决赛,前三名胜出,每轮比赛过后需要显示晋级选手的信息。
程序功能:
开始演讲比赛:完成整届比赛的流程,每个比赛阶段需要给用户一个提示,用户按任意键后继续下一个阶段;
查看往届记录:查看之前比赛前三名结果,每次比赛都会记录到文件中,文件用.csv后缀名保存;
清空比赛记录:将文件中数据清空;
退出比赛程序:用户输入某一选择后退出程序。
创建管理类头文件和cpp文件,在头文件中创建一个类,后续相关的成员函数在类中进行声明,具体的实现在cpp文件中。
菜单显示功能的实现步骤:先在头文件speechManager.h中声明显示菜单的函数,然后在speechManager.cpp中实现该函数,再到main.cpp中通过实例化对象调用该函数接口。之后的功能基本上都是按照这个步骤进行的。
头文件speechManager.h中声明显示菜单函数的代码如下。
#pragma once
#include <iostream>
using namespace std;
class speechManager
{
public:
speechManager(); //构造函数
void show_menu(); //显示菜单
~speechManager(); //析构函数
};
在speechManager.cpp中实现显示菜单的代码如下。
void speechManager::show_menu() //显示菜单
{
cout<<"****************************************"<<endl;
cout<<"**********演讲比赛流程管理系统**********"<<endl;
cout<<"********** 0.退出比赛程序 **********"<<endl;
cout<<"********** 1.开始演讲比赛 **********"<<endl;
cout<<"********** 2.查看往届记录 **********"<<endl;
cout<<"********** 3.清空比赛记录 **********"<<endl;
cout<<"****************************************"<<endl;
cout<<endl;
}
main.cpp中通过实例化对象调用该函数接口的代码如下。
speechManager sp;
sp.show_menu(); //显示菜单
运行程序后的结果如下图所示。
speechManager.cpp中实现退出管理系统的代码如下。
void speechManager::exit_system() //退出系统
{
cout<<"欢迎下次使用!"<<endl;
system("pause");
exit(0);
}
main.cpp中通过switch-case分支对用户的输入进行不同的处理,到此为止的代码框架如下。
int user_choice; speechManager sp; while(1) { sp.show_menu(); //显示菜单 cout<<"请输入您的选择: "; cin>>user_choice; switch(user_choice) { case 0: sp.exit_system(); //退出系统 break; case 1: break; case 2: break; case 3: break; default: system("cls"); //清屏 break; } }
运行程序之后输入0,按回车后显示如下,再按任意键就会退出该程序。
本案例中内容最多的就是演讲比赛功能,在管理类中添加下面各项属性。
vector<int> v1; //第一轮比赛12人
vector<int> v2; //第二轮比赛6人
vector<int> v; //获胜者3人
map<int,Person> m; //存放选手和编号的容器
int round; //比赛轮数
bool fileIsEmpty; //判断文件是否为空
map<int,vector<string>> m_record; //读取文件记录
int session; //记录比赛届数
在speechManager.h中创建选手类如下。
class Person
{
public:
string name; //选手姓名
double score[2]; //记录平均分,有两轮
};
在构造函数中初始化各项参数、创建比赛选手、然后从文件中加载往届的记录信息,构造函数的内容如下。
speechManager::speechManager() //构造函数
{
init_index(); //初始化各项参数
read_from_file(); //加载往届记录信息,读取到session供create_person()使用
create_person(); //创建选手
}
构造函数中调用的各函数如下。
void speechManager::init_index() //初始化 { this->v1.clear(); //清空各容器 this->v2.clear(); this->v.clear(); this->m.clear(); this->round = 1; //第一轮 this->m_record.clear(); } void speechManager::read_from_file() //从文件读取信息 { ifstream ifs("speech.cvs",ios::in); if(!ifs.is_open()) { fileIsEmpty = true; //cout<<"文件不存在!"<<endl; session = 0; //第0届 ifs.close(); return; } char ch; ifs>>ch; //先读一个字符 if(ifs.eof()) //文件被清空的情况 { //cout<<"文件为空!"<<endl; fileIsEmpty = true; session = 0; //第0届 ifs.close(); return; } fileIsEmpty = false; //以上两个if都不满足,说明文件有内容 ifs.putback(ch); //将上面读取的单个字符放回文件中 string data; int line = 0; //记录行数,每一行就是一届的信息 while(ifs>>data) //逐行读取到data中 { vector<string> vs; //存放拆分后的字符串 int pos = -1; int start = 0; while(1) //拆分字符串 { pos = data.find(",",start); //从start位置开始找第一个, if(pos == -1) { break; //没找到 } string temp = data.substr(start,pos-start); //截取子串 start = pos + 1; //移动下一次开始找的位置 vs.push_back(temp); //将拆分得到的字符串存入容器中 } this->m_record.insert(make_pair(line,vs)); //将届数和记录存入map容器中 line++; session = line; //记录届数 //cout<<line<<" data: "<<data<<endl; } ifs.close(); } void speechManager::create_person() //创建选手 { session++; //届数 string nameSeed = "ABCDEFGHIJKL"; for(int i=0;i<nameSeed.size();i++) { string name = "选手"; name += nameSeed[i]; Person p; p.name = name; //姓名 p.score[0] = 0; //分数都初始化为0 p.score[1] = 0; v1.push_back(session*10000+1+i); //根据届数给选手编号,并插入到vector容器中 m.insert(make_pair<int,Person>(session*10000+1+i,p)); //插入到map容器中 } }
正式开始演讲比赛后,分两轮进行,每轮比赛需要进行抽签决定顺序,存放评委打分,显示本轮晋级结果,并在第二轮结束后将本届比赛获胜的三位选手信息写入文件中。
void speechManager::start_speech() //开始比赛,控制整个流程 { //第一轮比赛 speech_draw(); //1.抽签确定比赛顺序 speech_contest(); //2.开始比赛并打分 show_score(); //3.显示晋级结果 //第二轮比赛 this->round++; speech_draw(); //1.抽签确定比赛顺序 speech_contest(); //2.开始比赛并打分 show_score(); //3.显示最终获胜结果 save_to_file(); //4.保存分数到文件中 cout<<"本次比赛结束!"<<endl; init_index(); //初始化各项参数 read_from_file(); //加载往届记录信息 create_person(); //创建选手 system("pause"); system("cls"); }
演讲比赛过程中用到的各个函数如下。
void speechManager::speech_draw() //抽签 { cout<<"-----------------------"<<endl; cout<<"第"<<this->round<<"轮比赛选手正在抽签..."<<endl; cout<<"-----------------------"<<endl; cout<<"抽签后的演讲顺序如下: "<<endl; if(this->round == 1) //第一轮抽签 { random_shuffle(v1.begin(),v1.end()); //洗牌,打乱v1容器中的编号顺序 for(vector<int>::iterator i=v1.begin();i!=v1.end();i++) { cout<<*i<<" "; } cout<<endl; } else //第二轮抽签 { random_shuffle(v2.begin(),v2.end()); //洗牌,打乱v2容器中的编号顺序 for(vector<int>::iterator i=v2.begin();i!=v2.end();i++) { cout<<*i<<" "; } cout<<endl; } cout<<endl; system("pause"); cout<<endl; } void speechManager::speech_contest() //开始比赛并打分 { cout<<"------------ 第"<<this->round<<"轮比赛开始 ------------"<<endl; multimap<double,int,greater<double>> group; //防止同分情况定义为multimap容器,降序排列6个人的成绩和编号 //这里把得分放在编号前面是为了降序排列得分,map容器是按照第一个位置的参数排序的 int num = 0; //记录小组内成员个数,6人一组 vector<int> vtemp; //创建一个临时容器,根据当前比赛轮数进行拷贝操作 if(this->round == 1) { vtemp = v1; //第一轮 } else { vtemp = v2; //第二轮 } for(vector<int>::iterator i=vtemp.begin();i!=vtemp.end();i++) { num++; deque<double> d; //存取评委打分,deque容器排序后容易去掉开头末尾两数 for(int j=0;j<10;j++) { double score = (rand()%401+600)/10.f; //60.0-100.0 d.push_back(score); } sort(d.begin(),d.end(),greater<double>()); //降序排列 d.pop_front(); //去除最高分 d.pop_back(); //去除最低分 double aver = accumulate(d.begin(),d.end(),0.0f) / (double) d.size(); //累加总分并求平均分 this->m[*i].score[round-1] = aver; //将平均分存放在map容器中 //cout<<"编号: "<<*i<<" 姓名: "<<m[*i].name<<" 平均分: "<<m[*i].score[round-1]<<endl; group.insert(make_pair<double,int>(aver,*i)); //插入临时容器中,key是得分,value是选手编号 if(num % 6 == 0) //num = 6 或 num = 12 时进入 { cout<<"********** 第"<<num/6<<"小组的排名如下 **********"<<endl; int count = 0; for(multimap<double,int,greater<double>>::iterator i=group.begin();i!=group.end();i++) { cout<<"编号: "<<i->second<<" 姓名: "<<m[i->second].name<<" 平均分: "<<m[i->second].score[round-1]<<endl; if(count < 3) //取前三名 { if(this->round == 1) { v2.push_back(i->second); //晋级第二轮的选手 } else { v.push_back(i->second); //最终获胜的选手 } count++; } } group.clear(); //每6人就清空一次容器 } } cout<<"------------ 第"<<this->round<<"轮比赛结束 ------------"<<endl; cout<<endl; system("pause"); cout<<endl; } void speechManager::show_score() //显示晋级结果 { cout<<"-------- 第"<<this->round<<"轮晋级选手信息如下 --------"<<endl; vector<int> vtemp; //创建一个临时容器,根据当前比赛轮数进行拷贝操作 if(this->round == 1) { vtemp = v2; } else { vtemp = v; } for(vector<int>::iterator i=vtemp.begin();i!=vtemp.end();i++) { cout<<"编号: "<<*i<<" 姓名: "<<m[*i].name<<" 平均分: "<<m[*i].score[round-1]<<endl; } cout<<"---------------------------------------"<<endl; cout<<endl; system("pause"); system("cls"); show_menu(); } void speechManager::save_to_file() //将晋级信息保存到文件 { ofstream ofs; ofs.open("speech.cvs",ios::out | ios::app); //用追加的方式往文件中写数据 for(vector<int>::iterator i=v.begin();i!=v.end();i++) { ofs<<*i<<","<<m[*i].score[1]<<","; } ofs<<endl; ofs.close(); cout<<"数据已保存!"<<endl; fileIsEmpty = false; //插入数据后文件已经不为空 }
抽签过程如下图所示。
第一轮比赛结束后,每个小组按照得分从高到低排列,每个小组取前三名晋级下一轮,如下图所示。
第二轮抽签、赛果及晋级信息如下图所示。
本次比赛结束后将获胜三人的信息存入文件中,方便后续访问。
read_from_file()函数中已经将文件中保存的记录读取到了map容器中,现在查看往届记录只需要从map容器中读取信息即可。
查看往届记录的函数体如下。
void speechManager::show_record() //显示往届记录 { if(fileIsEmpty) { cout<<"文件为空或不存在!"<<endl; } else { for(int i=0;i<m_record.size();i++) { cout<<"第"<<i+1<<"届---冠军编号:"<<m_record[i][0]<<" 分数:"<<m_record[i][1] <<" 亚军编号:"<<m_record[i][2]<<" 分数:"<<m_record[i][3] <<" 季军编号:"<<m_record[i][4]<<" 分数:"<<m_record[i][5]<<endl; } /*for(map<int,vector<string>>::iterator i=m_record.begin();i!=m_record.end();i++) { cout<<"第"<<i->first+1<<"届---冠军编号:"<<i->second[0]<<" 分数:"<<i->second[1] <<" 亚军编号:"<<i->second[2]<<" 分数:"<<i->second[3] <<" 季军编号:"<<i->second[4]<<" 分数:"<<i->second[5]<<endl; }*/ } system("pause"); system("cls"); }
读取往届记录信息的截图如下图所示。
往届记录在项目工程文件夹下的speech.cvs文件中存放的信息如下。
清空比赛记录前让用户再确认一次,确认无误后将存取记录的文件删空,这样以往的比赛记录就不存在了,同时还要执行构造函数中执行的几个函数进行初始化操作。
清空比赛记录的函数体如下。
void speechManager::clear_record() //清空往届记录 { if(fileIsEmpty) { cout<<"文件为空!"<<endl; } else { cout<<"确定清空文件?"<<endl; cout<<"输入 1---确定"<<endl; cout<<"其他键---取消"<<endl; int input = 0; cin>>input; if(input == 1) { ofstream ofs("speech.cvs",ios::trunc); //删除文件并重新创建同名文件 ofs.close(); init_index(); //初始化各项参数 session = 0; //第0届 create_person(); //创建选手 read_from_file(); //加载往届记录信息 cout<<"清空往届比赛记录成功!"<<endl; } } system("pause"); system("cls"); }
清空比赛记录的操作截图如下图所示。
再次查看往届记录,提示文件为空或不存在,打开文件,里面的内容也被清空了,如下图所示。
speechManager.h文件的代码如下。
#pragma once #include <iostream> #include <vector> #include <map> #include <string> #include <algorithm> #include <functional> #include <numeric> #include <deque> #include <fstream> using namespace std; class Person { public: string name; //选手姓名 double score[2]; //记录平均分,有两轮 }; class speechManager { public: speechManager(); //构造函数 void show_menu(); //显示菜单 void exit_system(); //退出系统 void init_index(); //初始化 void create_person(); //创建选手 void start_speech(); //开始比赛,控制整个流程 void speech_draw(); //抽签 void speech_contest(); //开始比赛并打分 void show_score(); //显示晋级结果 void save_to_file(); //将晋级信息保存到文件 void read_from_file(); //从文件读取信息 void show_record(); //显示往届记录 void clear_record(); //清空往届记录 ~speechManager(); //析构函数 vector<int> v1; //第一轮比赛12人 vector<int> v2; //第二轮比赛6人 vector<int> v; //获胜者3人 map<int,Person> m; //存放选手和编号的容器 int round; //比赛轮数 bool fileIsEmpty; //判断文件是否为空 map<int,vector<string>> m_record; //读取文件记录 int session; //记录比赛届数 };
speechManager.cpp文件的代码如下。
#include "speechManager.h" speechManager::speechManager() //构造函数 { init_index(); //初始化各项参数 read_from_file(); //加载往届记录信息,读取到session供create_person()使用 create_person(); //创建选手 } void speechManager::show_menu() //显示菜单 { cout<<"****************************************"<<endl; cout<<"**********演讲比赛流程管理系统**********"<<endl; cout<<"********** 0.退出比赛程序 **********"<<endl; cout<<"********** 1.开始演讲比赛 **********"<<endl; cout<<"********** 2.查看往届记录 **********"<<endl; cout<<"********** 3.清空比赛记录 **********"<<endl; cout<<"****************************************"<<endl; cout<<endl; } void speechManager::exit_system() //退出系统 { cout<<"欢迎下次使用!"<<endl; system("pause"); exit(0); } void speechManager::init_index() //初始化 { this->v1.clear(); //清空各容器 this->v2.clear(); this->v.clear(); this->m.clear(); this->round = 1; //第一轮 this->m_record.clear(); } void speechManager::create_person() //创建选手 { session++; //届数 string nameSeed = "ABCDEFGHIJKL"; for(int i=0;i<nameSeed.size();i++) { string name = "选手"; name += nameSeed[i]; Person p; p.name = name; //姓名 p.score[0] = 0; //分数都初始化为0 p.score[1] = 0; v1.push_back(session*10000+1+i); //根据届数给选手编号,并插入到vector容器中 m.insert(make_pair<int,Person>(session*10000+1+i,p)); //插入到map容器中 } } void speechManager::speech_draw() //抽签 { cout<<"-----------------------"<<endl; cout<<"第"<<this->round<<"轮比赛选手正在抽签..."<<endl; cout<<"-----------------------"<<endl; cout<<"抽签后的演讲顺序如下: "<<endl; if(this->round == 1) //第一轮抽签 { random_shuffle(v1.begin(),v1.end()); //洗牌,打乱v1容器中的编号顺序 for(vector<int>::iterator i=v1.begin();i!=v1.end();i++) { cout<<*i<<" "; } cout<<endl; } else //第二轮抽签 { random_shuffle(v2.begin(),v2.end()); //洗牌,打乱v2容器中的编号顺序 for(vector<int>::iterator i=v2.begin();i!=v2.end();i++) { cout<<*i<<" "; } cout<<endl; } cout<<endl; system("pause"); cout<<endl; } void speechManager::speech_contest() //开始比赛并打分 { cout<<"------------ 第"<<this->round<<"轮比赛开始 ------------"<<endl; multimap<double,int,greater<double>> group; //防止同分情况定义为multimap容器,降序排列6个人的成绩和编号 //这里把得分放在编号前面是为了降序排列得分,map容器是按照第一个位置的参数排序的 int num = 0; //记录小组内成员个数,6人一组 vector<int> vtemp; //创建一个临时容器,根据当前比赛轮数进行拷贝操作 if(this->round == 1) { vtemp = v1; //第一轮 } else { vtemp = v2; //第二轮 } for(vector<int>::iterator i=vtemp.begin();i!=vtemp.end();i++) { num++; deque<double> d; //存取评委打分,deque容器排序后容易去掉开头末尾两数 for(int j=0;j<10;j++) { double score = (rand()%401+600)/10.f; //60.0-100.0 d.push_back(score); } sort(d.begin(),d.end(),greater<double>()); //降序排列 d.pop_front(); //去除最高分 d.pop_back(); //去除最低分 double aver = accumulate(d.begin(),d.end(),0.0f) / (double) d.size(); //累加总分并求平均分 this->m[*i].score[round-1] = aver; //将平均分存放在map容器中 //cout<<"编号: "<<*i<<" 姓名: "<<m[*i].name<<" 平均分: "<<m[*i].score[round-1]<<endl; group.insert(make_pair<double,int>(aver,*i)); //插入临时容器中,key是得分,value是选手编号 if(num % 6 == 0) //num = 6 或 num = 12 时进入 { cout<<"********** 第"<<num/6<<"小组的排名如下 **********"<<endl; int count = 0; for(multimap<double,int,greater<double>>::iterator i=group.begin();i!=group.end();i++) { cout<<"编号: "<<i->second<<" 姓名: "<<m[i->second].name<<" 平均分: "<<m[i->second].score[round-1]<<endl; if(count < 3) //取前三名 { if(this->round == 1) { v2.push_back(i->second); //晋级第二轮的选手 } else { v.push_back(i->second); //最终获胜的选手 } count++; } } group.clear(); //每6人就清空一次容器 } } cout<<"------------ 第"<<this->round<<"轮比赛结束 ------------"<<endl; cout<<endl; system("pause"); cout<<endl; } void speechManager::show_score() //显示晋级结果 { cout<<"-------- 第"<<this->round<<"轮晋级选手信息如下 --------"<<endl; vector<int> vtemp; //创建一个临时容器,根据当前比赛轮数进行拷贝操作 if(this->round == 1) { vtemp = v2; } else { vtemp = v; } for(vector<int>::iterator i=vtemp.begin();i!=vtemp.end();i++) { cout<<"编号: "<<*i<<" 姓名: "<<m[*i].name<<" 平均分: "<<m[*i].score[round-1]<<endl; } cout<<"---------------------------------------"<<endl; cout<<endl; system("pause"); system("cls"); show_menu(); } void speechManager::save_to_file() //将晋级信息保存到文件 { ofstream ofs; ofs.open("speech.cvs",ios::out | ios::app); //用追加的方式往文件中写数据 for(vector<int>::iterator i=v.begin();i!=v.end();i++) { ofs<<*i<<","<<m[*i].score[1]<<","; } ofs<<endl; ofs.close(); cout<<"数据已保存!"<<endl; fileIsEmpty = false; //插入数据后文件已经不为空 } void speechManager::start_speech() //开始比赛,控制整个流程 { //第一轮比赛 speech_draw(); //1.抽签确定比赛顺序 speech_contest(); //2.开始比赛并打分 show_score(); //3.显示晋级结果 //第二轮比赛 this->round++; speech_draw(); //1.抽签确定比赛顺序 speech_contest(); //2.开始比赛并打分 show_score(); //3.显示最终获胜结果 save_to_file(); //4.保存分数到文件中 cout<<"本次比赛结束!"<<endl; init_index(); //初始化各项参数 read_from_file(); //加载往届记录信息 create_person(); //创建选手 system("pause"); system("cls"); } void speechManager::read_from_file() //从文件读取信息 { ifstream ifs("speech.cvs",ios::in); if(!ifs.is_open()) { fileIsEmpty = true; //cout<<"文件不存在!"<<endl; session = 0; //第0届 ifs.close(); return; } char ch; ifs>>ch; //先读一个字符 if(ifs.eof()) //文件被清空的情况 { //cout<<"文件为空!"<<endl; fileIsEmpty = true; session = 0; //第0届 ifs.close(); return; } fileIsEmpty = false; //以上两个if都不满足,说明文件有内容 ifs.putback(ch); //将上面读取的单个字符放回文件中 string data; int line = 0; //记录行数,每一行就是一届的信息 while(ifs>>data) //逐行读取到data中 { vector<string> vs; //存放拆分后的字符串 int pos = -1; int start = 0; while(1) //拆分字符串 { pos = data.find(",",start); //从start位置开始找第一个, if(pos == -1) { break; //没找到 } string temp = data.substr(start,pos-start); //截取子串 start = pos + 1; //移动下一次开始找的位置 vs.push_back(temp); //将拆分得到的字符串存入容器中 } this->m_record.insert(make_pair(line,vs)); //将届数和记录存入map容器中 line++; session = line; //记录届数 //cout<<line<<" data: "<<data<<endl; } ifs.close(); } void speechManager::show_record() //显示往届记录 { if(fileIsEmpty) { cout<<"文件为空或不存在!"<<endl; } else { //for(int i=0;i<m_record.size();i++) //{ // cout<<"第"<<i+1<<"届---冠军编号:"<<m_record[i][0]<<" 分数:"<<m_record[i][1] // <<" 亚军编号:"<<m_record[i][2]<<" 分数:"<<m_record[i][3] // <<" 季军编号:"<<m_record[i][4]<<" 分数:"<<m_record[i][5]<<endl; //} for(map<int,vector<string>>::iterator i=m_record.begin();i!=m_record.end();i++) { cout<<"第"<<i->first+1<<"届---冠军编号:"<<i->second[0]<<" 分数:"<<i->second[1] <<" 亚军编号:"<<i->second[2]<<" 分数:"<<i->second[3] <<" 季军编号:"<<i->second[4]<<" 分数:"<<i->second[5]<<endl; } } system("pause"); system("cls"); } void speechManager::clear_record() //清空往届记录 { if(fileIsEmpty) { cout<<"文件为空!"<<endl; } else { cout<<"确定清空文件?"<<endl; cout<<"输入 1---确定"<<endl; cout<<"其他键---取消"<<endl; int input = 0; cin>>input; if(input == 1) { ofstream ofs("speech.cvs",ios::trunc); //删除文件并重新创建同名文件 ofs.close(); init_index(); //初始化各项参数 session = 0; //第0届 create_person(); //创建选手 read_from_file(); //加载往届记录信息 cout<<"清空往届比赛记录成功!"<<endl; } } system("pause"); system("cls"); } speechManager::~speechManager() //析构函数 { }
main.cpp文件的代码如下。
#include <ctime> #include "speechManager.h" using namespace std; int main() { srand((unsigned int)time(NULL)); //随机数种子 int user_choice; //用户选择 speechManager sp; //实例化对象 while(1) { sp.show_menu(); //显示菜单 cout<<"请输入您的选择: "; cin>>user_choice; switch(user_choice) { case 0: sp.exit_system(); //退出系统 break; case 1: sp.start_speech(); //开始演讲比赛 break; case 2: sp.show_record(); //查看往届记录 break; case 3: sp.clear_record(); //清空比赛记录 break; default: system("cls"); //清屏 break; } } system("pause"); return 0; }
本文参考视频:
黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。