这个综合案例也是来源黑马程序员的,总觉得学了C++之后,不写点东西,都有点心虚,所以写了一下这个东西,希望不要嫌弃。
12.1 学校演讲比赛介绍
12.2 需求分析
12.3 实现思路
- 使用一个map容器,存储选手信息,map容器的key为uID(参赛编号),值为Player(选手对象),可以通过uID找到Playe的对象。
- 创建一个容器vector v;作为统一摇号的容器,把需要抽签的时候的uID都集中到这个容器中,然后进行抽签。
- 还创建了分组容器vector v1[4];因为需要4组,所以创建了一个容器数组,这样理解起来比较简单,先通过容器v抽签,抽完签之后,从头到尾存储到v1分组的4个容器中,然后每一组进行比赛,评分。
- 评分的时候,因为有10个评委,需要去掉最高分和最低分,这里使用了deque容器,这个容器就是操作头尾比较快速,刚好排完序之后,去掉头尾刚好是最高分和最低分,剩下的求平均。
- 评分的结果需要排序,第一是按最后算出平均分排序,第二如果平均分一样的话,按参赛编号升序排,这个确实让我纠结了很久,不过百度了一些找到了一篇讲:
对于multimap相同的key是value的排序
参考这篇博客:javascript:void(0)
所以就参考了这个写了一个出来,这样就符合题目的意思了。 - 一轮比赛完成之后,下一轮之前,还需要再次进行抽签,所以把之前的分组v1里面的数组又全部拷贝到抽签容器v中,然后进行抽签,抽完签,再次分配到各自的分组中,再次进行评分。
12.4 实现代码
#include <iostream>
#include <string>
#include <unordered_map>
#include <map>
#include <vector>
#include <ctime>
#include <algorithm>
#include <deque>
#include <numeric>
using namespace std; //老是不记得命名空间
#define random(x) rand()%(x)
#define random_2(a, b) ((rand() % (b-a)) + (a))
class Person
{
public:
string name;
int age;
Person(string name, int age) : name(name), age(age) {
}
Person(char name, int age) {
this->name = name;
this->age = age;
}
};
class Player : public Person
{
public:
int grade;
int uID; //参赛的编号
Player(string name, int age, int uID) : Person(name, age), uID(uID) {
grade = 0;
}
Player(char name, int age, int uID) : Person(name, age), uID(uID) {
grade = 0;
}
friend ostream& operator<<(ostream& os, Player& p);
};
ostream& operator<<(ostream& os, Player& p)
{
os << " 名字 " << p.name << " 年龄 " << p.age << " 编号 " << p.uID << " 成绩 " << p.grade << endl;
return os;
}
//评分
void player_score(vector<int>& v, map<int, Player>& m) {
multimap<int, int> m_map; //这个是可以自动排序的map, 第一个是成绩,第二个是uID, 第三个是排序greater<int>大到小
multimap<int, int, greater<int>> u_map; //这个是为了排uID的
for(vector<int>::iterator it = v.begin(); it != v.end(); it++) {
deque<int> grade;
for(int i=0; i<10; i++) { //10个评委
grade.push_back(random_2(20, 60));
}
//去掉最高分,和最低分
sort(grade.begin(), grade.end());
grade.front();
grade.back();
//算出平均值
int sum = accumulate(grade.begin(), grade.end(), 0);
map<int, Player>::iterator ret = m.find(*it);
if(ret == m.end())
throw out_of_range("超出范围");
ret->second.grade = sum / 8;
m_map.insert(make_pair(*it, ret->second.grade)); //这里要先反过来
}
//这个是对uID也进行排序,就是再次对map排序
for(auto it1 = m_map.begin(); it1!=m_map.end(); it1++)
{
u_map.insert(pair<int,int>(it1->second, it1->first));
}
//保存到v[i]
v.clear();
int count = 0;
for(multimap<int, int>::iterator it = u_map.begin(); it != u_map.end(); it++) {
count++;
if(count <= 3) {
v.push_back(it->second);
}
}
}
//打印晋级选手
void print_promotion(vector<int>& v, map<int, Player>& m)
{
//sort(v.begin(), v.end()); //先把参数编号按升序排列
for(vector<int>::iterator it = v.begin(); it != v.end(); it++) {
map<int, Player>::iterator ret = m.find(*it);
//cout << *it << endl;
if(ret == m.end())
throw out_of_range("超出范围");
cout << ret->second;
}
}
//抽签和分组 v要进行抽签的序列,v1是分组的序列, num是几个分组,size是一个分组有几个元素
void draw_group(vector<int>&v, vector<int> v1[], int num, int size)
{
static int first = 0;
vector<int>::iterator it;
if(first == 0) {
first = 1;
} else if(first == 1) {
v.clear();
v.resize(num*size);
it = v.begin();
for(int i=0; i<num*2; i++,it+=size/2) {
copy(v1[i].begin(), v1[i].end(), it);
}
}
//抽签
random_shuffle(v.begin(), v.end());
//分组
it = v.begin();
for(int i=0; i<num; i++,it=it+size) {
v1[i].resize(size);
copy(it, it+size, v1[i].begin());
}
}
int main(int argc, char **argv) {
cout << "hello c++" << endl;
//创建选手
map<int, Player> p_map;
vector<int> v;
vector<int> v1[4];
char name[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
srand(time(NULL));
for(int i = 1; i<=24; i++) {
p_map.insert(pair<int, Player>(i, Player(name[i], random_2(20, 60), i)));
v.push_back(i);
}
for(map<int, Player>::iterator it = p_map.begin(); it != p_map.end(); it++) {
cout << it->first << " " << it->second;
}
int num = 24/6;
for(int i=0; i<3; i++) {
//创建分组,并且抽签
draw_group(v, v1, num, 6);
//开始演讲,并且评分
cout << "==============================" << endl;
for(int i=0; i<num; i++) {
player_score(v1[i], p_map);
}
//打印这一轮晋级的选手
for(int i=0; i<num; i++) {
print_promotion(v1[i], p_map);
cout << "==============================" << endl;
}
num /= 2;
}
return 0;
}
用c++写了这段程序,相比于c语言来说,变化确实有点大,c++容器和算法都写好了,需要用就申请,然后调用就可以了,相对于c还需要自己写数据结构和基本的算法,确实提高了不少的效率,还有就是写c++的时候好像没怎么关注内存,可能是新手还对内存深入不了,对c的话,老是扣内存。
不知道以后还要不要学习其他语言,虽然语言只是工具,但是这个工具如果好用的话,还是需要学的。
且学且珍惜,共勉。