【贪玩巴斯】C++项目实战:演讲比赛「黑马程序员实战项目——文件IO流,Vector容器使用,内置算法调用,bug解决」

//  Created by AchesonD16 贪玩巴斯 on 2021/9/7.

项目名称:

演讲比赛

比赛规则:

学校举行一场演讲比赛,共有12个人参加。比赛共两轮,第一轮为淘汰赛,第二轮为决赛。

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

每名选手都有对应的编号,如 10001 ~ 10012

第一轮分为两个小组,每组6个人。 整体按照选手编号进行抽签后顺序演讲。

十个评委分别给每名选手打分,去除最高分,最低分,求的平均分为本轮选手的成绩。

当小组演讲完后,淘汰组内排名最后的三个选手,前三名晋级,进入下一轮的比赛。

第二轮为决赛,前三名胜出

每轮比赛过后需要显示晋级选手的信息

程序功能:

开始演讲比赛:完成整届比赛的流程,每个比赛阶段需要给用户一个提示,用户按任意键后继续下一个阶段

查看往届记录:查看之前比赛前三名结果,每次比赛都会记录到文件中,文件用.csv后缀名保存

清空比赛记录:将文件中数据清空

退出比赛程序:可以退出当前程序

以下为main主函数:

#include <iostream>

using namespace std;

#include "speechManager.hpp"

#include <string>

#include <ctime>



int main()

{

    // 随机数种子

    srand((unsigned int)time(NULL));

    

    // 创建管理类对象

    SpeechManager sm;

    

//     测试12名选手创建

//    for(map<int, Speaker>::iterator it = sm.m_Spearker.begin(); it != sm.m_Spearker.end(); it++)

//    {

//        cout << "选手编号:" << it->first << " 姓名:" << it->second.m_Nmae << " 分数:" << it->second.m_Score[0] << endl;

//    }

    

    

    

    int choice = 0; //用于存储用户输入

    while (true)

    {

        sm.show_Menu();

        cout << "请输入您的选择:" << endl;

        cin >> choice;

        

        switch (choice)

        {

            case 1: // 开始比赛

                sm.startSpeech();

                break;

            case 2: // 查看往届记录

//                sm.loadRecord();

                sm.showRecord();

                break;

            case 3: // 清空比赛记录

                sm.clearRecord();

                break;

            case 0: // 退出系统

                sm.exitSystem();

                break;

                

            default:

                system("cls"); // 清屏

                break;

        }

    }

    

    system("pause");

    return 0;

}

// 首先创建一个管理类 speechManager.h 和 speechManager.cpp

//功能:

//提供菜单界面与用户交互

//对演讲比赛流程进行控制

//与文件的读写交互

以下为speechManager.h头文件:

//
//  speechManager.hpp
//  ProjectSpeechgame
//
//  Created by AchesonD16 贪玩巴斯 on 2021/9/7.
//

#ifndef speechManager_hpp
#define speechManager_hpp
#include <stdio.h>

#pragma once
#include <iostream>
#include <vector>
#include <map>
#include "speaker.hpp"
#include <algorithm>
#include <deque>
#include <functional>
#include <numeric>
#include <fstream>
using namespace std;

#endif /* speechManager_hpp */

// 设计演讲管理类
// 注意在.h文件中只做声明,不实现
class SpeechManager
{
public:
    // 构造函数
    SpeechManager();
    
    // 菜单功能
    void show_Menu();
    
    // 退出功能
    void exitSystem();
    
    // 析构函数
    ~SpeechManager();
    
    // 初始化容器和属性
    void initSpeech();
    
    // 创建12名选手
    void createSpeaker();
    
    // 开始比赛 比赛整个流程的控制函数
    void startSpeech();
    
    // 抽签
    void speechDraw();
    
    // 比赛
    void speechContest();
    
    // 显示得分
    void showScore();
    
    // 保存分数记录
    void saveRecord();
    
    // 读取记录
    void loadRecord();
    
    // 显示往届记录
    void showRecord();
    
    // 清空文件
    void clearRecord();
    
    
    // 判断文件是否为空
    bool fileIsEmpty;
    
    // 存放往届记录的容器
    map<int, vector<string>> m_Record;
    
    // 成员属性
    // 保存第一轮比赛选手编号的容器
    vector<int> v1;
    
    // 第一轮晋级选手编号容器
    vector<int> v2;
    
    // 胜出前三名选手编号容器
    vector<int> vVictory;
    
    // 存放编号以及对应具体选手容器
    map<int, Speaker> m_Spearker;

    // 存放比赛轮数
    int m_Index;
};

以下为speechManager.cpp源程序:

//
//  speechManager.cpp
//  ProjectSpeechgame
//
//  Created by AchesonD16 贪玩巴斯 on 2021/9/7.
//

#include "speechManager.hpp"

// 构造函数 要把类的范围作用域加上
SpeechManager::SpeechManager()
{
    // 初始化容器和属性
    this->initSpeech();
    
    // 创建12名选手 函数调用
    this->createSpeaker();
    
    // 加载往届记录
    this->loadRecord();
    
}

// 菜单功能
void SpeechManager::show_Menu()
{
    cout << "-----------------------------------------"  << endl;
    cout << "------------- 欢迎参加演讲比赛 -------------"  << endl;
    cout << "------------- 1.开始演讲比赛 --------------"  << endl;
    cout << "------------- 2.查看往届记录 --------------"  << endl;
    cout << "------------- 3.清空比赛记录 --------------"  << endl;
    cout << "------------- 0.退出比赛程序 --------------"  << endl;
    cout << "-----------------------------------------"  << endl;
    cout << endl;
}

// 退出功能
void SpeechManager::exitSystem()
{
    cout << "欢迎下次使用!" << endl;
    system("pause");
    exit(0);
}

// 容器值初始化函数
void SpeechManager::initSpeech()
{
    // 容器都置空
    this->v1.clear();
    this->v2.clear();
    this->vVictory.clear();
    this->m_Spearker.clear();
    
    // 初始化比赛轮数
    this->m_Index = 1;
    
    // 将记录的容器 也清空
    this->m_Record.clear();
}

// 创建12名选手 构造函数中调用
void SpeechManager::createSpeaker()
{
    string nameSeed = "ABCDEFGHIJKL"; // 创建随机数种子
    for(int i = 0; i < nameSeed.size(); i++) // 给12个选手附上属性
    {
        string name = "选手";
        name += nameSeed[i]; // 选手 + A
        
        // 创建具体选手
        Speaker sp;
        sp.m_Nmae = name;
        
        for(int j = 0; j < 2; j++)
        {
            sp.m_Score[j] = 0; // 初始化两轮成绩皆为0
        }
        
        // 创建选手编号, 并且放入到v1容器中
        this->v1.push_back(i + 10001);
        
        // 选手编号以及对应选手 放入到map容器中
        this->m_Spearker.insert(make_pair( i + 10001, sp));
    }
}

// 开始比赛,创建一个 比赛整个流程控制的函数
void SpeechManager::startSpeech()
{
    // 第一轮开始比赛
    
    // 1、抽签
    this->speechDraw();
    // 2、比赛
    this->speechContest();
    // 3、显示晋级结果
    this->showScore();
    // 第二轮开始比赛
    this->m_Index++;
    // 1、抽签
    this->speechDraw();
    // 2、比赛
    this->speechContest();
    // 3、显示最终结果
    this->showScore();
    // 4、保存分数到文件中
    this->saveRecord();
    
    // 重置比赛,获取记录
    // 初始化容器和属性
    this->initSpeech();
    
    // 创建12名选手
    this->createSpeaker();
    
    // 加载往届记录
    this->loadRecord();
    
    
    cout << "本届比赛完毕!" << endl;
    system("pause");
    system("cls");
}

// 抽签
void SpeechManager::speechDraw()
{
    cout << "第 (" << this->m_Index << ")轮比赛选手正在抽签" << endl;
    cout << "---------------------------" << endl;
    cout << "抽签后演讲顺序如下:" << endl;
    
    if(this->m_Index == 1)
    {
        // 第一轮比赛
        random_shuffle(v1.begin(), v1.end());
        for(vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    else
    {
        // 第二轮比赛
        random_shuffle(v2.begin(), v2.end());
        for(vector<int>::iterator it = v2.begin(); it != v2.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    
    cout << "---------------------------" << endl;
    system("pause");
    cout << endl;
    
}

// 比赛功能实现的函数
void SpeechManager::speechContest()
{
    cout << "---------- 第 " << this->m_Index << " 轮比赛正式开始 ----------" << endl;
    
    // 准备临时容器 存放小组成绩
    multimap<double, int, greater<double>> groupScore;
    
    int num = 0; // 记录六人为一个组
    
    
    vector<int>v_Src; //比赛选手容器
    if(this->m_Index == 1)
    {
        v_Src = v1;
    }
    else
    {
        v_Src = v2;
    }
    
    // 遍历所有选手进行比赛
    for(vector<int>::iterator it = v_Src.begin(); it != v_Src.end(); it++)
    {
        num++;
        
        // 评委打分
        deque<double> d;
        for(int i = 0; i < 10; i++)
        {
            // 进行随机数打分
            double score = (rand() % 401 + 600) / 10.f; // 600~1000 10.f表示10的double类型
            // cout << score << " "; 可以显示具体的分数得分情况
            d.push_back(score);
        }
//        cout << endl;
        
        sort(d.begin(), d.end(), greater<double>());  // 排序操作
        d.pop_front(); // 去除最高分
        d.pop_back();  // 去除最低分
        
        double sum = accumulate(d.begin(), d.end(), 0.0f); // 总分
        double avg = sum / (double)d.size();  // 平均分 因为d.size()为整数,需要强转化为double型
    
        // 打印平均分
        // cout << "编号:" << *it << " 姓名:" << this->m_Spearker[*it].m_Nmae << " 获取平均分:" << avg << endl;
        
        // 将平均分放入到map容器中
        // 非常关键的一步
        this->m_Spearker[*it].m_Score[this->m_Index - 1] = avg;
        
        // 将打分的数据 放入到临时小组容器中
        groupScore.insert(make_pair(avg, *it));   // key是得分,value是具体选手编号
        // 每6人取出前三名
        if(num % 6 == 0)
        {
            cout << "第 " << num / 6 << " 小组比赛名次:" << endl;
            for(multimap<double, int, greater<double>>::iterator it = groupScore.begin(); it != groupScore.end(); it++)
            {
                cout << "编号:" << it->second << " 姓名:" << this->m_Spearker[it->second].m_Nmae << " 成绩:" << this->m_Spearker[it->second].m_Score[this->m_Index - 1] << endl;
            }
            
            // 取走前三名 放入下一个容器中
            int count = 0;
            for(multimap<double, int, greater<double>> :: iterator it = groupScore.begin(); it != groupScore.end() && count < 3; it++,count++)
            {
                if(this->m_Index == 1)
                {
                    v2.push_back((*it).second);
                }
                else
                {
                    vVictory.push_back((*it).second);
                }
            }
            
            groupScore.clear();  // 小组的容器要清空 不然会追加一些新的值进来
            cout << endl;
        }
    }
    cout << "---------------- 第 " << this->m_Index << " 轮比赛完毕 -------------" << endl;
    system("pause");
}

// 显示得分 函数
void SpeechManager::showScore()
{
    cout << "---------- 第 " << this->m_Index << " 轮晋级选手信息如下:----------" << endl;
    
    vector<int>v;
    if(this->m_Index == 1)
    {
        v = v2;
    }
    else
    {
        v = vVictory;
    }
    
    for(vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << "选手编号:" << *it << " 姓名:" << this->m_Spearker[*it].m_Nmae << " 得分:" << this->m_Spearker[*it].m_Score[this->m_Index - 1] << endl;
    }
    cout << endl;
    
    system("pause");
    system("cls");
    this->show_Menu();
}

// 保存记录函数
void SpeechManager::saveRecord()
{
    ofstream ofs;
    ofs.open("speech.csv", ios::out | ios::app); // 用追加的方式写文件
    
    // 将每个选手数据 写入到文件中
    for(vector<int>::iterator it = vVictory.begin(); it != vVictory.end(); it++)
    {
        ofs << *it << "," << this->m_Spearker[*it].m_Score[1] << "," ; // 这里打印的是第二轮即最后进入总决赛的前三名成绩
    }
    ofs << endl;
    
    // 关闭
    ofs.close();
    cout << "记录已经保存!" << endl;
    
    // 更改文件不为空的状态
    this->fileIsEmpty = false;
}

// 读取记录的函数
void SpeechManager::loadRecord()
{
    ifstream ifs("speech.csv", ios::in);  // 读取文件
    
    if(!ifs.is_open()) // 文件打开失败了调用函数非flase !flase则为 true
    {
        this->fileIsEmpty = true;
        // 测试代码
        //cout << "文件不存在" << endl;
        ifs.close();
        return;
    }
    
    // 文件清空清空
    char ch;
    ifs >> ch;
    if(ifs.eof())
    {
        // 测试代码
        // cout << "文件为空" << endl;
        this->fileIsEmpty = true;
        ifs.close();
        return;
    }
    
    // 文件不为空的情况
    this->fileIsEmpty = false;
    
    ifs.putback(ch);  // 将上面读取的单个字符 放回来
    
    string data;
    int index = 0; // 第几届的存储值
    
    while (ifs >> data)
    {
//        cout << data << endl; // 打印
//        10005,83.6125,10007,82.7375,10008,80.725,
//        解析存储的数据
        
        vector<string> v; //存放6个string的字符串
        
        int pos = -1; // 查到 ',' 位置的变量
        int start = 0;
        
        while(true)
        {
            
        pos = data.find(",", start);
        
        if(pos == -1)
        {
            // 没有找到的情况
        }
        string temp = data.substr(start, pos-start);
//        cout << temp << endl;
            v.push_back(temp);
        
        start = pos + 1;
        }
        
        this->m_Record.insert(make_pair(index, v));
        index ++ ;
    }
    ifs.close();
    
    for(map<int, vector<string>>::iterator it = this->m_Record.begin(); it != this->m_Record.end(); it++)
    {
        cout << it->first << "冠军编号:" << it->second[0] << " 分数:" << it->second[1] << endl;
    }
}

// 显示往届记录
void SpeechManager::showRecord()
{
    if(this->fileIsEmpty)
    {
        cout << "文件为空或者文件不存在!" << endl;
    }
    else{
        for(int i = 0; i < this->m_Record.size(); i++)
        {
            cout << " 第" << i + 1 << "届 " << "冠军编号:" << this->m_Record[i][0] << " 得分:" << this->m_Record[i][1] << " " << "亚军编号:" << this->m_Record[i][2] << " 得分:" << this->m_Record[i][3] << " " << "季军编号:" << this->m_Record[i][4] << " 得分:" << this->m_Record[i][5] << endl;
        }
    }
   
    system("pause");
    system("cls");
}

// 清空文件
void SpeechManager::clearRecord()
{
    cout << "是否确定清空文件?" << endl;
    cout << "1、是" << endl;
    cout << "2、否" << endl;
    
    int select = 0;
    
    cin >> select;
    
    if(select == 1)
    {
        // 确认清空
        ofstream ofs("speech.csv", ios::trunc); // 存在直接删除,然后重新创建新的空文件
        ofs.close();
        
        // 初始化容器和属性
        this->initSpeech();
        
        // 创建12名选手 函数调用
        this->createSpeaker();
        
        // 加载往届记录
        this->loadRecord();
        
        cout << "清空成功!" << endl;
    }
    system("pause");
    system("cls");
}


// 析构函数
SpeechManager::~SpeechManager()
{
    
}

以下为speaker.hpp:

//
//  speaker.hpp
//  ProjectSpeechgame
//
//  Created by AchesonD16 贪玩巴斯 on 2021/9/8.
//

#ifndef speaker_hpp
#define speaker_hpp
#include <stdio.h>
#endif /* speaker_hpp */

#pragma once
#include <iostream>

using namespace std;

// 选手类
class Speaker
{
public:
    string m_Nmae;  // 姓名
    double m_Score[2];  // 分数两轮
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贪玩巴斯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值