C++--综合应用-演讲比赛项目

发布于:2025-05-20 ⋅ 阅读:(15) ⋅ 点赞:(0)

需求

分析

1、初始化,生成演讲学生数组,打乱数组以便随机分组

2、每轮比赛后需要统计每个学生的胜场,以便决定进入下一轮和最终胜利的学生

代码实现

#pragma once

#include<iostream>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<fstream>

using namespace std;

/*
* N为M的倍数
* N(=12)个学生参加演讲比赛。比赛共两轮。
* 第一轮、分组淘汰赛,随机分组,每组M(=6)人,两两演讲PK。每组决出前三名进入下一轮。
* 第二轮、决赛,每组两两PK,决出比赛前三名。
* 每轮比赛过后显示晋级选手信息。(可以保存比赛记录到文件中,方便查看)
*/
class Student {
public:
	int id;
	string name;
	Student(int id, string name) : id(id), name(name) {
		this->id = id;
		this->name = name;
	}
	int say() { // 演讲 通过比较随机数大小判断演讲胜负
		return rand() % 12;
	}
};

static int times = 0;
static const int NUM = 12;
static const int MAX_NUM = 10001;
static Student** stu;
static Student** origin_stu;
static string s_name = "ABCDEFGHIJKL";
static const string file_name = "competition.txt";

auto int_asc_sort = [](int a, int b)->bool {
	return a > b;
};
auto asc_sort = [](pair<Student*, int> a, pair<Student*, int> b)->bool {
	return a.second > b.second;
};
static void print_set_no_erase(multiset<pair<Student*, int>, decltype(asc_sort)> topK) {
	for (multiset<pair<Student*, int>, decltype(asc_sort)>::iterator a = topK.begin(); a != topK.end(); a++) {
		pair<Student*, int> p = *a;
		Student* s = p.first;
		int count = p.second;
		cout << "id:" << s->id << " name:" << s->name << " 胜场: " << count << endl;
	}
}
static multiset<pair<Student*, int>, decltype(asc_sort)> print_set(multiset<pair<Student*, int>, decltype(asc_sort)> topK) {
	cout << "胜场降序排序后......" << endl;
	int limit = 1;
	for (multiset<pair<Student*, int>, decltype(asc_sort)>::iterator a = topK.begin(); a != topK.end(); a++) {
		if (limit++ > 6) {
			break;
		}
		pair<Student*, int> p = *a;
		Student* s = p.first;
		int count = p.second;
		cout << "id:" << s->id << " name:" << s->name << " 胜场: " << count << endl;
	}
	multiset<pair<Student*, int>, decltype(asc_sort)>::iterator a = topK.begin();
	a++; a++; a++;
	topK.erase(a, topK.end());
	return topK;
}
static void print_score(int a[], int len) {
	for (int i = 0; i < len; i++) {
		cout << s_name.substr(i, 1) << " 胜场: " << a[i] << endl;
	}
}
static multiset<pair<Student*, int>, decltype(asc_sort)> print_score(int a[], int len, multiset<pair<Student*, int>, decltype(asc_sort)> topK) {
	for (int i = 0; i < len; i++) {
		//cout << s_name.substr(i, 1) << " stu[" << i << "] = " << a[i] << endl;
		topK.insert(make_pair(origin_stu[i], a[i]));
	}
	return print_set(topK);
}
static void print_stu(Student ** stu, int len) {
	for (int i = 0; i < len; i++) {
		cout << "student[" << i 
			<< "] id:" 
			<< stu[i]->id << " name:" 
			<< stu[i]->name << endl;
	}
}

void count_times() {
	// 计算是第几次比赛
	fstream read_file;
	read_file.open(file_name, ios::in);
	string temp;
	while (getline(read_file, temp, '\n')) {
		times++;
	}
	times = times / 3;
	read_file.close();
}

// 初始化演讲的学生,打乱顺序以便随机分组
void init() {
	stu = new Student* [NUM];
	origin_stu = new Student* [NUM];
	srand(time(NULL));
	for (int i = 0; i < NUM; i++) {
		stu[i] = new Student(10000 + i + 1, s_name.substr(i, 1));
		origin_stu[i] = new Student(10000 + i + 1, s_name.substr(i, 1));
	}
	random_shuffle(stu, stu+NUM);
	//print_stu(stu);

	if (times == 0) {
		count_times();
	}
}

void competition(Student** stu1, Student** stu2, int len, int result[], int result2[]) {
	for (int i = 0; i < len; i++) {
		cout << "选手【" << stu1[i]->name << "】的比赛......";
		for (int j = 0; j < len; j++) {
			cout << "场次:" << stu1[i]->name << " PK " << stu2[j]->name << " -> ";
			if (stu1[i]->say() >= stu2[j]->say()) {
				cout << stu1[i]->name << "胜" << "\t";
				result[stu1[i]->id - MAX_NUM]++;
			}
			else
			{
				cout << stu2[j]->name << "胜" << "\t";
				result2[stu2[j]->id - MAX_NUM]++;
			}
		}
		cout << endl;
	}
}

// 提取哪些学生晋级了
void extraction(multiset<pair<Student*, int>, decltype(asc_sort)> top, Student** s) {
	int i = 0;
	for (multiset<pair<Student*, int>, decltype(asc_sort)>::iterator a = top.begin(); a != top.end(); a++) {
		s[i++] = a->first;
	}
}

void merge_array(int a[], int b[], int c[], int len) {
	for (int i = 0; i < len; i++) {
		c[i] = a[i] + b[i];
	}
}

// 比赛结果写入文件
static void store(pair<Student*, int> p[], int len) {
	// 写入比赛结果
	fstream out(file_name, ios::app);
	//while (out.getline((char *)p, sizeof(pair<Student*, int>))) {
	//}
	for (int i = 0; i < len; i++) {
		out << p[i].first->id << " " << p[i].first->name << " " << p[i].second << endl;
	}
	out.close();
	times++; // 比赛场数加1
}

// 清空比赛记录文件
static void clear() {
	fstream out(file_name, ios::out|ios::trunc);
	out.close();
	times = 0;
}

// 查看历史比赛结果
static void look_result() {
	fstream read_file;
	read_file.open(file_name, ios::in);
	string temp;
	int count = 1;
	for (int i = 1; i <= times; i++) {
		cout << "第" << i << "次比赛结果如下:" << endl;
		while (getline(read_file, temp, '\n')) {
			cout << temp << endl;
			if ((count++) % 3 == 0) {
				break;
			}
		}
		read_file.seekg(11/*每行11个字节,换行回车占2个字节*/ * (count - 1));
	}
}

void main_entry() {
	init();
	cout << "输入1开始第一轮比赛:";
	int start1;
	cin >> start1;
	if (start1 != 1) {
		cout << "游戏中止......" << endl;
		return;
	}
	Student** stu1 = new Student* [NUM/2];
	Student** stu2 = new Student * [NUM / 2];
	for (int i = 0; i < NUM; i++) {
		if (i < NUM/2) {
			stu1[i] = stu[i];
		}
		else {
			stu2[i-NUM/2] = stu[i];
		}
	}
	cout << "第一轮分组情况:" << endl;
	cout << "1组: " << endl;
	print_stu(stu1, NUM/2);
	cout << "2组: " << endl;
	print_stu(stu2, NUM / 2);
	delete[] stu;
	srand(time(NULL));
	int result[NUM] = {0};
	int result2[NUM] = {0};
	// 总共36场比赛 6 * 6 = 36
	// 0 7 8 9 10 11 12
	// 1 7 8 9 10 11 12
	// 2 7 8 9 10 11 12
	// 3 7 8 9 10 11 12
	// 4 7 8 9 10 11 12
	// 5 7 8 9 10 11 12
	// 6 7 8 9 10 11 12
	cout << "第一轮总共36场比赛,比赛结果如下:" << endl;
	competition(stu1, stu2, NUM/2, result, result2);
	//for (int i = 0; i < NUM / 2; i++) {
	//	for (int j = 0; j < NUM / 2; j++) {
	//		if (stu1[i]->say() >= stu2[j]->say()) {
	//			result[MAX_NUM - stu1[i]->id]++;
	//		}
	//		else
	//		{
	//			result2[MAX_NUM - stu2[j]->id]++;
	//		}
	//	}
	//}
	//print_score(result, NUM);
	//print_score(result2, NUM);
	int result_array1[NUM] = { 0 };
	merge_array(result, result2, result_array1, NUM);
	print_score(result_array1, NUM);
	//multiset<pair<Student*, int>, decltype(asc_sort)> topK(asc_sort);
	multiset<pair<Student*, int>, decltype(asc_sort)> set1(asc_sort);
	multiset<pair<Student*, int>, decltype(asc_sort)> set2(asc_sort);
	cout << "1组胜场详情:";
	multiset<pair<Student*, int>, decltype(asc_sort)> top1 = print_score(result, NUM, set1);
	cout << "2组胜场详情:";
	multiset<pair<Student*, int>, decltype(asc_sort)> top2 = print_score(result2, NUM, set2);
	cout << "1组前三名如下:" << endl;
	print_set_no_erase(top1);
	cout << "2组前三名如下:" << endl;
	print_set_no_erase(top2);
	delete[] stu1;
	delete[] stu2;

	cout << endl;
	cout << "---------------------------" << endl;
	cout << "输入数字1继续第二轮比赛:";
	int select;
	cin >> select;
	if (select != 1) {
		cout << "第二轮游戏中止......" << endl;
		return;
	}
	//sort(result, result + NUM, greater<int>());
	//sort(result, result + NUM, asc_sort);
	Student** s1 = new Student*[3];
	Student** s2 = new Student*[3];
	extraction(top1, s1);
	extraction(top2, s2);
	cout << "第二轮分组情况:" << endl;
	cout << "1组: " << endl;
	print_stu(s1, 3);
	cout << "2组: " << endl;
	print_stu(s2, 3);
	int r1[NUM] = {0};
	int r2[NUM] = {0};
	//int* r1 = new int[6]{0};
	//int* r2 = new int[6]{0};
	cout << "第二轮总共9场比赛,比赛结果如下:" << endl;
	competition(s1, s2, 3, r1, r2);
	//print_score(r1, NUM);
	//cout << endl;
	//print_score(r2, NUM);
	int result_array[NUM] = {0};
	merge_array(r1, r2, result_array, NUM);
	print_score(result_array, NUM);
	//sort(result_array, result_array + NUM, greater<int>());
	//sort(result_array, result_array + NUM, int_asc_sort);
	pair<Student*, int> p[NUM];
	for (int i = 0; i < NUM; i++) {
		p[i] = make_pair(origin_stu[i], result_array[i]);
	}
	sort(p, p+NUM, asc_sort);
	store(p, 3);
	cout << "前三名信息如下:" << endl;
	cout << "第一名 id:" << p[0].first->id << " name:" << p[0].first->name << " 总胜场:" << p[0].second << endl;
	cout << "第二名 id:" << p[1].first->id << " name:" << p[1].first->name << " 总胜场:" << p[1].second << endl;
	cout << "第三名 id:" << p[2].first->id << " name:" << p[2].first->name << " 总胜场:" << p[2].second << endl;
}

// 比赛入口
void entry() {
	while (true) {
		int select;
		cout << "=============================" << endl;
		cout << "0、退出" << endl;
		cout << "1、开始游戏" << endl;
		cout << "2、查看历史比赛结果" << endl;
		cout << "3、清空历史比赛记录" << endl;
		cout << "=============================" << endl;
		cin >> select;
		if (select == 1) {
			system("cls");
			cout << "开始游戏..." << endl;
			cout << endl;
			main_entry();
			//look_result();
		}
		else if (select == 2) {
			if (times == 0) {
				count_times();
			}
			system("cls");
			look_result();
		}
		else if (select == 3) {
			clear();
			system("cls");
		}
		else {
			break;
		}
	}
	cout << "比赛结束..." << endl;
}

一种测试结果

开始游戏...

输入1开始第一轮比赛:1
第一轮分组情况:
1组:
student[0] id:10002 name:B
student[1] id:10009 name:I
student[2] id:10001 name:A
student[3] id:10007 name:G
student[4] id:10012 name:L
student[5] id:10011 name:K
2组:
student[0] id:10003 name:C
student[1] id:10005 name:E
student[2] id:10008 name:H
student[3] id:10004 name:D
student[4] id:10006 name:F
student[5] id:10010 name:J
第一轮总共36场比赛,比赛结果如下:
选手【B】的比赛......场次:B PK C -> C胜        场次:B PK E -> B胜     场次:B PK H -> B胜     场次:B PK D -> D胜    场次:B PK F -> F胜     场次:B PK J -> J胜
选手【I】的比赛......场次:I PK C -> C胜        场次:I PK E -> E胜     场次:I PK H -> I胜     场次:I PK D -> D胜    场次:I PK F -> F胜     场次:I PK J -> J胜
选手【A】的比赛......场次:A PK C -> A胜        场次:A PK E -> A胜     场次:A PK H -> H胜     场次:A PK D -> D胜    场次:A PK F -> A胜     场次:A PK J -> J胜
选手【G】的比赛......场次:G PK C -> C胜        场次:G PK E -> E胜     场次:G PK H -> G胜     场次:G PK D -> G胜    场次:G PK F -> G胜     场次:G PK J -> J胜
选手【L】的比赛......场次:L PK C -> L胜        场次:L PK E -> E胜     场次:L PK H -> L胜     场次:L PK D -> L胜    场次:L PK F -> F胜     场次:L PK J -> L胜
选手【K】的比赛......场次:K PK C -> K胜        场次:K PK E -> K胜     场次:K PK H -> K胜     场次:K PK D -> D胜    场次:K PK F -> F胜     场次:K PK J -> J胜
A 胜场: 3
B 胜场: 2
C 胜场: 3
D 胜场: 4
E 胜场: 3
F 胜场: 4
G 胜场: 3
H 胜场: 1
I 胜场: 1
J 胜场: 5
K 胜场: 3
L 胜场: 4
1组胜场详情:胜场降序排序后......
id:10012 name:L 胜场: 4
id:10001 name:A 胜场: 3
id:10007 name:G 胜场: 3
id:10011 name:K 胜场: 3
id:10002 name:B 胜场: 2
id:10009 name:I 胜场: 1
2组胜场详情:胜场降序排序后......
id:10010 name:J 胜场: 5
id:10004 name:D 胜场: 4
id:10006 name:F 胜场: 4
id:10003 name:C 胜场: 3
id:10005 name:E 胜场: 3
id:10008 name:H 胜场: 1
1组前三名如下:
id:10012 name:L 胜场: 4
id:10001 name:A 胜场: 3
id:10007 name:G 胜场: 3
2组前三名如下:
id:10010 name:J 胜场: 5
id:10004 name:D 胜场: 4
id:10006 name:F 胜场: 4

---------------------------
输入数字1继续第二轮比赛:1
第二轮分组情况:
1组:
student[0] id:10012 name:L
student[1] id:10001 name:A
student[2] id:10007 name:G
2组:
student[0] id:10010 name:J
student[1] id:10004 name:D
student[2] id:10006 name:F
第二轮总共9场比赛,比赛结果如下:
选手【L】的比赛......场次:L PK J -> J胜        场次:L PK D -> D胜     场次:L PK F -> F胜
选手【A】的比赛......场次:A PK J -> A胜        场次:A PK D -> D胜     场次:A PK F -> A胜
选手【G】的比赛......场次:G PK J -> G胜        场次:G PK D -> G胜     场次:G PK F -> F胜
A 胜场: 2
B 胜场: 0
C 胜场: 0
D 胜场: 2
E 胜场: 0
F 胜场: 2
G 胜场: 2
H 胜场: 0
I 胜场: 0
J 胜场: 1
K 胜场: 0
L 胜场: 0
前三名信息如下:
第一名 id:10001 name:A 总胜场:2
第二名 id:10004 name:D 总胜场:2
第三名 id:10006 name:F 总胜场:2
=============================
0、退出
1、开始游戏
2、查看历史比赛结果
3、清空历史比赛记录
=============================