本文主要以演讲比赛为例介绍STL综合性的案例。
目录如下,全文较长,建议收藏阅读。
一、比赛介绍与需求分析
1、比赛介绍
- 比赛方式:分组比赛,每组6个人;选手每次要随机分组,进行比赛;
第一轮:分为4个小组,每组6个人。比如100-105为一组,106-111为第二组,依次类推, 每人分别按照抽签(draw)顺序演讲。当小组演讲完后,淘汰组内排名最后的三个选手,然后继续下一个小组的比赛。
第二轮:分为2个小组,每组6人。比赛完毕,淘汰组内排名最后的三个选手,然后继续下一个小组的比赛。
第三轮:只剩下6个人,本轮为决赛,选出前三名。
评分标准:10个评委打分,去除最低、最高分,求平均分每个选手演讲完由10个评委分别打分。该选手的最终得分是去掉一个最高分和一个最低分,求得剩下的8个成绩的平均分。选手的名次按得分降序排列,若得分一样,按参赛号升序排名。
2、需求分析
- 产生选手(A~X),姓名,得分,选手编号。
- 第一轮比赛:选手抽签,选手比赛,查看比赛结果
- 第二轮比赛,选手抽签,选手比赛,查看比赛结果
- 第三轮比赛,选手抽签,选手比赛,查看比赛结果
二、实现思路分析
1、信息存储
本案例需要在容器中存放 选手信息、选手得分信息、比赛抽签信息、选手的晋级信息等,涉及到各个容器的类型。
class Speaker;
:选手类Speaker(姓名和得分)
map<int, Speaker> m_Speaker
:该容器存放所有选手编号和选手姓名
vector<int> v1
:所有选手的编号信息
vector<int> v2
:第1轮晋级名单
vector<int> v3
:第2轮晋级名单
vector<int> v4
:第3轮前三名名单
multimap<int, int, greater<int> > group_Map
:每个小组的比赛得分信息,是一个临时容器,用来存储每组6个人的排名(从大到小) key:分数 value:编号
目的:方便去除最低最高分
2、函数
//创建选手
void CreatSpeaker(vector<int> &v, map<int, Speaker>& m_Speaker){}
//抽签
void speech_contest_draw(vector<int> &v){}
//比赛
voidspeech_contest(int index,vector<int> &v1,map<int, Speaker> &m_Speaker,vector<int> &v2){}
//显示比赛结果
speech__contest_Show(int index,vector<int>& v,map<int,Speaker>& m_Speaker){}//参数1:第几轮 参数2:晋级编号 参数3:具体人员信息
三、案例框架搭建
class Speaker //选手类
{
public:
string m_Name;//姓名
int m_Score[3];//得分数组
};
//创建选手
void CreatSpeaker(vector<int> &v, map<int, Speaker>& m_Speaker)
{
}
//抽签
void speech_contest_draw(vector<int> &v)
{
}
//比赛
void speech_contest(map<int, Speaker> &mSpeaker, vector<int> &v1, vector<int> &v2)
{
}
//比赛结果
speech__contest_Show(int index,vector<int>& v,map<int,Speaker>& m_Speaker)
{
}
void main()
{
//随机数种子
srand((unsigned int)time(NULL));
map<int, Speaker> m_Speaker;//所有选手编号和选手信息
vector<int> v1; //所有选手的编号信息
vector<int> v2; //第1轮晋级名单
vector<int> v3; //第2轮晋级名单
vector<int> v4; //第3轮前三名名单
//创建选手
CreatSpeaker(v1, m_Speaker);
//第一轮比赛
//抽签
speech_contest_draw(v1);
//比赛
speech_contest(1,v1, m_Speaker,v2);
//显示比赛结果
cout << "================================================================================" << endl;
speech__contest_Show(1,v2, m_Speaker);//参数1:第几轮 参数2:晋级编号 参数3:具体人员信息
//第二轮比赛
//抽签
speech_contest_draw(v2);
//比赛
speech_contest(2, v2, m_Speaker, v3);
//显示比赛结果
cout << "================================================================================" << endl;
speech__contest_Show(2, v3, m_Speaker);
//第三轮比赛
//抽签
speech_contest_draw(v3);
//比赛
speech_contest(3, v3, m_Speaker, v4);
//显示比赛结果
cout << "================================================================================" << endl;
speech__contest_Show(3, v4, m_Speaker);
system("pause");
return0;
}
四、业务函数实现
//创建选手
void CreatSpeaker(vector<int> &v, map<int, Speaker>& m_Speaker)
{
string nameSeed = "ABCDEFGHIJKLMNOPQRSTUVWX";
for (int i = 0; i < nameSeed.size(); i++)
{
string name = "选手";
name += nameSeed[i];
Speaker sp;
sp.m_Name = name;
for (int j = 0; j < 3; j++)
{
sp.m_Score[j]=0;
}
v.push_back(i+100);//选手编号从100--123
m_Speaker.insert(make_pair(i + 100, sp));
}
}
//抽签
void speech_contest_draw(vector<int> &v)
{
//用洗牌算法进行抽签
random_shuffle(v.begin(), v.end());
}
//比赛
voidspeech_contest(int index,vector<int> &v1,map<int, Speaker> &m_Speaker,vector<int> &v2)
{
//声明临时容器,用来存储每组6个人的排名(从大到小) key:分数 value:编号
multimap<int, int, greater<int>>group_Map;
int num = 0;//计数器
//index:表示第几轮的得分
//v1:比赛选手
//m_Speaker:选手编号和具体的选手
//v2: 晋级的选手编号容器
for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
{
num++;//记录是不是够6个人
//用deque容器进行打分
deque<int>d;
for (int i = 0; i < 10; i++)
{
int score = rand() % 40 + 60;
d.push_back(score);
}
//排序分数
sort(d.begin(), d.end());
//去除最高最低分
d.pop_back();
d.pop_front();
//累计分数
int sum = accumulate(d.begin(), d.end(), 0);
int avg = sum / d.size();
//将平均分放入到m_Speaker容器中
m_Speaker[*it].m_Score[index - 1] = avg;
//每六个人取前三名晋级
//用临时的容器保存这6个人
//临时容器存放数据
group_Map.insert(make_pair(avg, *it));
if (num % 6 == 0)
{
//取前三名,遍历临时容器取前三名
int count = 0;
for (multimap<int, int, greater<int>>::iterator mit = group_Map.begin(); mit != group_Map.end(),count < 3 ; mit++ , count++)
{
//晋级容器获取数据
v2.push_back(mit->second);
}
group_Map.clear();//清空临时容器
}
}
}
//显示比赛结果
speech__contest_Show(int index,vector<int>& v,map<int,Speaker>& m_Speaker)//参数1:第几轮 参数2:晋级编号 参数3:具体人员信息
{
cout << "第" << index << "轮比赛成绩如下:" << endl;
for (map<int, Speaker>::iterator it = m_Speaker.begin(); it != m_Speaker.end(); it++)
{
cout << "选手编号:" << it->first << " 姓名:" << it->second.m_Name <<
" 得分:" << it->second.m_Score[index - 1] << endl;
}
cout << "-----------------晋级名单-----------------" << endl;
cout << "序号" << "\t" << "姓名" << "\t" << "得分" << endl;
//输出6个人员的信息
for (vector<int>::iterator v_it = v.begin(); v_it != v.end(); v_it++)
{
cout << *v_it << "\t" << m_Speaker[*v_it].m_Name << "\t" << m_Speaker[*v_it].m_Score[index-1] << endl;
}
}
五、运行结果
首先打印所有参赛人员信息
1、第一轮比赛
2、第二轮比赛
3、第三轮比赛
六 思考总结
该案例在控制台实现了简单的比赛业务逻辑,对其中的各种迭代器的使用要求比较高,在学习该案例的时候,一定要注意!对该案例提出以下改进的点:
1、在案例中,每个小组的比赛结果是否可以实施打印出来
2、打印每轮比赛成绩时,已经淘汰的人也会被打印出来,得分为0,是否可以仅显示紧急的选手成绩
3、最后一轮比赛结束时,前三名可以输出为冠军、亚军、季军