STL经典案例(三)——俺是歌手挑战赛管理系统(涉及的STL内容较多,篇幅有点长,耐心看完,相信我,一定会有收获的!)

news2024/11/16 17:39:42

一、需求:俺是歌手挑战赛比赛规则如下

  • 目前共计12名选手报名参赛,选手编号为1-12号
  • 比赛分为A和B两组,每组6人,选手随机抽签进行分组
  • 比赛共两轮赛事,第一轮为淘汰赛,第二轮为决赛,淘汰赛中每组前三名晋级下一轮,决赛按最终得分诞生冠亚季军
  • 十个评委进行打分,最终得分为去掉一个最高分和一个最低分之后的平均分
  • 每轮赛事结束后都要显示晋级的选手信息及其得分
  • 将每赛季的冠亚季军的最终得分信息进行保存

在这里插入图片描述

二、大致思路

1,创建管理类和选手类
管理类:由于实现比赛的具体流程,成员属性为所有参赛选手容器、第一轮晋级的选手容器、进入决胜局的选手容器、选手编号和具体对应的选手容器(用于根据选手编号来找到具体的选手信息)
选手类:用于创建选手,成员属性为姓名和成绩,其中成绩为数组存放比赛的成绩
2,开始比赛
第一轮比赛:抽签、比赛、显示晋级结果
第二轮比赛:抽签、比赛、显示最终结果、保存冠亚季军信息(选手编号和最终得分)
3,查看记录
读取记录、查看记录
4,清空记录

在这里插入图片描述
看完这张图大概就知道该项目的框架了
主函数中通过switch case语句共四个功能:开始比赛、查看记录、清空记录、退出系统
项目共涉及到两个类,选手类(Player)和管理类(manager)
管理类中核心是开始比赛函数(startCompetition()),其负责调用各个模块函数进行拼接实现

三、具体步骤实现

1,新建C++空项目

在这里插入图片描述

2,创建管理类

管理类主要负责界面的交互和比赛的全部流程
创建管理类:Manager.hManager.cpp

①目前项目大致结构

在这里插入图片描述

②Manager.h

构造函数、析构函数、界面显示用户交互函数show_Menu()定义

#pragma once
class Manager 
{
public:
	Manager();//构造函数声明,并需要在类外进行实现,空实现就行

	void show_Menu();//用于用户的页面交互显示函数
	//后续添加函数均由此处开始添加
	
	~Manager();//析构函数,并需要在类外进行实现,空实现就行
};

③Manager.cpp

界面显示用户交互函数show_Menu()实现

#include "Manager.h"
#include <iostream>

void 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;
	std::cout << std::endl;
}

//后续对应头文件函数的实现均有此处进行添加

Manager::Manager() //构造函数空实现
{

}

Manager::~Manager() //析构函数空实现
{

}

④main.cpp

调用Manager管理类的界面显示用户交互函数show_Menu()

#include "Manager.h"
#include <iostream>

int main(int argc, char* agrv[])
{
	Manager manager;//所有的功能都放在Manager类中
	manager.show_Menu();
	
	system("pause");
	
	return 0;
}

⑤运行效果

在这里插入图片描述

3,比赛系统框架搭建

①Manager.h

新添加退出系统函数exit_System()声明

	void exit_System();//退出系统

②Manager.cpp

退出系统函数exit_System()实现

void Manager::exit_System() 
{
	std::cout << "Welcome to next use! Bye~" << std::endl;
	system("pause");
	exit(0); //退出系统
}

③main.cpp

通过swith case获取用户的输入,进入对应选择的功能
将退出系统函数exit_System()放在case0分支下
调用Manager管理类的退出系统函数exit_System()

#include "Manager.h"
#include <iostream>

int main(int argc, char* agrv[])
{
	Manager manager;
	int selection = 0;//接受用户的选择

	while (true) 
	{
		manager.show_Menu(); //显示菜单

		std::cout << "Please input your selection:" << std::endl;
		std::cin >> selection;

		switch (selection)
		{
		case 1: //开始比赛
			break;
		case 2: //查看记录
			break;
		case 3: //清空记录
			break;
		case 0: // 退出系统
			manager.exit_System();//调用管理类中的退出系统函数
			break;
		default: //按下其他键
			system("cls"); //清屏
			break;
		}
	}

	system("pause");
	return 0;
}

④运行效果

在这里插入图片描述

4,创建选手类

①目前项目大致结构

这里不需要实现,只需一个类就行,故定义选手类Player
在这里插入图片描述

②Player.h

选手类中成员属性为姓名和每轮比赛的得分,成员方法为对应的set和get方法
选手信息包括选手姓名每轮比赛的最终得分(共两轮比赛)

#pragma once
#include <iostream>
#include <string>
class Player
{
public:
	std::string getName() //拿到选手姓名
	{
		return this->name_;
	}
	double* getScores() //拿到最终得分
	{
		return this->scores_;
	}
	void setName(std::string name) //设置选手姓名
	{
		this->name_ = name;
	}
	void setScores(double arr[]) //给选手打分
	{
		this->scores_[0] = arr[0];
		this->scores_[1] = arr[1];
	}

private:
	std::string name_; //选手姓名
	double scores_[2]; //两轮成绩
};

5,管理类中添加成员属性和成员方法

①Manager.h

添加管理类的成员属性:进入淘汰赛、半决赛、总决赛比赛的选手容器、比赛回合、选手编号和选手信息绑定容器
添加管理类的成员方法:比赛初始化函数initCompetition()声明

	std::vector<int> v_knockout;  //存放第一轮淘汰比赛的选手的id编号 12人
	std::vector<int> v_semifinal; //存放进入第二轮半决赛的选手的id编号 6人
	std::vector<int> v_finals;    //存放进入第三轮总决赛的选手的id编号 3人

	std::map<int, Player> id_player; //选手编号和选手信息绑定

	int round_; //比赛轮数

	void initCompetition(); //比赛初始化

①Manager.cpp

管理类的成员方法:比赛初始化函数initCompetition()实现,并在构造函数中进行调用比赛初始化函数

void Manager::initCompetition() // 比赛初始化函数
{
	this->v_knockout.clear();//第一轮淘汰比赛的选手的id编号清空
	this->v_semifinal.clear();//进入第二轮半决赛的选手的id编号清空
	this->v_finals.clear();//存放进入第三轮总决赛的选手的id编号清空
	this->id_player.clear();//编号id和选手信息绑定容器清空
	this->round_ = 1;//第一回合
}

6,管理类中添加成员方法——添加选手

①Manager.h

创建选手函数createPlayer()声明

	void createPlayer(); //创建比赛选手

②Manager.cpp

创建选手函数createPlayer()实现
选手姓名为A-L共十二位,成绩初始化都为0,将编号id和选手信息进行绑定,并将编号id(1-12)放入淘汰比赛的选手的id编号容器中(v_knockout),在构造函数中进行调用创建选手函数

void Manager::createPlayer() //创建比赛选手
{
	std::string nameList = "ABCDEFGHIJKL"; //十二个选手name分别为A、B...
	for (int i = 0; i < nameList.size(); i++) 
	{
		std::string name = "Player";
		name += nameList[i];

		Player player;
		player.setName(name); //初始化设置参赛选手的姓名
		for (int j = 0; j < 2; j++) 
		{
			double arr[2] = { 0,0 }; //初始化设置参赛选手的每轮比赛得分
			player.setScores(arr);
		}

		this->v_knockout.push_back(i+1);//v_knockout为淘汰赛参加的12名选手,给选手编号赋值1-12
		
		//每个map中存放key为id,value为选手信息
		this->id_player.insert(std::make_pair(i+1, player));//编号分别为1,2,...,11,12
	}
}

③main.cpp

调用测试函数show_id_palyer_info(),用于显示id和player信息绑定是否成功
测试完之后没问题即可注释掉show_id_palyer_info(manager.id_player);

#include "Manager.h"
#include <iostream>
#include<iomanip>

void show_id_palyer_info(std::map<int, Player> id_palyer) //显示id和player信息绑定是否成功
{
	//std::setw(2) << std::setfill('0')为了将个位数的id补为两位,比如01,02,03...
	for (std::map<int, Player>::iterator it = id_palyer.begin(); it != id_palyer.end(); it++)
	{
		std::cout << "Player id is: " <<std::setw(2) << std::setfill('0') << (*it).first
			<< " ,name is: " << it->second.getName()
			<< " ,round 1 scores is: " << it->second.getScores()[0]
			<< " ,round 2 scores is: " << it->second.getScores()[1]
			<< std::endl;
	}
}

int main(int argc, char* agrv[])
{
	Manager manager;
	int selection = 0;//接受用户的选择

	//测试一下id和player信息绑定是否成功
	show_id_palyer_info(manager.id_player);

	while (true) 
	{
		manager.show_Menu(); //显示菜单
		
		std::cout << "Please input your selection:" << std::endl;
		std::cin >> selection;

		switch (selection)
		{
		case 1: //开始比赛
			break;
		case 2: //查看记录
			break;
		case 3: //清空记录
			break;
		case 0: // 退出系统
			manager.exit_System();//调用管理类中的退出系统函数
			break;
		default: //按下其他键
			system("cls"); //清屏
			break;
		}
	}

	system("pause");

	return 0;
}

④运行效果

在这里插入图片描述

7,管理类中添加流程控制函数——startCompetition()

startCompetition()开始比赛这个成员方法流程:
第一轮比赛:抽签、比赛、显示晋级结果
第二轮比赛:抽签、比赛、显示最终结果、保存分数
因为第二轮比赛完了之后就全部结束了
每个过程都用一个独立的函数进行实现

Ⅰ抽签功能

这一步完成开始比赛startCompetition()中的比赛抽签功能competitionDraw()
比赛抽签思路:第一回合(淘汰赛)12名参赛选手比赛id编号依次为1-12,先随机抽取,然后前6个为A组,后6位选手为B组进行抽签

①Manager.h

开始比赛成员方法startCompetition()声明

	void startCompetition();//开始比赛
	void competitionDraw(); //比赛抽签
②Manager.cpp

startCompetition()开始比赛成员方法具体实现,这里列了下框架结构,具体的每个步骤均由每个函数进行实现

void Manager::startCompetition() //开始比赛成员方法实现
{
	//第一轮比赛
	//1、抽签
	this->competitionDraw();
	//2、比赛

	//3、显示晋级结果

	//第二轮比赛

	//1、抽签

	//2、比赛

	//3、显示最终结果

	//4、保存分数
}

void Manager::competitionDraw() 
{
	std::cout << "Rounds :" << this->round_ << " ,player is drawing..." << std::endl;
	std::cout << "The order of the draw is as follows: " << std::endl;

	if (this->round_ == 1) // 第一轮淘汰赛,参赛12人,分两组,每组前三晋级
	{
		std::random_shuffle(v_knockout.begin(), v_knockout.end()); //第一轮比赛的参赛选手容器为v_knockout
		
		std::vector<int>::iterator it_a, it_m, it_b;
		it_a = v_knockout.begin();
		it_m = v_knockout.begin();
		it_b = v_knockout.end();
		int m = v_knockout.size()/2; //6

		
		for (it_a = v_knockout.begin(); it_a != v_knockout.end(); it_a++)
		{
			std::cout << (*it_a) << " ";
		}
		std::cout << std::endl;
		std::cout << "-----------------------------" << std::endl;

		while (m--) 
		{
			it_m++;
		}
		std::cout << "A group is: " << std::endl;
		for (it_a = v_knockout.begin(); it_a != it_m; it_a++) 
		{
			std::cout << (*it_a) << " ";
		}
		std::cout << std::endl;
		std::cout << "B group is: " << std::endl;
		for (it_b = it_m; it_b != v_knockout.end(); it_b++)
		{
			std::cout << (*it_b) << " ";
		}
		std::cout << std::endl;
		
	}
	else // 第二轮半决赛,参赛6人,前三晋级
	{
		std::random_shuffle(v_semifinal.begin(), v_semifinal.end());//目前半决赛还没有加入选手,因为淘汰赛还没有开始进行
		for (std::vector<int>::iterator it = v_semifinal.begin(); it != v_semifinal.end(); it++) 
		{
			std::cout<<"(*it)"<<std::endl;
		}
		std::cout << std::endl;
	}
	system("pause");
	std::cout << std::endl;
}
③main.cpp

开始比赛成员方法startCompetition()放在主函数中的case1分支下

#include "Manager.h"
#include <iostream>
#include<iomanip>

void show_id_palyer_info(std::map<int, Player> id_palyer) //显示id和player信息绑定是否成功
{
	//std::setw(2) << std::setfill('0')为了将个位数的id补为两位,比如01,02,03...
	for (std::map<int, Player>::iterator it = id_palyer.begin(); it != id_palyer.end(); it++)
	{
		std::cout << "Player id is: " <<std::setw(2) << std::setfill('0') << (*it).first
			<< " ,name is: " << it->second.getName()
			<< " ,round 1 scores is: " << it->second.getScores()[0]
			<< " ,round 2 scores is: " << it->second.getScores()[1]
			<< std::endl;
	}
}

int main(int argc, char* agrv[])
{
	Manager manager;
	int selection = 0;//接受用户的选择

	//测试一下id和player信息绑定是否成功
	//show_id_palyer_info(manager.id_player);

	while (true) 
	{
		manager.show_Menu(); //显示菜单
		
		std::cout << "Please input your selection:" << std::endl;
		std::cin >> selection;

		switch (selection)
		{
		case 1: //开始比赛
			manager.startCompetition(); //调用开始比赛成员方法
			break;
		case 2: //查看记录
			break;
		case 3: //清空记录
			break;
		case 0: // 退出系统
			manager.exit_System();//调用管理类中的退出系统函数
			break;
		default: //按下其他键
			system("cls"); //清屏
			break;
		}
	}

	system("pause");

	return 0;
}
④运行效果

在这里插入图片描述

Ⅱ比赛功能

上一步完成了选手比赛抽签功能competitionDraw()

接下来开始实现比赛功能competitionContest()
比赛主要是十位评委对选手进行打分,去掉一个最低分和最高分求解平均分为选项最终成绩
可以参考博文:STL经典案例(一)——评委打分

①Manager.h

开始比赛函数competitionContest()声明

	void competitionContest(); //开始比赛
②Manager.cpp

比赛开始函数competitionContest()实现

void Manager::competitionContest() //开始比赛函数实现
{
	std::cout << "The round is: " << this->round_ << " starting----------------------" << std::endl;


	//存放临时容器,存放分组后的每个小组成员的成绩,double为每个人的最终得分,int为选手的id编号
	std::multimap<double, int, std::greater<int>>groupScore;//内建函数std::greater<int>,从大到小排序

	int groupnumber = 0;

	std::vector <int>v_competitor;//实际的参赛选手容器
	if (this->round_ == 1)//淘汰赛每组的前三名晋级 
	{
		v_competitor = v_knockout;//淘汰赛
	}
	else 
	{
		v_competitor = v_semifinal;//半决赛
	}

	for (std::vector<int>::iterator it = v_competitor.begin(); it != v_competitor.end(); it++) //遍历选手,评委打分,这里的it为选手的id编号
	{
		groupnumber++;//小组成员自增

		//使用双端数组deque接收十位评委打分,到时候排完序直接可以去除最高分和最低分
		std::deque<double> scores;
		for (int i = 0; i < 10; i++) 
		{
			double score = (rand() % 401 + 600) / 10.f;//rand() % 401 == [0,401)
			scores.push_back(score); 
			//std::cout << score << " ";//查看十位评委给选手的具体打分情况
		}
		//std::cout << std::endl;

		sort(scores.begin(), scores.end(), std::greater<double>());//降序排列,内建函数greater从大到小排序

		scores.pop_front();//去除最高分
		scores.pop_back();//去除最低分

		double score_sum = std::accumulate(scores.begin(), scores.end(), 0.0f);//容器内所有的值进行累加
		double score_avg = score_sum / (double)scores.size();//平均分

		//测试输出一下平均分
		/*
		std::cout << "Player id is: " << *it
			<< " ,name is: " << this->id_player[*it].getName()
			<< " ,aver is: " << score_avg;
        */

		//把平均分放入到map容器id_player中,按id编号得到选手信息,然后再放入到选手信息中的得分数组里即可
		double arr[2] = {0};
		int i = this->round_ - 1;
		arr[i] = score_avg;
		this->id_player[*it].setScores(arr);

		//将每个选手的最终得分存放到临时小组容器中
		groupScore.insert(std::make_pair(score_avg, *it));//key为最终成绩,value为选手的id编号

		//每个小组取出最终得分前三名
		if (groupnumber % 6 == 0)
		{
			if (groupnumber == 6 && this->round_==1)std::cout << "Group A Ranking is :" << std::endl;
			if (groupnumber == 12 && this->round_ == 1)std::cout << "Group B Ranking is :" << std::endl;
			if (groupnumber == 6 && this->round_ == 2)std::cout << "Outstanding Group Ranking is :" << std::endl;

			for (std::multimap<double, int, std::greater<double>>::iterator it = groupScore.begin(); it != groupScore.end(); it++) 
			{
				std::cout << "Player id is: " << it->second
					<< " ,name is: " << this->id_player[it->second].getName()
					<< " ,score is: " << this->id_player[it->second].getScores()[this->round_ - 1]
					<< std::endl;
			}

			//获取每组的前三名,晋级
			int count = 0;
			for (std::multimap<double, int, std::greater<double>>::iterator it = groupScore.begin(); it != groupScore.end(); it++)
			{
				if (count < 3) //前三名晋级
				{
					count++;
					if (this->round_ == 1)//淘汰赛晋级半决赛的选手id编号
					{
						v_semifinal.push_back((*it).second);//key为最终成绩,value为选手id编号
					}
					else //半决赛晋级决赛的选手id编号
					{
						v_finals.push_back((*it).second);//key为最终成绩,value为选手id编号
					}
				}
			}
			groupScore.clear();//小组容器清空,避免后续的追加
			std::cout << std::endl;
		}
	}
	//std::cout << std::endl;

	std::cout << "-----------------Round " << this->round_ << " is over!--------------" << std::endl;
	system("pause");
}
③运行效果

在这里插入图片描述

Ⅲ显示比赛分数功能

上一步完成了比赛功能competitionContest()
已经将十二名选手进行分组,并且每组六人,也都按最终成绩进行了排序

接下来将这每组的最终得分最高的前三名选手进行晋级并显示晋级选手的最终得分
显示比赛分数函数showScore()

①Manage.h

显示比赛分数函数showScore()声明

	void showScore(); //显示比赛结果
②Manage.cpp

显示比赛分数函数showScore()实现

void Manager::showScore() //显示得分函数
{
	std::cout << "Round " << this->round_ << " Promoted Players is: " << std::endl;
	std::vector<int> player;
	if (this->round_ == 1) //第一轮淘汰赛比赛
	{
		player = this->v_semifinal;//进入半决赛的选手名单
	}
	else 
	{
		player = this->v_finals;//进入决赛的选手名单
	}

	for (std::vector<int>::iterator it = player.begin(); it != player.end(); it++) 
	{
		std::cout << "Player id is: " << (*it) << " ,name is: " << this->id_player[*it].getName()
			<< " ,scores is: " << this->id_player[*it].getScores()[this->round_ - 1] << std::endl;
	}
	std::cout<<std::endl;
	system("pause");//按任意键继续
	system("cls");//清屏
	this->show_Menu();//重新显示一下菜单
}
③运行效果

在这里插入图片描述

Ⅳ第二轮比赛+抽签+比赛+显示比赛分数功能复用

只需要将控制比赛轮次的成员属性round_自加即可

①Manage.cpp

在流程控制函数中将比赛轮次的成员属性round_自加实现第二轮比赛
第二轮比赛和第一轮比赛一样,都是抽签competitionDraw()、比赛competitionContest()、显示晋级名单showScore()
函数复用即可

void Manager::startCompetition() //开始比赛成员方法实现
{
	//第一轮比赛
	//1、抽签
	this->competitionDraw();
	//2、比赛
	this->competitionContest();
	//3、显示晋级结果
	this->showScore();
	//第二轮比赛
	this->round_++;
	//1、抽签
	this->competitionDraw();
	//2、比赛
	this->competitionContest();
	//3、显示最终结果
	this->showScore();
	//4、保存分数
}
②运行效果

在这里插入图片描述

Ⅴ保存冠亚季军选手的信息

①Manage.h

保存冠亚季军选手的信息函数savePlayerInfo()声明

	void savePlayerInfo();//保存冠亚季军选手的信息
②Manage.cpp

保存冠亚季军选手的信息函数savePlayerInfo()实现

void Manager::savePlayerInfo() 
{
	std::ofstream ofs;
	ofs.open("./compepiption.csv", std::ios::out | std::ios::app);

	for (std::vector<int>::iterator it = v_finals.begin(); it != v_finals.end(); it++) 
	{
		ofs << (*it) << "," << id_player[*it].getScores()[1] << ",";
	}
	ofs << std::endl;
	ofs.close();
	std::cout << "Already saved! " << std::endl;
}
③运行效果

在这里插入图片描述

⑥总结

就此流程控制函数startCompetition()所包含的所有流程均已全部实现
在这里插入图片描述

8,管理类中添加查看往届比赛记录成员方法——读取冠亚季军选手信息

读取往届冠亚季军选手信息函数loadPlayerInfo()
上一步已经实现了保存冠亚季军选手的信息,现在开始读取这些信息
首先需要判断保存的文件是否存在,其次通过比赛届数与冠亚季军选手的信息通过map进行关联

①Manage.h

读取往届冠亚季军选手信息函数loadPlayerInfo()声明

	void loadPlayerInfo();//读取往届冠亚季军选手信息
	bool fileIsEmpty;//判断文件是否为空
	std::map<int, std::vector<std::string>> past_records;//存放往届记录的容器

②Manage.cpp

读取往届冠亚季军选手信息函数loadPlayerInfo()实现
因为这些是往届的比赛记录,故放在构造函数中,程序运行就执行

void Manager::loadPlayerInfo() 
{
	std::ifstream ifs("./compepiption.csv", std::ios::in);//读取文件
	
	//文件不存在,打开失败
	if (!ifs.is_open()) //打开失败
	{
		this->fileIsEmpty = true;//文件不存在,标志位设为true
		std::cout << "file is not exist!" << std::endl;
		ifs.close();
		return;
	}

	//文件存在,但文件为空
	char ch;
	ifs >> ch;//从文件中读一个字符
	if (ifs.eof()) //若文件读了一个文件后,就到结尾了
	{
		this->fileIsEmpty = true;//文件为空,标志位设为true
		std::cout << "file is empty!" << std::endl;
		ifs.close();
		return;
	}

	//重新若能走到这里,表示文件存在且不为空
	this->fileIsEmpty = false;

	ifs.putback(ch);//因为之前取出一个字符验证文件是否为空,现在就需把这个字符再读回来

	std::string info;//存放比赛记录的信息,主要是冠亚季军的编号和最终成绩六个逗号分隔的字符串,是完整的全部信息
	int index = 0;//第几届的比赛
	while (ifs >> info) 
	{
		//std::cout << info << std::endl;

		std::vector<std::string> data;
		int pos = -1;//标志位
		int start = 0;//起始位
		
		while (true) 
		{
			//数据格式:10, 86.675, 9, 81.3, 7, 78.55,
			pos = info.find(",", start);//从全部的信息中按逗号查找,从start位置开始查找
			if (pos == -1) //没找到返回pos为-1,找到了返回pos为具体的位置
			{
				break;//没找到,或者找完了
			}

			//取字符串函数substr,参数一:起始位置;参数二;截取长度
			std::string temp = info.substr(start, pos - start);//pos为逗号位置,start为起始位置,相减就是我们要分割长度

			data.push_back(temp);//将分割后的结果放入data容器中
			start = pos + 1;//查找下一个
		}
		this->past_records.insert(std::make_pair(index, data));//将比赛的届数和冠军季军亚军的信息和成绩进行绑定

		index++;//比赛届数
	}
	ifs.close();

	//小测试
	for (std::map<int, std::vector<std::string>>::iterator it = past_records.begin(); it != past_records.end(); it++) 
	{
		std::cout << "Round is: " << (*it).first+1 << " ,Champion No." << it->second[0]
			<< " ,Final Score is: " << it->second[1] << std::endl;
	}
}

Manager::Manager() //构造函数
{
	this->initCompetition(); //调用比赛初始化函数
	this->createPlayer();    //调用创建选手函数
	this->loadPlayerInfo();//加载往届比赛记录
}

③运行效果

在这里插入图片描述

9,管理类中添加查看往届比赛记录成员方法——显示冠亚季军选手信息

显示往届冠亚季军选手信息函数showPastCompetitionRecord()
上一步读取完冠亚季军选手的信息,接下来开始进行显示

①Manage.h

显示往届冠亚季军选手信息函数showPastCompetitionRecord()声明

	void showPastCompetitionRecord();//显示往届比赛记录

②Manage.cpp

显示往届冠亚季军选手信息函数showPastCompetitionRecord()实现

void Manager::showPastCompetitionRecord() //显示往届比赛记录
{
	for (int i = 0; i < this->past_records.size(); i++) //i表示第几届比赛
	{
		std::cout << "Round is: " << i + 1 << ", "
			<< "Champion No." << this->past_records[i][0] << ", Final Score is: " << this->past_records[i][1] << "; "
			<< "Runner-up No." << this->past_records[i][2] << ", Final Score is: " << this->past_records[i][3] << "; "
			<< "Third Place No." << this->past_records[i][4] << ", Final Score is: " << this->past_records[i][5] << "; "
			<< std::endl;
	}
}

③main.cpp

通过swith case获取用户的输入,进入对应选择的功能
将查看往届记录函数showPastCompetitionRecord()放在case2分支下
调用Manager管理类的查看往届记录函数showPastCompetitionRecord()

#include "Manager.h"
#include <iostream>
#include<iomanip>

void show_id_palyer_info(std::map<int, Player> id_palyer) //显示id和player信息绑定是否成功
{
	//std::setw(2) << std::setfill('0')为了将个位数的id补为两位,比如01,02,03...
	for (std::map<int, Player>::iterator it = id_palyer.begin(); it != id_palyer.end(); it++)
	{
		std::cout << "Player id is: " <<std::setw(2) << std::setfill('0') << (*it).first
			<< " ,name is: " << it->second.getName()
			<< " ,round 1 scores is: " << it->second.getScores()[0]
			<< " ,round 2 scores is: " << it->second.getScores()[1]
			<< std::endl;
	}
}

int main(int argc, char* agrv[])
{
	Manager manager;
	int selection = 0;//接受用户的选择

	//测试一下id和player信息绑定是否成功
	//show_id_palyer_info(manager.id_player);

	while (true) 
	{
		manager.show_Menu(); //显示菜单
		
		std::cout << "Please input your selection:" << std::endl;
		std::cin >> selection;

		switch (selection)
		{
		case 1: //开始比赛
			manager.startCompetition(); //调用开始比赛成员方法
			break;
		case 2: //查看记录
			manager.showPastCompetitionRecord();
			break;
		case 3: //清空记录
			break;
		case 0: // 退出系统
			manager.exit_System();//调用管理类中的退出系统函数
			break;
		default: //按下其他键
			system("cls"); //清屏
			break;
		}
	}

	system("pause");

	return 0;
}

④运行效果

在这里插入图片描述

10,清空记录功能

通过swith case获取用户的输入,进入对应选择的功能
将清空往届比赛记录函数clearPastCompetitionRecord()放在case4分支下
调用Manager管理类的清空往届比赛记录函数clearPastCompetitionRecord()

用户确认清空记录,通过truncf方式打开文件,该方式若存在则删除文件重新创建
清空记录之后还需要对容器进行初始化

②Manage.cpp

void Manager::clearPastCompetitionRecord() //清空往届比赛记录
{
	std::cout << "Are you sure you want to empty past competition record files?" << std::endl;
	std::cout << "1,Yes." << std::endl;
	std::cout << "2,No." << std::endl;

	int user_selection;
	std::cin >> user_selection;

	if (user_selection == 1) 
	{
		std::ofstream ofs("./compepiption.csv", std::ios::trunc);
		ofs.close();
		this->competitionReset();//重置初始化容器、重新创建12名选手、重新加载往届记录

		std::cout << "clear is successful" << std::endl;
	}

	system("pause");
	system("cls");
}

11,完善系统细节

Ⅰ显示冠亚季军选手信息功能——showPastCompetitionRecord()

若往届没有冠亚季军记录,则进行提示

①Manage.cpp
void Manager::showPastCompetitionRecord() //显示往届比赛记录
{
	if (this->fileIsEmpty) //若文件不存在或为空则提示用户
	{
		std::cout << "The file does not exist or the record is empty." << std::endl;
	}
	else //文件存在或不为空
	{
		for (int i = 0; i < this->past_records.size(); i++) //i表示第几届比赛
		{
			std::cout << "Round is: " << i + 1 << ", "
				<< "Champion No." << this->past_records[i][0] << ", Final Score is: " << this->past_records[i][1] << "; "
				<< "Runner-up No." << this->past_records[i][0] << ", Final Score is: " << this->past_records[i][1] << "; "
				<< "Third Place No." << this->past_records[i][0] << ", Final Score is: " << this->past_records[i][1] << "; "
				<< std::endl;
		}
	}
}
②运行效果

在这里插入图片描述

Ⅱ保存冠亚季军选手的信息——savePlayerInfo()

若刚开始比赛记录为空,保存了冠亚季军选手信息之后,需要更新文件为空的标志位

①Manage.cpp
void Manager::savePlayerInfo() 
{
	std::ofstream ofs;
	ofs.open("./compepiption.csv", std::ios::out | std::ios::app);//以追加的方式写入文件,若不存在则创建

	for (std::vector<int>::iterator it = v_finals.begin(); it != v_finals.end(); it++) 
	{
		ofs << (*it) << "," << id_player[*it].getScores()[1] << ",";
	}
	ofs << std::endl;
	ofs.close();
	std::cout << "Already saved! " << std::endl;

	this->fileIsEmpty = false;
}

Ⅲ流程控制函数——startCompetition()

比赛完之后,需要重置比赛,并且获取记录

①Manage.h
void competitionReset();//重置比赛
②Manage.cpp
void Manager::competitionReset() 
{
	//重置比赛,获取记录
	this->initCompetition();//初始化容器
	this->createPlayer();//重新创建12名参赛选手
	this->loadPlayerInfo();//加载往届的比赛记录
}

Ⅳ初始化时需要初始化往届比赛记录容器——initCompetition()

初始化的时候需要清空之前的比赛记录容器

①Manage.cpp
void Manager::initCompetition() // 比赛初始化函数
{
	this->v_knockout.clear();//第一轮淘汰比赛的选手的id编号清空
	this->v_semifinal.clear();//进入第二轮半决赛的选手的id编号清空
	this->v_finals.clear();//存放进入第三轮总决赛的选手的id编号清空
	this->id_player.clear();//编号id和选手信息绑定容器清空
	this->round_ = 1;//第一回合

	this->past_records.clear();//往届比赛记录容器初始化
}

在开始比赛(startCompetition())中进行调用

void Manager::startCompetition() //开始比赛成员方法实现
{
	//第一轮比赛
	//1、抽签
	this->competitionDraw();
	//2、比赛
	this->competitionContest();
	//3、显示晋级结果
	this->showScore();
	//第二轮比赛
	this->round_++;
	//1、抽签
	this->competitionDraw();
	//2、比赛
	this->competitionContest();
	//3、显示最终结果
	this->showScore();
	//4、保存分数
	this->savePlayerInfo();

	this->competitionReset();//重新初始化

	std::cout << "Completion of the session!" << std::endl;
	system("pause");
	system("cls");
}

Ⅴ添加随机数种子——main.cpp

头文件:#include <ctime>
主函数最前面添加:std::srand((unsigned int)time(NULL));

四、完整项目

完整项目结构:
在这里插入图片描述

1,选手类——Player.h

#pragma once
#include <iostream>
#include <string>
class Player
{
public:
	std::string getName() //拿到选手姓名
	{
		return this->name_;
	}
	double* getScores() //拿到最终得分
	{
		return this->scores_;
	}
	void setName(std::string name) //设置选手姓名
	{
		this->name_ = name;
	}
	void setScores(double arr[]) //给选手打分
	{
		this->scores_[0] = arr[0];
		this->scores_[1] = arr[1];
	}

private:
	std::string name_; //选手姓名
	double scores_[2]; //两轮成绩
};

2,管理类——Manager.h

#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <deque>
#include <algorithm>//sort排序算法
#include <functional>//内建函数greater从大到小排序,用于sort排序算法指定排序规则
#include <numeric>//容器求和函数accumulate
#include <fstream>
#include "Player.h"

class Manager 
{
public:
	Manager();//构造函数

	void show_Menu();//用于用户的页面交互显示函数
	void exit_System();//退出系统

	std::vector<int> v_knockout;  //存放第一轮淘汰比赛的选手的id编号 12人
	std::vector<int> v_semifinal; //存放进入第二轮半决赛的选手的id编号 6人
	std::vector<int> v_finals;    //存放进入第三轮总决赛的选手的id编号 3人

	std::map<int, Player> id_player; //选手编号和选手信息绑定

	int round_ = 1; //比赛轮数

	void initCompetition(); //比赛初始化
	void createPlayer(); //创建比赛选手
	void startCompetition();//开始比赛

	void competitionDraw(); //比赛抽签
	void competitionContest(); //开始比赛
	void showScore(); //显示比赛结果
	void savePlayerInfo();//保存冠亚季军选手的信息

	void loadPlayerInfo();//读取往届冠亚季军选手信息
	bool fileIsEmpty;//判断文件是否为空
	std::map<int, std::vector<std::string>> past_records;//存放往届记录的容器

	void showPastCompetitionRecord();//显示往届比赛记录
	void competitionReset();//重置比赛

	void clearPastCompetitionRecord();//清空往届比赛记录

	~Manager();//析构函数
};

3,管理类实现——Manager.cpp

#include "Manager.h"
#include <iostream>


void 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;
	std::cout << std::endl;
}

void Manager::exit_System() 
{
	std::cout << "Welcome to next use! Bye~" << std::endl;
	system("pause");
	exit(0); //退出系统
}

void Manager::initCompetition() // 比赛初始化函数
{
	this->v_knockout.clear();//第一轮淘汰比赛的选手的id编号清空
	this->v_semifinal.clear();//进入第二轮半决赛的选手的id编号清空
	this->v_finals.clear();//存放进入第三轮总决赛的选手的id编号清空
	this->id_player.clear();//编号id和选手信息绑定容器清空
	this->round_ = 1;//第一回合

	this->past_records.clear();//往届比赛记录容器初始化
}

void Manager::createPlayer() //创建比赛选手
{
	std::string nameList = "ABCDEFGHIJKL"; //十二个选手name分别为A、B、C、D...
	for (int i = 0; i < nameList.size(); i++) 
	{
		std::string name = "Player";
		name += nameList[i];

		Player player;
		player.setName(name); //初始化设置参赛选手的姓名
		for (int j = 0; j < 2; j++) 
		{
			double arr[2] = { 0,0 }; //初始化设置参赛选手的每轮比赛得分
			player.setScores(arr);
		}

		this->v_knockout.push_back(i+1);//v_knockout为淘汰赛参加的12名选手,给选手编号赋值1-12

		//每个map中存放key为id,value为选手信息
		this->id_player.insert(std::make_pair(i+1, player));//编号分别为1,2,...,11,12

	}
}

void Manager::startCompetition() //开始比赛成员方法实现
{
	//第一轮比赛
	//1、抽签
	this->competitionDraw();
	//2、比赛
	this->competitionContest();
	//3、显示晋级结果
	this->showScore();
	//第二轮比赛
	this->round_++;
	//1、抽签
	this->competitionDraw();
	//2、比赛
	this->competitionContest();
	//3、显示最终结果
	this->showScore();
	//4、保存分数
	this->savePlayerInfo();

	this->competitionReset();//重新初始化

	std::cout << "Completion of the session!" << std::endl;
	system("pause");
	system("cls");
}

void Manager::competitionReset() 
{
	//重置比赛,获取记录
	this->initCompetition();//初始化容器
	this->createPlayer();//重新创建12名参赛选手
	this->loadPlayerInfo();//加载往届的比赛记录
}

void Manager::competitionDraw() 
{
	std::cout << "Rounds :" << this->round_ << " ,player is drawing..." << std::endl;
	std::cout << "The order of the draw is as follows: " << std::endl;

	if (this->round_ == 1) // 第一轮淘汰赛,参赛12人,分两组,每组前三晋级
	{
		std::random_shuffle(v_knockout.begin(), v_knockout.end()); //第一轮比赛的参赛选手容器为v_knockout
		
		std::vector<int>::iterator it_a, it_m, it_b;
		it_a = v_knockout.begin();
		it_m = v_knockout.begin();
		it_b = v_knockout.end();
		int m = v_knockout.size()/2; //6

		
		for (it_a = v_knockout.begin(); it_a != v_knockout.end(); it_a++)
		{
			std::cout << (*it_a) << " ";
		}
		std::cout << std::endl;
		std::cout << "-----------------------------" << std::endl;

		while (m--) 
		{
			it_m++;
		}
		std::cout << "A group is: " << std::endl;
		for (it_a = v_knockout.begin(); it_a != it_m; it_a++) 
		{
			std::cout << (*it_a) << " ";
		}
		std::cout << std::endl;
		std::cout << "B group is: " << std::endl;
		for (it_b = it_m; it_b != v_knockout.end(); it_b++)
		{
			std::cout << (*it_b) << " ";
		}
		std::cout << std::endl;
		
	}
	else // 第二轮半决赛,参赛6人,前三晋级
	{
		std::random_shuffle(v_semifinal.begin(), v_semifinal.end());//目前半决赛还没有加入选手,因为淘汰赛还没有开始进行
		for (std::vector<int>::iterator it = v_semifinal.begin(); it != v_semifinal.end(); it++) 
		{
			std::cout << (*it) << " ";
		}
		std::cout << std::endl;
	}
	system("pause");
	std::cout << std::endl;
}

void Manager::competitionContest() //开始比赛函数实现
{
	std::cout << "The round is: " << this->round_ << " starting----------------------" << std::endl;


	//存放临时容器,存放分组后的每个小组成员的成绩,double为每个人的最终得分,int为选手的id编号
	std::multimap<double, int, std::greater<int>>groupScore;//内建函数std::greater<int>,从大到小排序

	int groupnumber = 0;

	std::vector <int>v_competitor;//实际的参赛选手容器
	if (this->round_ == 1)//淘汰赛每组的前三名晋级 
	{
		v_competitor = v_knockout;//淘汰赛
	}
	else 
	{
		v_competitor = v_semifinal;//半决赛
	}

	for (std::vector<int>::iterator it = v_competitor.begin(); it != v_competitor.end(); it++) //遍历选手,评委打分,这里的it为选手的id编号
	{
		groupnumber++;//小组成员自增

		//使用双端数组deque接收十位评委打分,到时候排完序直接可以去除最高分和最低分
		std::deque<double> scores;
		for (int i = 0; i < 10; i++) 
		{
			double score = (rand() % 401 + 600) / 10.f;//rand() % 401 == [0,401)
			scores.push_back(score); 
			//std::cout << score << " ";//查看十位评委给选手的具体打分情况
		}
		//std::cout << std::endl;

		sort(scores.begin(), scores.end(), std::greater<double>());//降序排列,内建函数greater从大到小排序

		scores.pop_front();//去除最高分
		scores.pop_back();//去除最低分

		double score_sum = std::accumulate(scores.begin(), scores.end(), 0.0f);//容器内所有的值进行累加
		double score_avg = score_sum / (double)scores.size();//平均分

		//测试输出一下平均分
		/*
		std::cout << "Player id is: " << *it
			<< " ,name is: " << this->id_player[*it].getName()
			<< " ,aver is: " << score_avg;
        */

		//把平均分放入到map容器id_player中,按id编号得到选手信息,然后再放入到选手信息中的得分数组里即可
		double arr[2] = {0};
		arr[this->round_ - 1] = score_avg;
		this->id_player[*it].setScores(arr);

		//将每个选手的最终得分存放到临时小组容器中
		groupScore.insert(std::make_pair(score_avg, *it));//key为最终成绩,value为选手的id编号

		//每个小组取出最终得分前三名
		if (groupnumber % 6 == 0)
		{
			if (groupnumber == 6)std::cout << "Group A Ranking is :" << std::endl;
			if (groupnumber == 12)std::cout << "Group B Ranking is :" << std::endl;

			for (std::multimap<double, int, std::greater<double>>::iterator it = groupScore.begin(); it != groupScore.end(); it++) 
			{
				std::cout << "Player id is: " << it->second
					<< " ,name is: " << this->id_player[it->second].getName()
					<< " ,score is: " << this->id_player[it->second].getScores()[this->round_ - 1]
					<< std::endl;
			}

			//获取每组的前三名,晋级
			int count = 0;
			for (std::multimap<double, int, std::greater<double>>::iterator it = groupScore.begin(); it != groupScore.end(); it++)
			{
				if (count < 3) //前三名晋级
				{
					count++;
					if (this->round_ == 1)//淘汰赛晋级半决赛的选手id编号
					{
						v_semifinal.push_back((*it).second);//key为最终成绩,value为选手id编号
					}
					else //半决赛晋级决赛的选手id编号
					{
						v_finals.push_back((*it).second);//key为最终成绩,value为选手id编号
					}
				}
			}
			groupScore.clear();//小组容器清空,避免后续的追加
			std::cout << std::endl;
		}
	}
	//std::cout << std::endl;

	std::cout << "-----------------Round " << this->round_ << " is over!--------------" << std::endl;
	system("pause");
}

void Manager::showScore() //显示得分函数
{
	std::cout << "Round " << this->round_ << " Promoted Players is: " << std::endl;
	std::vector<int> player;
	if (this->round_ == 1) //第一轮淘汰赛比赛
	{
		player = this->v_semifinal;//进入半决赛的选手名单
	}
	else 
	{
		player = this->v_finals;//进入决赛的选手名单
	}

	for (std::vector<int>::iterator it = player.begin(); it != player.end(); it++) 
	{
		std::cout << "Player id is: " << (*it) << " ,name is: " << this->id_player[*it].getName()
			<< " ,scores is: " << this->id_player[*it].getScores()[this->round_ - 1] << std::endl;
	}
	std::cout<<std::endl;
	system("pause");//按任意键继续
	system("cls");//清屏
	this->show_Menu();//重新显示一下菜单
}

void Manager::savePlayerInfo() 
{
	std::ofstream ofs;
	ofs.open("./compepiption.csv", std::ios::out | std::ios::app);//以追加的方式写入文件,若不存在则创建

	for (std::vector<int>::iterator it = v_finals.begin(); it != v_finals.end(); it++) 
	{
		ofs << (*it) << "," << id_player[*it].getScores()[1] << ",";
	}
	ofs << std::endl;
	ofs.close();
	std::cout << "Already saved! " << std::endl;

	this->fileIsEmpty = false;
}


void Manager::loadPlayerInfo() 
{
	std::ifstream ifs("./compepiption.csv", std::ios::in);//读取文件
	
	//文件不存在,打开失败
	if (!ifs.is_open()) //打开失败
	{
		this->fileIsEmpty = true;//文件不存在,标志位设为true
		//std::cout << "file is not exist!" << std::endl;
		ifs.close();
		return;
	}

	//文件存在,但文件为空
	char ch;
	ifs >> ch;//从文件中读一个字符
	if (ifs.eof()) //若文件读了一个文件后,就到结尾了
	{
		this->fileIsEmpty = true;//文件为空,标志位设为true
		//std::cout << "file is empty!" << std::endl;
		ifs.close();
		return;
	}

	//重新若能走到这里,表示文件存在且不为空
	this->fileIsEmpty = false;

	ifs.putback(ch);//因为之前取出一个字符验证文件是否为空,现在就需把这个字符再读回来

	std::string info;//存放比赛记录的信息,主要是冠亚季军的编号和最终成绩六个逗号分隔的字符串,是完整的全部信息
	int index = 0;//第几届的比赛
	while (ifs >> info) 
	{
		//std::cout << info << std::endl;

		std::vector<std::string> data;
		int pos = -1;//标志位
		int start = 0;//起始位
		
		while (true) 
		{
			//数据格式:10, 86.675, 9, 81.3, 7, 78.55,
			pos = info.find(",", start);//从全部的信息中按逗号查找,从start位置开始查找
			if (pos == -1) //没找到返回pos为-1,找到了返回pos为具体的位置
			{
				break;//没找到,或者找完了
			}

			//取字符串函数substr,参数一:起始位置;参数二;截取长度
			std::string temp = info.substr(start, pos - start);//pos为逗号位置,start为起始位置,相减就是我们要分割长度

			data.push_back(temp);//将分割后的结果放入data容器中
			start = pos + 1;//查找下一个
		}
		this->past_records.insert(std::make_pair(index, data));//将比赛的届数和冠军季军亚军的信息和成绩进行绑定

		index++;//比赛届数
	}
	ifs.close();

	/*
	//小测试
	for (std::map<int, std::vector<std::string>>::iterator it = past_records.begin(); it != past_records.end(); it++) 
	{
		std::cout << "Round is: " << (*it).first+1 << " ,Champion No." << it->second[0]
			<< " ,Final Score is: " << it->second[1] << std::endl;
	}
	*/
}

void Manager::showPastCompetitionRecord() //显示往届比赛记录
{
	if (this->fileIsEmpty) //若文件不存在或为空则提示用户
	{
		std::cout << "The file does not exist or the record is empty." << std::endl;
	}
	else //文件存在或不为空
	{
		for (int i = 0; i < this->past_records.size(); i++) //i表示第几届比赛
		{
			std::cout << "Round is: " << i + 1 << ", "
				<< "Champion No." << this->past_records[i][0] << ", Final Score is: " << this->past_records[i][1] << "; "
				<< "Runner-up No." << this->past_records[i][2] << ", Final Score is: " << this->past_records[i][3] << "; "
				<< "Third Place No." << this->past_records[i][4] << ", Final Score is: " << this->past_records[i][5] << "; "
				<< std::endl;
		}
	}
}

void Manager::clearPastCompetitionRecord() //清空往届比赛记录
{
	std::cout << "Are you sure you want to empty past competition record files?" << std::endl;
	std::cout << "1,Yes." << std::endl;
	std::cout << "2,No." << std::endl;

	int user_selection;
	std::cin >> user_selection;

	if (user_selection == 1) 
	{
		std::ofstream ofs("", std::ios::trunc);
		ofs.close();
		this->competitionReset();//重置初始化容器、重新创建12名选手、重新加载往届记录

		std::cout << "clear is successful" << std::endl;
	}

	system("pause");
	system("cls");
}

Manager::Manager() //构造函数
{
	this->initCompetition(); //调用比赛初始化函数
	this->createPlayer();    //调用创建选手函数
	this->loadPlayerInfo();//加载往届比赛记录
}

Manager::~Manager() //析构函数空实现
{
	//用于释放存放放在堆区的数据,我们这里没用到,故有没有无所谓
}

4,主函数——main.cpp

#include "Manager.h"
#include <iostream>
#include <iomanip>
#include <ctime>

void show_id_palyer_info(std::map<int, Player> id_palyer) //显示id和player信息绑定是否成功
{
	//std::setw(2) << std::setfill('0')为了将个位数的id补为两位,比如01,02,03...
	for (std::map<int, Player>::iterator it = id_palyer.begin(); it != id_palyer.end(); it++)
	{
		std::cout << "Player id is: " <<std::setw(2) << std::setfill('0') << (*it).first
			<< " ,name is: " << it->second.getName()
			<< " ,round 1 scores is: " << it->second.getScores()[0]
			<< " ,round 2 scores is: " << it->second.getScores()[1]
			<< std::endl;
	}
}

int main(int argc, char* agrv[])
{
	//添加随机数种子
	std::srand((unsigned int)time(NULL));

	Manager manager;
	int selection = 0;//接受用户的选择

	//测试一下id和player信息绑定是否成功
	//show_id_palyer_info(manager.id_player);

	while (true) 
	{
		manager.show_Menu(); //显示菜单
		
		std::cout << "Please input your selection:" << std::endl;
		std::cin >> selection;

		switch (selection)
		{
		case 1: //开始比赛
			manager.startCompetition(); //调用开始比赛成员方法
			break;
		case 2: //查看记录
			manager.showPastCompetitionRecord();
			break;
		case 3: //清空记录
			manager.clearPastCompetitionRecord();
			break;
		case 0: // 退出系统
			manager.exit_System();//调用管理类中的退出系统函数
			break;
		default: //按下其他键
			system("cls"); //清屏
			break;
		}
	}

	system("pause");

	return 0;
}

5,运行效果

1.开始比赛
在这里插入图片描述
2.查看往届记录
在这里插入图片描述
3.清空比赛记录
在这里插入图片描述
0.退出比赛程序
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2076295.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git —— 2、创建本地版本库

版本库 版本库又名仓库&#xff0c;英文名repository&#xff0c;这个仓库里面的所有文件都可以被Git管理起来&#xff0c;每个文件的修改.删除&#xff0c;Git都能跟踪&#xff0c;以便任何时刻都可以追踪历史&#xff0c;或者在将来某个时刻可以“还原“。   创建本地版本库…

day31-测试之性能测试工具JMeter的功能概要、元件作用域和执行顺序

目录 一、JMeter的功能概要 1.1.文件目录介绍 1).bin目录 2).docs目录 3).printable_docs目录 4).lib目录 1.2.基本配置 1).汉化 2).主题修改 1.3.基本使用流程 二、JMeter元件作用域和执行顺序 2.1.名称解释 2.2.基本元件 2.3.元件作用域 1).核心 2).提示 3).作用域的原则 2.…

【AI绘画】Midjourney前置/imagine与单图指令详解

文章目录 &#x1f4af;Midjourney前置指令/imagine什么是前置指令&#xff1f;/imaginepromptUpscale(放大)Variations&#xff08;变化&#xff09;&#x1f504;&#xff08;重新生成一组图片&#xff09; &#x1f4af;单张图片指令Upscale (细节优化)Vary&#xff08;变体…

计算机二级真题--程序填空大题 章节

每类题有一些规律&#xff0c;这里来总结一下个人做题遇到的一些规律&#xff0c;大家可以自行掌握 1.在while循环里常常会将将最后一行空着作为考点&#xff0c;例如下面第的10题&#xff0c;因为需要联系整个循环所以经常分析不出来&#xff0c;实际上for训话中也有过这种考…

无需标注数据:引领视频编辑模型达到新高度

人工智能咨询培训老师叶梓 转载标明出处 由于标注视频编辑数据的稀缺&#xff0c;开发精确且多样化的视频编辑模型一直是个挑战。目前研究者们大多聚焦于无需训练的方法&#xff0c;但这些方法在性能和编辑能力范围上都有所限制。为此Meta AI的研究团队提出了一种新的方法&…

Code Llama: Open Foundation Models for Code论文阅读

整体介绍 Code Llama 发布了3款模型&#xff0c;包括基础模型、Python 专有模型和指令跟随模型&#xff0c;参数量分别为 7B、13B、34B 和 70B。这些模型在长达 16k tokens 的序列上训练。都是基于 Llama 2。 作者针对infilling (FIM) 、长上下文、指令专门做了微调 long-con…

CSS Sprite(精灵图)

CSS Sprite也叫CSS精灵图、CSS雪碧图&#xff0c;是一种网页图片应用处理方式。它允许你将一个页面涉及到的所有零星图片都包含到一张大图中去 优点&#xff1a; 减少图片的字节减少网页的http请求&#xff0c;从而大大的提高页面的性能 原理&#xff1a; 通过background-i…

《黑神话悟空》幽魂怎么打?大头怪幽魂打法攻略

黑神话悟空第一章中许多玩家都容易被大头怪幽魂给难住&#xff0c;这算是渡劫中的第一难&#xff0c;所以不少玩家想了解黑神话悟空大头怪怎么打&#xff1f;其实大头怪打起来并不难&#xff0c;只是很多的玩家们没有了解他的弱点以及特性。小编今天就为大家整理了大头怪幽魂的…

吴艳妮牵手创维,奥运后的首个代言为什么是她?

​近日&#xff0c;吴艳妮参加奥运会的表彰大会&#xff0c;晒出了与孙颖莎、王楚钦等运动员的合照&#xff0c;并写道&#xff1a;“最幸福的一天”在网络上引发讨论&#xff0c;让人不禁想起在巴黎奥运会刚结束的时候&#xff0c;家电巨头创维官宣她作为其品牌大使的消息也是…

在不训练模型的情况下强化语言模型

文章目录 一些神奇咒语提供额外资讯拆解任务使用工具让模型彼此合作 一些神奇咒语 让模型一步一步的思考 让模型解释一下自己的答案 对模型进行情绪勒索&#xff0c;比如对模型说&#xff1a;这件事对我真的很重要&#xff01; 跟模型说”请“是没有用的&#xff1b;跟模型说“…

IO--标准函数使用方法

在学习这个知识点时&#xff0c;要清楚我们使用IO其实就是如何使用函数&#xff1b; 注意点 函数名函数参数之间的关系应用的场景&#xff0c;返回值缓冲区的概念 1、IO的分类 文件IO标准IO 重点 1、标准IO函数 fopen / fclosefprintf / fscanffputc / …

如何使用Kdrill检测Windows内核中潜在的rootkit

关于Kdrill Kdrill是一款用于分析 Windows 64b 系统内核空间安全的工具&#xff0c;该工具基于纯Python 3开发&#xff0c;旨在帮助广大研究人员评估Windows内核是否受到了rootkit攻击。 需要注意的是&#xff0c;该项目与Python2/3兼容&#xff0c;无其他依赖组件&#xff0c…

女明星玩乙游,为何会推动国乙玩家“世纪大和解”?

“震惊&#xff01;叠姐和光姐竟然世纪大和解了。” 这件在国乙圈匪夷所思、想都不敢想的事&#xff0c;竟然在一位女明星的推动下发生了&#xff0c;也因此诞生了国乙圈的“8.22事件”。 事情的起因是女艺人乃万在社交平台上发布了乙游相关言论&#xff0c;引起了乙游玩家不…

SAP 有趣的‘bug‘ 选择屏幕输入框没了

如下代码将会输出一个P_U的字段 PARAMETERS p_u TYPE string VISIBLE LENGTH 12 MEMORY ID m1.AT SELECTION-SCREEN OUTPUT.LOOP AT SCREEN.IF screen-name P_U.screen-invisible 1.MODIFY SCREEN.ENDIF.ENDLOOP. 如果我们给这个字段设置一个默认值&#xff0c;参考如下代码…

8.26-docker创建容器+打包镜像+docker文件的学习

一、回顾 创建容器&#xff1a;docker run -it --name a1 centos:latest /bin/bash 查看容器&#xff1a;docker ps&#xff08;查看正在up的容器&#xff09; docker ps -a&#xff08;查看所有的容器&#xff09; 切回宿主机&#xff1a;ctrl p q 启动容器&#xff1a;d…

Furion+SqlSugar环境配置与项目创建

一、速通一图流 二、安装 .NET 8 1. 下载与安装 .NET 8 SDK 访问 .NET 下载页面 并下载最新版本的 .NET 8 SDK。根据操作系统选择适合的安装包&#xff08;如 Windows、macOS 或 Linux&#xff09;&#xff0c;并按照提示完成安装。 2. 验证安装 打开终端或命令提示符&…

SpringMVC - 第一个 SpringMVC 程序

MVC: 模块 视图 控制器 的简写&#xff0c;表示层 属于 C V&#xff0c;业务层和逻辑层属于 M SpringMVC 是对 web 使用的一套框架&#xff0c;可以更加快捷高效的管理 web应用 所有的请求都会经过 DispatcherServlet 这一个 Servlet 支持 IoC 和 AOP 统一处理请求 可以解析多…

找工作——行秋24届求职面试经验汇总

前言 求职记录&#xff1a;本人bg双9&#xff08;末流&#xff09;&#xff0c;共投岗位200&#xff0c;收到5个offer&#xff0c;求职方向偏向于国企&#xff0c;求职城市青睐新一线城市。个人求职记录 (qq.com)https://docs.qq.com/sheet/DSlBBVWRKZVZ5TWlD?tabBB08J2&…

C 06 编译4阶段

c语言编译的4个阶段&#xff1a;预处理、 编译、 汇编、 链接 预处理阶段会在源代码中查找预编译指令&#xff0c;其中主要是头文件展开&#xff08;include)&#xff0c;宏定义&#xff08;defind&#xff09;&#xff0c;选择性编译&#xff08;ifdef&#xff09;三种指令 预…

Claude 3.5 Sonnet引入了LaTeX公式渲染功能!!

终于&#xff0c;Claude 也引入了LaTeX公式渲染功能&#xff0c;消息一出&#xff0c;评论区的网友们热议不断。 【最新版】手把手Claude 3.5 Sonnet 详细步骤注册方法&#xff01;_claude 3.5 sonnet 注册 早在 ChatGPT 率先支持 LaTeX 语言用于输入和显示数学公式时&#xf…