#include "SingingCompetition.h"
#include <Windows.h>
#include <algorithm>
CSingingCompetition::CSingingCompetition(void)
{
m_iRound = 0;
srand((unsigned)time(0));
}
CSingingCompetition::~CSingingCompetition(void)
{
}
void CSingingCompetition::JoinCompetition()
{
string strNameBaseSource("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); //名字组成元素的来源
random_shuffle(strNameBaseSource.begin(),strNameBaseSource.end());
for (int i = 0; i < 24; i ++)
{
string strExt(1,strNameBaseSource[i]);
Singer singer;
singer.iLatestScore = 0;
singer.strName = "选手" + strExt;
m_mapSinger.insert(make_pair(i + 100,singer));
m_lstRemainingID.push_back(i + 100);
}
for (map<int,Singer>::iterator it = m_mapSinger.begin(); it != m_mapSinger.end(); it ++)
{
string szoutput;
szoutput = it->second.strName;
cout << it->second.strName << " 参赛号:" << it->first << endl;
}
}
void CSingingCompetition::FirstKnockout()
{
if (m_iRound == 0)
{
m_iRound = 1;
//进行淘汰赛
Knockout();
cout<<"第" << m_iRound <<" 轮淘汰赛中被淘汰的歌手的名字 "<< endl;
for (vector<int>::iterator it=m_vecIDBeEliminatedInFirstRound.begin(); it!=m_vecIDBeEliminatedInFirstRound.end(); ++it)
{
cout<<m_mapSinger[*it].strName.c_str() << endl;
}
cout << endl << endl;
}
}
void CSingingCompetition::SecondKnockout()
{
if (m_iRound == 1)
{
m_iRound = 2;
//进行淘汰赛
Knockout(); //逻辑与第一轮差不多,区别在下页
cout<<"第" << m_iRound <<" 轮淘汰赛中被淘汰的歌手的分数: " << endl;
for (multiset<int>::iterator it=m_mltsetScoreBeEliminatedInSecondRound.begin(); it!=m_mltsetScoreBeEliminatedInSecondRound.end(); ++it)
{
cout<< *it << " ";
}
cout << endl << endl;
}
}
void CSingingCompetition::Finals()
{
if (m_iRound == 2)
{
m_iRound = 3;
//第三轮决赛
for (list<int>::iterator it=m_lstRemainingID.begin(); it!=m_lstRemainingID.end(); ++it)
{
//生成歌手的分数
MakeScore(m_mapSinger[*it]);
//记录当前小组歌手的得分情况,按分数降序排列
m_mltmapCurGroup.insert(pair<int,int>(m_mapSinger[*it].iLatestScore, *it));
}
//打印小组决赛情况
cout <<"*************小组决赛情况:*************\n";
for (multimap<int,int, greater<int> >::iterator it=m_mltmapCurGroup.begin(); it!=m_mltmapCurGroup.end(); ++it)
{
cout <<m_mapSinger[it->second].strName << "的得分:" <<it->first << endl;
}
cout << endl;
m_mapSinger.clear();
m_lstRemainingID.clear();
m_vecIDBeEliminatedInFirstRound.clear();
m_mltsetScoreBeEliminatedInSecondRound.clear();
m_mltmapCurGroup.clear();
m_iRound = 0;
}
}
void CSingingCompetition::Knockout()
{
cout <<"*************第" << m_iRound <<" 轮淘汰赛:*************" << endl;
int iSingerIndex = 0; //第几个歌手正在演唱,1代表第一个歌手,2代表第二个歌手。。。
for (list<int>::iterator it=m_lstRemainingID.begin(); it!=m_lstRemainingID.end(); )
{
++iSingerIndex;
//生成歌手的分数
MakeScore(m_mapSinger[*it]);
//记录当前演唱小组歌手的得分情况,按分数降序排列
m_mltmapCurGroup.insert(pair<int,int>(m_mapSinger[*it].iLatestScore, *it));
if (iSingerIndex%6 == 0)
{
//小组演唱完毕,打印小组得分情况
PrintGroupScore();
//在当前小组中淘汰歌手
EraseInCurGroup();
//在剩余歌手中删除歌手
EraseInRemainingID(it++);
}
else
{
++it;
}
}
}
void CSingingCompetition::MakeScore(Singer &singer)
{
deque<int> deqScore; //为什么选用deque? 其它容器呢?
//vector在去掉一个最高分,一个最低分时,需要从头部移除一个元素,效率低。
//list不支持随机索引,在下面的accumulate的计算也比较慢。
//set/multiset一开始就排序,按流程来说的十个评委评分过程是不排序的,然后评分后再排序去掉最高分最低分。如果不考虑流程,在这程序中可以使用multiset(分数可能一样,set不行),使一开始就排序好,不过在accumulate的计算中,也比较慢。
//map/multimap是映射,在这边不需要。
//十个评委分别对歌手打分,打分过程没要求排序
for (int i=0; i<10; ++i)
{
int iScore = 60 + rand()%40;
deqScore.push_back(iScore);
}
//为十个评委的打分排序
sort(deqScore.begin(), deqScore.end());
//去掉一个最高分,去掉一个最低分
deqScore.pop_front();
deqScore.pop_back();
//求八个评委打分的总和
int iScoreSum = accumulate(deqScore.begin(), deqScore.end(), 0);
//求八个评委打分的平均分
int iScoreAverage = (int)(iScoreSum/deqScore.size());
//给歌手设置得分
singer.iLatestScore = iScoreAverage;
}
void CSingingCompetition::PrintGroupScore()
{
cout <<"小组得分情况:" << endl;
for (multimap<int,int, greater<int> >::iterator it=m_mltmapCurGroup.begin(); it!=m_mltmapCurGroup.end(); ++it)
{
cout <<m_mapSinger[it->second].strName <<"得分 : " << it->first << endl;
}
cout << endl;
}
void CSingingCompetition::EraseInCurGroup()
{
int iSingerLastIndexInGroup = 0; //组内歌手的倒数索引
while(iSingerLastIndexInGroup<3)
{
//获取当前演唱小组的最后一个元素的迭代器
multimap<int,int,greater<int> >::iterator it=m_mltmapCurGroup.end();
--it;
++iSingerLastIndexInGroup;
if (m_iRound == 1)
{
//记录第一轮淘汰赛中被淘汰的歌手的参赛号
m_vecIDBeEliminatedInFirstRound.push_back(it->second);
}
else if (m_iRound == 2)
{
//记录第二轮淘汰赛中被淘汰的歌手的分数
m_mltsetScoreBeEliminatedInSecondRound.insert(m_mapSinger[it->second].iLatestScore);
}
//从当前演唱小组的集合容器中删除最后一个元素
m_mltmapCurGroup.erase(it);
}
}
void CSingingCompetition::EraseInRemainingID(list<int>::iterator it)
{
int iSingerReverseIndexInGroup = 0; //逆向遍历的索引
while(iSingerReverseIndexInGroup<6)
{
//查找逆向遍历迭代器所指的参赛ID所对应歌手的{分数,参赛ID}是否在当前演唱小组中
multimap<int,int,greater<int> >::iterator itMltmapScoreToID =
find(m_mltmapCurGroup.begin(),m_mltmapCurGroup.end(),
multimap<int,int,greater<int> >::value_type(m_mapSinger[*it].iLatestScore,
*it));
if (itMltmapScoreToID == m_mltmapCurGroup.end())
{
//没找到,从剩余歌手集合中删除该歌手的参赛号
it = m_lstRemainingID.erase(it);
}
//逆向遍历的索引自增
++iSingerReverseIndexInGroup;
//防止对容器的begin()迭代器进行--操作。
if (it != m_lstRemainingID.begin())
{
--it;
}
}
//清除该组的比赛记录存储,以便下一组比赛记录的存储
m_mltmapCurGroup.clear();
}