美文网首页
C++ STL容器实现简单的演讲比赛系统

C++ STL容器实现简单的演讲比赛系统

作者: FredricZhu | 来源:发表于2021-11-22 16:41 被阅读0次

需求分析如下,


image.png

工程目录如下


image.png

CMakeLists.txt

cmake_minimum_required(VERSION 2.6)

if(APPLE)
    message(STATUS "This is Apple, do nothing.")
elseif(UNIX)
    message(STATUS "This is linux, set CMAKE_PREFIX_PATH.")
    set(CMAKE_PREFIX_PATH /vcpkg/ports/cppwork/vcpkg_installed/x64-linux/share)
endif(APPLE)

project(speech_match)

add_definitions(-std=c++17)

add_definitions(-g)

find_package(ZLIB)

find_package(glog REQUIRED)

find_package(OpenCV REQUIRED )

find_package(Boost REQUIRED COMPONENTS
    system
    filesystem
    serialization
    program_options
    thread
    )

find_package(DataFrame REQUIRED)

if(APPLE)
    MESSAGE(STATUS "This is APPLE, set INCLUDE_DIRS")
set(INCLUDE_DIRS ${Boost_INCLUDE_DIRS} /usr/local/include /usr/local/iODBC/include /opt/snowflake/snowflakeodbc/include/ ${CMAKE_CURRENT_SOURCE_DIR}/../../include/ ${CMAKE_CURRENT_SOURCE_DIR}/include/)
elseif(UNIX)
    MESSAGE(STATUS "This is linux, set INCLUDE_DIRS")
    set(INCLUDE_DIRS ${Boost_INCLUDE_DIRS} /usr/local/include ${CMAKE_CURRENT_SOURCE_DIR}/../../include/ ${CMAKE_CURRENT_SOURCE_DIR}/include/)
endif(APPLE)


if(APPLE)
    MESSAGE(STATUS "This is APPLE, set LINK_DIRS")
    set(LINK_DIRS /usr/local/lib /usr/local/iODBC/lib /opt/snowflake/snowflakeodbc/lib/universal)
elseif(UNIX)
    MESSAGE(STATUS "This is linux, set LINK_DIRS")
    set(LINK_DIRS ${Boost_INCLUDE_DIRS} /usr/local/lib /vcpkg/ports/cppwork/vcpkg_installed/x64-linux/lib)
endif(APPLE)

if(APPLE)
    MESSAGE(STATUS "This is APPLE, set ODBC_LIBS")
    set(ODBC_LIBS iodbc iodbcinst)
elseif(UNIX)
    MESSAGE(STATUS "This is linux, set LINK_DIRS")
    set(ODBC_LIBS odbc odbcinst ltdl)
endif(APPLE)

include_directories(${INCLUDE_DIRS})
LINK_DIRECTORIES(${LINK_DIRS})

file( GLOB main_file_list ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) 

file( GLOB APP_SOURCES  ${CMAKE_CURRENT_SOURCE_DIR}/*.h ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/../../include/http/impl/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../include/yaml/impl/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../include/df/impl/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../include/death_handler/impl/*.cpp  ${CMAKE_CURRENT_SOURCE_DIR}/include/utils/*.h ${CMAKE_CURRENT_SOURCE_DIR}/include/utils/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/impl/utils/*.cpp)

add_library(${PROJECT_NAME}_lib SHARED ${APP_SOURCES})
target_link_libraries(${PROJECT_NAME}_lib ${Boost_LIBRARIES} ZLIB::ZLIB glog::glog DataFrame::DataFrame ${OpenCV_LIBS})
target_link_libraries(${PROJECT_NAME}_lib  ssl crypto libgtest.a pystring libyaml-cpp.a libgmock.a ${ODBC_LIBS} libnanodbc.a pthread dl backtrace)

foreach( main_file ${main_file_list} )
    file(RELATIVE_PATH filename ${CMAKE_CURRENT_SOURCE_DIR} ${main_file})
    string(REPLACE ".cpp" "" file ${filename})
    add_executable(${file}  ${main_file})
    target_link_libraries(${file} ${PROJECT_NAME}_lib)
endforeach( main_file ${main_file_list})

main.cpp

#include "utils/speech_manager.h"
#include "utils/funcs.h"

#include <iostream>
#include <cstdlib>

int main(int argc, char* argv[]) {

    srand((unsigned int)time(nullptr));
    speech_manager sm;

    int choice {};
    while(true) {
        sm.show_menu();
        std::cout << "请输入您的选择: " << std::endl;
        std::cin >> choice;
        switch (choice) {
        case 1:
            sm.start_speech();
            break;
        case 2:
            sm.show_record();
            break;
        case 3:
            sm.clear_record();
            break;
        case 0:
            sm.exit_system();
            break;
        default:
            Funcs::clear();
            break;
        }
    }
    

    Funcs::pause();
    
    return EXIT_SUCCESS;
}

include/utils/speech_manager.h

#ifndef _FREDIRC_SPEECH_MANAGER_H_
#define _FREDIRC_SPEECH_MANAGER_H_

#include "beans/speaker.h"

#include <vector>
#include <map>
#include <string>

class speech_manager {
    public:
        speech_manager();
        ~speech_manager();

        void show_menu();
        void exit_system();

        void init_speech();
        void create_speaker();
        void start_speech();
        void speech_contest();

        // 显示比赛得分
        void show_score();
        // 保存记录
        void save_record();
        // 读取往届记录
        void load_record();
        // 查看往届记录
        void show_record();
        // 清空记录
        void clear_record();

        // 抽签
        void speech_draw();
    // private:
        // 第一轮比赛选手容器12人
        std::vector<int> v1;
        // 第一轮晋级容器6人
        std::vector<int> v2;
        // 胜利前3名容器
        std::vector<int> v_victory;

        std::map<int, speaker> m_speakers;

        // 记录比赛轮数
        int m_index;
        // 文件是否为空指示符
        bool m_file_empty;
        // 往届记录数据
        std::map<int, std::vector<std::string>> m_record;
};
#endif

impl/utils/speech_manager.h

#include "utils/speech_manager.h"
#include "utils/funcs.h"
#include "pystring/pystring.h"

#include <iostream>
#include <sstream>
#include <fstream>
#include <chrono>
#include <algorithm>
#include <functional>
#include <random>
#include <deque>

speech_manager::speech_manager() {
    // 初始化属性
    init_speech();
    // 创建选手
    create_speaker();
    // 读取往届记录
    load_record();
}

speech_manager::~speech_manager() {

}

void speech_manager::show_menu() {
    std::cout << "****************************************" << std::endl;
    std::cout << "************   欢迎参加演讲比赛   *********" << std::endl;
    std::cout << "************   1.开始演讲比赛    *********" << std::endl;
    std::cout << "************   2.查看往届记录    *********" << std::endl;
    std::cout << "************   3.清空比赛记录    *********" << std::endl;
    std::cout << "************   0.退出比赛程序    *********" << std::endl;
    std::cout << std::endl;
}

void speech_manager::exit_system() {
    std::cout << "欢迎下次使用" << std::endl;
    Funcs::pause();
    ::exit(0);
}
    
void speech_manager::init_speech() {
    v1.clear();
    v2.clear();
    v_victory.clear();

    m_speakers.clear();
    m_index = 1;
    m_record.clear();
}

void speech_manager::create_speaker() {
    std::string name_seed = "ABCDEFGHIJKL";
    std::string name_prefix = "选手";
    for(int i=0; i<name_seed.size(); ++i) {
        std::stringstream name_ss;
        name_ss << name_prefix << name_seed[i];
        std::string name = name_ss.str();
        
        speaker sp;
        sp.m_name = name;
        for(int i=0; i<2; ++i) {
            sp.m_score[i] = 0;
        }

        v1.emplace_back(i+10001);
        m_speakers.insert({i+10001, std::move(sp)});
    }
}

void speech_manager::start_speech() {
    // 第一轮比赛
    // 1.抽签
    speech_draw();
    // 2.比赛
    speech_contest();
    // 3.显示晋级结果
    show_score();

    // 4.第二轮比赛
    ++m_index;
    // 5.抽签
    speech_draw();
    // 6.比赛
    speech_contest();
    // 7.显示最终结果
    show_score();
    // 保存分数
    save_record();

    std::cout << "本届比赛完毕" << std::endl;

    // 重新初始化比赛
    init_speech();
    create_speaker();
    // 比赛完成之后,往届记录列表更新
    load_record();
    Funcs::pause();
    Funcs::clear();
}

void speech_manager::speech_contest() {
    std::cout << "---------第 " << m_index << " 轮比赛正式开始: ---------------" << std::endl;
    // 临时容器,保存key分数, value 选手编号
    std::multimap<double, int, std::greater<double>> group_score;
    int num = 0; // 记录人员数,6个为一组
    std::vector<int> v_src; // 比赛的人员容器

    if(m_index == 1) {
        v_src = v1;
    } else {
        v_src = v2;
    }
    for(auto&& sp_index: v_src) {
        ++num;

        // 评委打分
        std::deque<double> d;
        for(int i=0; i<10; ++i) {
            double score = (rand()%401 + 600)/ 10.0f; // 60 - 100
            d.emplace_back(std::move(score));
        }

        std::sort(d.begin(), d.end(), std::greater<double>());
        d.pop_front(); // 去掉最高分
        d.pop_back(); //去掉最低分

        double sum = std::accumulate(d.begin(), d.end(), 0.0f);
        double avg = sum/(double)(d.size()); 
        m_speakers[sp_index].m_score[m_index-1] = avg;
        // 6人一组,用临时容器保存
        group_score.insert({avg, sp_index});
        if(num % 6==0) {
            std::cout << "第 " << num / 6 << "小组比赛名次" << std::endl;
            int count = 0;
            for(auto&& score_index: group_score) {
                if(count < 3) {
                    if(m_index == 1) {
                        v2.emplace_back(score_index.second);
                    } else {
                        v_victory.emplace_back(score_index.second);
                    }
                }
                std::cout << "编号: " << score_index.second << " 姓名: " << m_speakers[score_index.second].m_name << " 成绩: " << m_speakers[score_index.second].m_score[m_index-1] << std::endl;
                ++count;
            }

            group_score.clear();
            std::cout << std::endl;
        }
    }

    std::cout << "---------第 " << m_index << " 轮比赛完毕: ---------------" << std::endl;
    Funcs::pause();
}

void speech_manager::speech_draw() {
    std::cout << "第 << " << m_index << " >> 轮比赛选手正在抽签" << std::endl;
    std::cout << "--------------------------------" << std::endl;
    std::cout << "抽签后演讲顺序如下: " << std::endl;

    unsigned int seed = std::chrono::system_clock::now().time_since_epoch().count();
    if(m_index == 1) {
        std::shuffle(v1.begin(), v1.end(), std::default_random_engine(seed));

        for(auto&& sp_index: v1) {
            std::cout << sp_index << " ";
        }
        std::cout << std::endl;
    } else {
        std::shuffle(v2.begin(), v2.end(), std::default_random_engine(seed));
        for(auto&& sp_index: v2) {
            std::cout << sp_index << " ";
        }
        std::cout << std::endl;
    }
    std::cout << "--------------------------------" << std::endl;
    Funcs::pause();
}

void speech_manager::show_score() {
    std::cout << "----------第" << m_index << "轮晋级选手信息如下: -------------" << std::endl;
    std::vector<int> v;
    if(m_index == 1) {
        v = v2;
    }else {
        v = v_victory;
    }

    for(auto&& speech_index: v) {
         std::cout << "选手编号: " << speech_index << " 选手姓名: " << m_speakers[speech_index].m_name << " 得分: "
            << m_speakers[speech_index].m_score[m_index-1] << std::endl;
    }

    std::cout << std::endl;
    Funcs::pause();
    Funcs::clear();
}

void speech_manager::save_record() {
    std::ofstream ofs;
    ofs.open("speech.csv", std::ios::out | std::ios::app);
    for(auto&& speech_index: v_victory) {
        ofs << speech_index << "," << m_speakers[speech_index].m_score[1] << ",";
    }
    ofs << std::endl;
    ofs.close();
    std::cout << "记录已经保存" << std::endl;
    m_file_empty = false;
}

void speech_manager::load_record() {
    std::ifstream ifs {"speech.csv", std::ios::in};
    if(!ifs.is_open()) {
        m_file_empty = true;
        std::cout << "往届记录文件不存在" << std::endl;
        ifs.close();
        return;
    }

    char ch;
    ifs >> ch;
    if(ifs.eof()) {
        std::cout << "文件为空" << std::endl;
        m_file_empty = true;
        ifs.close();
        return;
    }

    m_file_empty = false;
    // 刚才读的那个字符放回去
    ifs.putback(ch);

    std::string line;
    int index = 0;
    while(ifs >> line) {
        std::vector<std::string> v{};
        pystring::split(line, v, ",");
        m_record.insert({index, v});
        ++index;
    }
    ifs.close();
}

void speech_manager::show_record() {

    if(m_file_empty) {
        std::cout << "文件不存在,或记录为空" << std::endl;
        return;
    }

    for(int i=0; i<m_record.size(); ++i) {
        std::cout << "第" << i+1 << "届 "
            << "冠军编号: " << m_record[i][0] << " 得分: " << m_record[i][1] 
            << " 亚军编号: " << m_record[i][2] << " 得分: " << m_record[i][3]
            << " 季军编号: " << m_record[i][4] << " 得分: " << m_record[i][5]
            << std::endl;
    }
    Funcs::pause();
    Funcs::clear(); 
}

void speech_manager::clear_record() {
    std::cout << "确认清空?" << std::endl;
    std::cout << "1.确认" << std::endl;
    std::cout << "2.返回" << std::endl;
    int select;
    std::cin >> select;
    // 选择确认清空
    if(select == 1) {
        std::ofstream ofs {"speech.csv", std::ios::trunc};
        ofs.close();
        init_speech();
        create_speaker();
        load_record();
        std::cout << "清空成功" << std::endl;
    }
    Funcs::pause();
    Funcs::clear();
}

include/utils/funcs.h

#ifndef _FREDIRC_FUNCS_H_
#define _FREDIRC_FUNCS_H_

namespace Funcs {
    void pause();
    void clear();
};

#endif

impl/utils/funcs.cpp

#include "utils/funcs.h"

#include <iostream>

void Funcs::pause() {
#ifdef WINDOWS
    (void)std::system("pause");
#else
    (void)std::system("read");
#endif
}

void Funcs::clear() {
#ifdef WINDOWS
    (void)std::system("cls");
#else
    (void)std::system("clear");
#endif
}

include/beans/speaker.h

#ifndef _FREDRIC_SPEAKER_H_
#define _FREDRIC_SPEAKER_H_

#include <string>

struct speaker {    
    std::string m_name;
    double m_score[2];
};

#endif

程序运行的效果如下,


image.png

相关文章

网友评论

      本文标题:C++ STL容器实现简单的演讲比赛系统

      本文链接:https://www.haomeiwen.com/subject/mrubtrtx.html