【C++ STL小案例】--演讲比赛

本文主要以演讲比赛为例介绍STL综合性的案例。
目录如下,全文较长,建议收藏阅读。

一、比赛介绍与需求分析

1、比赛介绍

  • 比赛方式:分组比赛,每组6个人;选手每次要随机分组,进行比赛;

第一轮:分为4个小组,每组6个人。比如100-105为一组,106-111为第二组,依次类推, 每人分别按照抽签(draw)顺序演讲。当小组演讲完后,淘汰组内排名最后的三个选手,然后继续下一个小组的比赛。
第二轮:分为2个小组,每组6人。比赛完毕,淘汰组内排名最后的三个选手,然后继续下一个小组的比赛。
第三轮:只剩下6个人,本轮为决赛,选出前三名。

评分标准:10个评委打分,去除最低、最高分,求平均分每个选手演讲完由10个评委分别打分。该选手的最终得分是去掉一个最高分和一个最低分,求得剩下的8个成绩的平均分。选手的名次按得分降序排列,若得分一样,按参赛号升序排名。

2、需求分析

  1. 产生选手(A~X),姓名,得分,选手编号。
  2. 第一轮比赛:选手抽签,选手比赛,查看比赛结果
  3. 第二轮比赛,选手抽签,选手比赛,查看比赛结果
  4. 第三轮比赛,选手抽签,选手比赛,查看比赛结果

二、实现思路分析

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;
	}
	
}

五、运行结果

首先打印所有参赛人员信息
在这里插dffdsfsf述

1、第一轮比赛

在这里插入图片描述

2、第二轮比赛

在这里插入图片描述

3、第三轮比赛

在这里插入图片描述

六 思考总结

该案例在控制台实现了简单的比赛业务逻辑,对其中的各种迭代器的使用要求比较高,在学习该案例的时候,一定要注意!对该案例提出以下改进的点:
1、在案例中,每个小组的比赛结果是否可以实施打印出来
2、打印每轮比赛成绩时,已经淘汰的人也会被打印出来,得分为0,是否可以仅显示紧急的选手成绩
3、最后一轮比赛结束时,前三名可以输出为冠军、亚军、季军

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值