<C++>12 项目:演讲比赛管理系统

本文最后更新于:2023年6月27日 上午

12 项目:演讲比赛管理系统

12.1 项目需求

共有 12 名选手,编号 10001 - 10012

比赛分为 2 轮:

  1. 第一轮比赛分为 2 组分别进行。每组前 3 名晋级下一轮比赛
  2. 第二轮比赛的前 3 名胜出

打分方式:10 个评委分别对每位选手打分,去除最高分和最低分,剩余的平均分为选手本轮成绩

每轮比赛过后,显示晋级选手(胜出选手)的信息

选手信息:姓名、编号、性别、成绩、排名

打分范围:0 - 100(随机)

菜单:

  • 选手报名
  • 选手信息变更
  • 选手查询(按姓名、编号查找)
  • 开始比赛
    • 显示选手信息、轮次信息(输出至 .csv 文档)
    • 随机打分、手动打分
    • 确认晋级选手(输出至 .csv 文档)
    • 第二轮
    • 确认胜出选手(输出至 .csv 文档)
  • 查看往届记录
  • 清空比赛记录
  • 退出系统

附录

演讲比赛管理系统

执行以下代码:

#include "menu.h"

int main() {
	menu0();
}

#头文件

player.h

包含 Player 类、Com 类

  • Player 类:选手类。对象包含选手信息(ID、姓名、得分)。

    该类包含一个静态容器,代表参赛选手的集合

  • Com 类:仿函数。实现对 Player* 的按 socre 的比较

#pragma once
#include<iostream>
using namespace std;
#include<string>
#include<set>
#include<fstream>

class Com;

class Player {
public:
	static int id_count;						// ID 计数。实例化时的 ID 值一般从 10000 开始
	static set<Player*, Com>* players;			// 静态容器,代表参赛选手的集合
	Player(string name);						// 构造方法。传入姓名
	~Player();									// 析构方法。是空实现
	string print();								// 返回选手信息的字符串
	void set_socre(double s);
	double get_socre();
	void set_name(string s);
	string get_name();
	int get_id();
	static void initial();						// 初始化 Player 类。会清空参赛选手,并重置 ID 计数
	static void flush(set<Player*, Com>& p);	// 用新的选手集合取代目前的集合
	bool operator>(Player& p);
	bool operator<(Player& p);
	bool operator==(Player& p);
private:
	double socre = 0;							// 选手得分,初始为 -1
	int id;										// 选手 ID。不能更改
	string name;								// 选手姓名
};


class Com {
public:
	bool operator()(Player* p1, Player* p2) const;
};

menu.h

程序入口。包含了大部分方法

#pragma once
#include<iostream>
using namespace std;
#include<string>
#include<set>
#include<vector>
#include<algorithm>
#include<fstream>
#include<numeric>

#include "player.h"

void menu0();										// 程序主方法
void showMenu0();									// 仅展示菜单
void add_player();									// 添加一位选手
void affirm_player();								// 查找选手
Player* affirm_by_id(int id);						// 按照 ID 查找选手
Player* affirm_by_name(const string& name);			// 按照姓名查找选手
void changePlayer();								// 变更选手信息
void start_match();									// 开始比赛
set<Player*, Com>& round1(set<Player*, Com>& p);	// 第一轮比赛
double socre();										// 生成一个随机的分数
set<Player*, Com>& round2(set<Player*, Com>& p);	// 第二轮比赛
void histroy();										// 查看历史记录
void clear_histroy();								// 清空历史记录
void write();										// 将目前的赛况导出
void show_all();									// 展示参赛选手信息
bool log_out();										// 退出程序前的确认

#源文件

player.cpp

#include "player.h"

Player::Player(string name) {				// 构造器。每次构造时会更新随机值的种子
	this->id = ++id_count;
	this->name = name;
	this->socre = -1;
	srand((unsigned)time(NULL));
}

Player::~Player() {}						// 析构函数。是空实现

string Player::print() {					// 返回选手信息的字符串。项之间以 \t 分隔
	return to_string(id) + "\t" + name + "\t" + (socre < 0 ? "-" : (to_string(socre)));
}


void Player::set_socre(double s) {
	this->socre = s;
};
double Player::get_socre() {
	return this->socre;
};
void Player::set_name(string s) {
	this->name = s;
};
string Player::get_name() {
	return this->name;
};
int Player::get_id() {
	return this->id;
};

void Player::flush(set<Player*, Com>& p) {	// 静态方法。该方法会替换原先的参赛选手集合
	if (Player::players != NULL) {
		delete Player::players;
		Player::players = NULL;
	}
	Player::players = &p;
};

bool Player::operator>(Player& p) {
	if (this->socre != p.socre) {
		return this->socre > p.socre;
	} else return this->id > p.id;
};

bool Player::operator<(Player& p) {
	return p > *this;
};

bool Player::operator==(Player& p) {
	return p.id == this->id && p.name == this->name;
};

void Player::initial() {					// 静态方法。该方法会清空参赛选手集合,并重置 ID 计数
	Player::id_count = 10000;
	if (Player::players != NULL) delete Player::players;
	Player::players = NULL;
	Player::players = new set<Player*, Com>;
};

// 以下是两个静态变量的初始化
int Player::id_count = 10000;
set<Player*, Com>* Player::players = new set<Player*, Com>;


bool Com::operator()(Player* p1, Player* p2) const {	// 仿函数,比较两个 Player*
	if (p1->get_socre() != p2->get_socre()) {
		return p1->get_socre() > p2->get_socre();
	}
	else return p1->get_id() > p2->get_id();
};

menu.cpp

#include "menu.h"


void showMenu0() {
	cout << "————————·演讲比赛:★:管理系统·————————" << endl;
	cout << "\t\t1.选 手 报 名" << endl;
	cout << "\t\t2.选 手 查 询" << endl;
	cout << "\t\t3.变 更 选 手" << endl;
	cout << "\t\t4.比 赛 开 始" << endl;
	cout << "\t\t5.查 看 往 届 记 录" << endl;
	cout << "\t\t6.清 空 比 赛 记 录" << endl;
	cout << "\t\t7.查 看 全 部 选 手" << endl;
	cout << "\t\t9.退 出 系 统" << endl;
};

void menu0() {	
	bool running = true;
	while (running) {
		showMenu0();
		int choice = 0;
		cout << "请输入您的选择:";
		cin >> choice;
		cout << endl << "——————————————————————" << endl;
		switch (choice) {
		case 1:
			add_player();
			break;
		case 2:
			affirm_player();
			break;
		case 3:
			changePlayer();
			break;
		case 4:
			start_match();
			break;
		case 5:
			histroy();
			break;
		case 6:
			clear_histroy();
			break;
		case 7:
			show_all();
			break;
		case 9:
			if (log_out()) running = false;
			break;
		default:
			cout << "输入有误,请重新输入!" << endl;
			break;
		}
		system("pause");
		system("cls");
	}
};

void add_player() {
	if (Player::players->size() >= 12) {
		cout << "选手数量已满!(最多 12 人)" << endl;
		return;
	}
	cout << "========= 添 加 选 手 =========" << endl << "请输入选手姓名:";
	string name;
	cin >> name;
	Player* temp = new Player(name);
	Player::players->insert(temp);
	cout << endl << "选手信息:" << temp->print() << endl;
	cout << "继续吗?(Y / N):";
	char confirm = 'N';
	cin >> confirm;
	if (confirm == 'Y' || confirm == 'y' || confirm == '1') {
		cout << endl;
		add_player();
	}
};

void affirm_player() {
	if (Player::players->size() == 0) {
		cout << "目前暂无选手报名。" << endl;
		return;
	}
	cout << "========= 查 找 选 手 =========" << endl << "请输入查找方法(1[id] / 2[姓名]):";
	int choice = 1;
	cin >> choice;
	if (choice == 2) {
		cout << "========= 姓 名 查 找 =========" << endl;
		cout << "请输入姓名:";
		string s;
		cin >> s;
		affirm_by_name(s);
	}
	else if (choice == 1) {
		cout << "========= ID 查 找 =========" << endl;
		cout << "请输入 ID:";
		cin >> choice;
		affirm_by_id(choice);
	}
	else {
		cout << "返回菜单。" << endl;
		return;
	}
};

Player* affirm_by_id(int id) {
	for (set<Player*>::const_iterator i = Player::players->begin(); i != Player::players->end(); i++) {
		Player* temp = *i;
		if (temp->get_id() == id) {
			cout << "找到以下选手:" << temp->print() << endl;
			return *i;
		}
	}
	cout << "未找到该选手信息" << endl;
	return NULL;
};

Player* affirm_by_name(const string& name) {
	bool found = false;
	set<Player*> ss;
	for (set<Player*>::const_iterator i = Player::players->begin(); i != Player::players->end(); i++) {
		Player* temp = *i;
		if (temp->get_name() == name) {
			ss.insert(*i);
			found = true;
		}
	}
	if (!found) {
		cout << "未找到该选手信息" << endl;
		return NULL;
	}
	else {
		cout << "找到以下 " << ss.size() << " 位选手:" << endl;
		for (set<Player*>::const_iterator i = ss.begin(); i != ss.end(); i++) {
			Player* temp = *i;
			cout << temp->print() << endl;
		}
		if (ss.size() == 1) {
			return *ss.begin();
		}
		cout << "是否再通过 ID 查找?(Y / N):";
		char confirm = 'N';
		cin >> confirm;
		if (confirm == 'Y' || confirm == 'y') {
			int id = 0;
			cout << endl << "请输入 ID:";
			cin >> id;
			return affirm_by_id(id);
		}
		else return NULL;
	}
};

void changePlayer(){
	show_all();
	cout << "请输入要改变的选手 ID:";
	int id = -1;
	cin >> id;
	cout << endl;
	Player* player = affirm_by_id(id);
	if (player == NULL) return;
	cout << "请输入选手姓名:";
	string name;
	cin >> name;
	player->set_name(name);
	affirm_by_id(id);
};

void start_match(){
	if (Player::players->size() < 12) {
		cout << "人数不足!" << endl;
		return;
	}
	system("cls");
	cout << "展示本轮参赛选手:" << endl;
	show_all();
	cout << endl;
	//write(0);
	cout << "按任意键开始比赛" << endl;
	system("pause");
	system("cls");
	Player::flush(round1(*Player::players));
	//write(1);
	cout << endl << "晋级选手是:" << endl;
	show_all();
	cout << endl;
	cout << "下一轮比赛即将开始" << endl;
	system("pause");
	system("cls");
	Player::flush(round2(*Player::players));
	write();
	cout << endl;
	cout << "比赛的胜出者是:" << endl << endl;
	set<Player*, Com>::const_iterator i = Player::players->begin();
	Player* temp = *i;
	i++;
	cout << "★★·第一名:" << temp->print() << "·★★" << endl << endl;
	temp = *i;
	i++;
	cout << "·☆·第二名:" << temp->print() << "·☆·" << endl << endl;
	temp = *i;
	i++;
	cout << "···第三名:" << temp->print() << "···" << endl << endl;
	system("pause");
	Player::initial();
};



void write() {
	if (Player::players->size() == 0) return;
	ofstream ost;
	ost.open("game_data.csv", ios::out | ios::app);
	for (set<Player*>::const_iterator i = Player::players->begin(); i != Player::players->end(); i++) {
		Player* temp = *i;
		ost << temp->print() << endl;
	}
	ost << endl;
	ost.close();
};





set<Player*, Com>& round1(set<Player*, Com>& p){
	cout << "———————Round 1———————" << endl;
	set<Player*, Com> team1;
	set<Player*, Com> team2;
	set<Player*, Com>* winner = new set<Player*, Com>;
	set<Player*>::const_iterator it = p.begin();
	for (int i = 0; it != p.end(); it++, i++) {
		if (i == 0) {
			cout << "······第一组······" << endl;
			cout << "·ID\t姓名\t得分·" << endl;
		}
		else if (i == 6) {
			cout << "······第二组······" << endl;
			cout << "·ID\t姓名\t得分·" << endl;
		}
		Player* temp = *it;
		temp->set_socre(socre());
		cout << temp->print() << endl;
		if (i < 6) team1.insert(temp);
		else team2.insert(temp);
	}
	set<Player*, Com>::const_iterator i1 = team1.begin();
	set<Player*, Com>::const_iterator i2 = team2.begin();
	for (int i = 0; i < 3; i++) {
		if (i1 != team1.end()) {
			winner->insert(*i1);
			i1++;
		}
		if (i2 != team2.end()) {
			winner->insert(*i2);
			i2++;
		}
	}
	return *winner;
};

double socre(){
	vector<int> ss;
	for (int i = 0; i < 10; i++) {
		ss.push_back(rand() % 101);
	}
	sort(ss.begin(), ss.end());
	double socre = accumulate(++ss.begin(), --ss.end(), 0);
	socre /= 8;
	return socre;
};

set<Player*, Com>& round2(set<Player*, Com>& p){
	set<Player*, Com>* winner = new set<Player*, Com>;

	cout << "———————Round 2———————" << endl;
	cout << "·ID\t姓名\t得分·" << endl;
	for (set<Player*, Com>::const_iterator it = p.begin(); it != p.end(); it++) {
		Player* temp = *it;
		temp->set_socre(socre());
		cout << temp->print() << endl;
		winner->insert(temp);
	}
	set<Player*, Com>::const_iterator it = winner->begin();
	it++;
	it++;
	it++;
	winner->erase(it, winner->end());
	return *winner;
};


void histroy(){
	cout << "========= 历 史 记 录 =========" << endl;
	ifstream ifs;
	ifs.open("game_data.csv", ios::in);
	if (!ifs.is_open()) {
		cout << "当前没有比赛记录" << endl;
		return;
	}
	char c;
	ifs >> c;
	if (ifs.eof()) {
		cout << "当前没有比赛记录" << endl;
		return;
	}
	ifs.putback(c);
	int n = 0;
	string data;
	while (ifs >> data) {
		if (n % 3 == 0) {
			cout << endl;
			if (n % 9 == 0) {
				cout << endl << "———————第 " << (n / 9) + 1 << " 届演讲比赛———————" << endl;
				cout << "·ID\t姓名\t得分·" << endl;
			}
		}
		n++;
		cout << data << '\t';
	}
	cout << endl << "——————————————————" << endl;
};

void clear_histroy(){
	ofstream ost;
	ost.open("game_data.csv", ios::out | ios::trunc);
	ost.close();
};

void show_all() {
	cout << "========= 选 手 信 息 =========" << endl;
	cout << "·ID·\t-姓名-\t·成绩·" << endl;
	for (set<Player*>::const_iterator i = Player::players->begin(); i != Player::players->end(); i++) {
		Player* temp = *i;
		cout << temp->print() << endl;
	}
	cout << "========= 展 示 完 毕 =========" << endl;
};

bool log_out(){
	cout << "确定要退出吗?未保存的记录将会消失(Y / N):";
	char affirm = 'N';
	cin >> affirm;
	return affirm == 'Y' || affirm == 'y';
};

<C++>12 项目:演讲比赛管理系统
https://i-melody.github.io/2022/05/21/C++/入门阶段/12 项目:演讲比赛管理系统/
作者
Melody
发布于
2022年5月21日
许可协议