C语言实现世界杯的小组分组。参赛队:英格兰、法国、德国、意大利、西班牙、荷兰、葡萄牙、克罗地亚、土耳其、俄罗斯、瑞典、捷克、塞尔维亚、加纳、科特迪瓦、突尼斯、尼日利亚、喀麦隆、日本、韩国、澳大利亚、伊朗、美国、墨西哥、哥斯达黎加、洪都拉斯、巴西、阿根廷、巴拉圭、智利、乌拉圭、厄瓜多尔。
世界杯的小组分组规则如下:八只种子球队,是:乌拉圭队、西班牙队、德国队、阿根廷队、哥伦比亚队、比利时队、瑞士队、巴西队。
这八只球队一定分别在A——H八个组中(八只球队不能碰面)。小组分为A——H一共八个小组。分组结果按行输出。每个小组四个球队。(参考循环赛)。
提示:1.可以用链表指针或者结构体数组;2.随机数;3.也许你能做到我没有想到的
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define TreeHeigh 5
typedef struct tree_s tree_t;
struct tree_s {
int Score;
int Heigh;
tree_t *Left;
tree_t *Right;
const char *Name;
};
const char *Other[] =
{
"英格兰","意大利","葡萄牙","克罗地亚","土耳其","瑞典","捷克","塞尔维亚","加纳",
"科特迪瓦","突尼斯","尼日利亚","喀麦隆","日本","韩国","澳大利亚","伊朗","美国",
"墨西哥","哥斯达黎加","洪都拉斯","巴拉圭","智利","厄瓜多尔"
};
const char *Send[] = { "乌拉圭","西班牙","德国","阿根廷","荷兰","法国","巴西","俄罗斯" };
int F_Send[8];
int F_Other[24];
void tree_init(tree_t **root, int heigh);
void tree_print(tree_t *root);
int main(void)
{
tree_t *root;
int heigh;
heigh = 0;
root = NULL;
tree_init(&root, heigh);
tree_print(root);
return 0;
}
void tree_init(tree_t **root, int Heigh)
{
int f;
static int g = -1;
srand((unsigned)time(NULL));
if (NULL == *root)
{
tree_t *item = (tree_t *)malloc(sizeof(tree_t));
if (NULL == item)
exit(EXIT_FAILURE);
item->Left = NULL;
item->Right = NULL;
item->Name = NULL;
item->Score = -1;
item->Heigh = Heigh;
*root = item;
}
if (TreeHeigh == (*root)->Heigh)
{
++g;
if (0 == g % 4)
{
while (1)
{
f = rand() % 8;
if (0 == F_Send[f])
{
(*root)->Name = Send[f];
F_Send[f] = 1;
break;
}
}
}
else
{
while (1)
{
f = rand() % 24;
if (0 == F_Other[f])
{
(*root)->Name = Other[f];
F_Other[f] = 1;
break;
}
}
}
}
if (TreeHeigh == Heigh)
return;
tree_init(&(*root)->Left, Heigh + 1);
tree_init(&(*root)->Right, Heigh + 1);
}
void tree_print(tree_t *root)
{
static int g = 0;
static char ch = 'A';
if (NULL == root)
return;
if (NULL != root->Name)
{
if (0 == g % 4)
printf("%c\n", ch++);
printf("%s ", root->Name);
++g;
if (0 == g % 2)
printf("\n");
}
tree_print(root->Left);
tree_print(root->Right);
}
能够正常运行,但功能不全面
运行环境为Visual Studio 2022
再上面代码的基础上添加一个随机分组后模拟比赛进行淘汰赛,输出排名的功能
假设八个小组均为种子球队出线晋级下一轮,目前需要进行八支球队随机分四组进行八进四赛制,四组决出胜者后再分组进行四进二,最后进行决赛。输出世界杯比赛排名。
因为不知道谁会胜利就随机模拟吧,最后按照结果输出前四名(能按结果排序输出前八名更好)
代码两百行左右,越多越好,感谢各位
在你代码基础上增加了功能,通过结构体数组实现,通过递归进行计算,从8进4、4进2,2进1为止,每轮比赛输出比赛的双方及结果。最后输出总排名,运行结果如下:
代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
const char* Other[] =
{
"英格兰","意大利","葡萄牙","克罗地亚","土耳其","瑞典","捷克","塞尔维亚","加纳",
"科特迪瓦","突尼斯","尼日利亚","喀麦隆","日本","韩国","澳大利亚","伊朗","美国",
"墨西哥","哥斯达黎加","洪都拉斯","巴拉圭","智利","厄瓜多尔"
};
const char* Send[] = { "乌拉圭","西班牙","德国","阿根廷","荷兰","法国","巴西","俄罗斯" };
int F_Send[8];
int F_Other[24];
//定义数据结构
typedef struct _teamnode
{
int id; //球队编号,这个没太大影响
char name[20];
}TeamNode;
void group();
void startgame();
int main(void)
{
srand((unsigned int)time(NULL));
//分组
group();
printf("\n\n----------------晋级赛------------------\n");
startgame();
system("pause");
return 0;
}
void group()
{
TeamNode teams[8][4];
int flag[24]={0};
int i,j;
int index;
char ch = 'A';
//将8个种子队分别插入8个小组
for(i=0;i<8;i++)
{
strcpy(teams[i][0].name,Send[i]);
}
//将21个球队分配给每个小组
for(i=0;i<7;i++)
{
for(j=1;j<4;j++)
{
while(1)
{
index = rand()%24;
//判断index对应的小队是否已经被分配
if(flag[index] == 0)
{
flag[index] =1;
break;
}
}
teams[i][j].id = index;
strcpy(teams[i][j].name,Other[index]);
}
}
//剩余的3个球队分配给最后一个小组,这里剩余3个不再用随机数,是因为当剩余的数量较少时,通过随机数得到正确的位置的概率会极低
j = 1;
for(i=0;i<24;i++)
{
if(flag[i]==0)
{
teams[7][j].id = i;
strcpy(teams[7][j].name,Other[i]);
flag[i] = 1;
j++;
}
if(j== 4) break;
}
//显示分组
for(i=0;i<8;i++)
{
printf("%c组:\n",(char)(ch+i));
for(j=0;j<4;j++)
{
printf(" %s",teams[i][j].name);
if(j==1 || j==3)
printf("\n");
}
printf("\n");
}
}
//两两分组比赛
void game(TeamNode teams[], int nmbTeams)
{
int i, j, t;
int index1,index2;
TeamNode tmp;
TeamNode arr[32];
if (nmbTeams == 1 || nmbTeams == 0)
{
return;
}
//标识球队的状态
t = nmbTeams;
while (t)
{
index1 = rand() % t; //得到第一支球队
//获取第一支球队的对手
while (1)
{
index2 = rand() % t;
if (index2 != index1)
break;
}
//将这两只球队移动到数组末尾
tmp = teams[t - 2];
teams[t - 2] = teams[index1];
teams[index1] = tmp;
tmp = teams[t - 1];
teams[t - 1] = teams[index2];
teams[index2] = tmp;
t -= 2;
}
//输出比赛的的球队,并通过随机数设置获胜的球队
printf("%d进%d比赛\n", nmbTeams, nmbTeams / 2);
for (i = 0; i < nmbTeams-1; i += 2)
{
printf("%s VS %s ", teams[i].name, teams[i + 1].name);
index1 = rand() % 2; //获取0到1的随机数,0表示前面的球队胜利,1表示后面的球队胜利
if (index1 == 1) //交换两个球队的位置,并输出结果
{
printf("%s晋级\n", teams[i + 1].name); //将晋级的球队放在前面
tmp = teams[i];
teams[i] = teams[i + 1];
teams[i + 1] = tmp;
}
else
printf("%s晋级\n", teams[i].name);
}
//将所有获胜的球队 放在数组的最前面
j = 0;
for(i=1;i<nmbTeams;i+=2)
arr[j++] = teams[i];
j=0;
for(i=0;i<nmbTeams;i+=2)
teams[j++] = teams[i];
for(j=0;j<nmbTeams/2;j++)
teams[nmbTeams/2+j] = arr[j];
//递归,直到得出总冠军
game(teams, nmbTeams / 2);
}
void startgame()
{
//生成球队数组,只考虑种子球队
TeamNode teams[8];
int i, nmbTeams = 8;
for (int i = 0; i < nmbTeams; i++)
{
teams[i].id = i + 1;
strcpy(teams[i].name, Send[i]); //只考虑种子球队
}
//每两个球队进行淘汰赛
game(teams, nmbTeams);
//输出最后的排名
printf("\n\n--------------排名---------------\n");
for (i = 0; i < nmbTeams; i++)
printf("%-2d %s\n", i + 1, teams[i].name);
}
如果全部都是淘汰赛,其实相对好模拟,直接用数组操作即可。因为只需要用数组记录队的ID即可,可以通过ID查询到原始队伍名称。
按现在的规则,只能输出 1、2和并列3名吧,没有说3、4名有比赛(当然添加一场比赛模拟也是可以的)。
分组其实用洗牌算法,种子队洗牌随机排序,其它队洗牌随机排序,然后依序取种子1队,其它3队组成一组,可以再在组内随机排序(意义不大,因为其他3队本身就是乱序的)。
因为后面比赛是淘汰赛,相对简单,对于小组赛,如果也是淘汰赛,也简单,如果是循环赛相对复杂!
对于淘汰赛,模拟得到0或者1分别表示2队中前序或者后序队伍获胜,把其对应ID写入下一轮待比赛队伍即可。
至于种子队全部进入第2轮,因为种子队ID一定,且其和最小,所以直接比较第二轮待进行队伍ID和是否为定值即可判断,如果是,再排序一次(其实这个分组的时候已经排序过,意义不大的)。
这样其实队伍ID可以一直在一个数组中,总是数组中2N与2N+1的队伍进行比赛淘汰,N是等待比赛队伍总数的一半。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
const char* Name[32]={"乌拉圭","西班牙","德国","阿根廷","荷兰","法国","巴西","俄罗斯","英格兰","意大利","葡萄牙","克罗地亚","土耳其","瑞典","捷克","塞尔维亚","加纳",
"科特迪瓦","突尼斯","尼日利亚","喀麦隆","日本","韩国","澳大利亚","伊朗","美国","墨西哥","哥斯达黎加","洪都拉斯","巴拉圭","智利","厄瓜多尔"};
void sortTerm(unsigned int * IDArr,unsigned int len){
/*利用洗牌算法,根据flen情况,对IDArr中前len元素进行随机排序*/
unsigned int i,t,r;
srand((unsigned)time(NULL));
for(i=0;i<len;i++){
t=IDArr[i];
r=rand()%len;
IDArr[i]=IDArr[r];
IDArr[r]=t;
}
}
void getGame(unsigned int *A) {
/*模拟2队伍比赛情况,2元素根据数组,胜利队为A[0],失败队为A[1]*/
unsigned int t,r;
srand((unsigned)time(NULL));
r=rand()%2;
if (r!=0){
t=A[0];
A[0]=A[1];
A[1]=t;
}
}
int main(void) {
unsigned int seedT[8]={0,1,2,3,4,5,6,7};
unsigned int otherT[24]={8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};
unsigned int tLen,i;
unsigned int gameStar[32],VEnd[16],LEnd[16];
/* 随机分组过程 */
sortTerm(seedT , 8);
sortTerm(otherT,24);
for (i=0;i<8;i++){
gameStar[i*4]=seedT[i];
gameStar[i*4+1]=otherT[i*3];
gameStar[i*4+2]=otherT[i*3+1];
gameStar[i*4+3]=otherT[i*3+2];
}
/*小组赛,淘汰赛要进行2轮,下面是第一轮*/
tLen=16;
for( i=0;i<tLen;i++){
getGame(gameStar+i*2);
VEnd[i] = gameStar[i*2];
LEnd[i] = gameStar[i*2+1];
}
for(i=0;i<tLen;i++){
gameStar[i]=VEnd[i];
gameStar[i+tLen]=LEnd[i];
}
/*小组赛,淘汰赛要进行2轮,下面是第二轮*/
tLen =8;
for( i=0;i<tLen;i++){
getGame(gameStar+i*2);
VEnd[i] = gameStar[i*2];
LEnd[i] = gameStar[i*2+1];
}
for(i=0;i<tLen;i++){
gameStar[i]=VEnd[i];
gameStar[i+tLen]=LEnd[i];
}
/* 小组赛后的重新分组 */
unsigned int sum=0;
for(i=0;i<8;i++){
sum=sum+gameStar[i];
}
if(sum==28) sortTerm(gameStar , 8);
/*四分之一决赛*/
tLen =4;
for( i=0;i<tLen;i++){
getGame(gameStar+i*2);
VEnd[i] = gameStar[i*2];
LEnd[i] = gameStar[i*2+1];
}
for(i=0;i<tLen;i++){
gameStar[i]=VEnd[i];
gameStar[i+tLen]=LEnd[i];
}
/*半决赛*/
tLen =2;
for( i=0;i<tLen;i++){
getGame(gameStar+i*2);
VEnd[i] = gameStar[i*2];
LEnd[i] = gameStar[i*2+1];
}
for(i=0;i<tLen;i++){
gameStar[i]=VEnd[i];
gameStar[i+tLen]=LEnd[i];
}
/* 决赛 */
getGame(gameStar);
/*所有比赛结果都保存到 gameStar 中的*/
/* 结果输出 */
printf("冠军:%s\n",Name[gameStar[0]]);
printf("亚军:%s\n",Name[gameStar[1]]);
printf("止步半决赛:%s,%s\n",Name[gameStar[2]],Name[gameStar[3]]);
printf("进入八强:%s,%s,%s,%s\n",Name[gameStar[4]],Name[gameStar[5]],Name[gameStar[6]],Name[gameStar[7]]);
printf("小组赛胜利过1场:%s,%s,%s,%s,%s,%s,%s,%s\n",Name[gameStar[8]],Name[gameStar[9]],Name[gameStar[10]],Name[gameStar[11]],Name[gameStar[12]],Name[gameStar[13]],Name[gameStar[14]],Name[gameStar[15]]);
}
需要用Java实现榨干你吗?