从文本文件中随机配对团队两次

Randomly Pair Teams From Text File Twice

我是 C 编程的新手,我正在尝试完成这个随机配对程序,但我在启动它时遇到了问题。基本上,该程序需要从文本文件中读取 3 个字母的球队名称,将它们放入一个数组中,然后随机将球队配对。有两轮比赛,第二轮比赛不能重赛。此外,来自同一所学校的球队不能互相比赛。来自同一所学校的团队在文本文件中共享相同的第一个字符和行。任何人都可以帮助我如何编写代码吗? :) 这是名为 provisions.txt:

的文本文件

ABA ABC ABD ABG
BAA BAB BAC
CAB CBA
DAB DBC DBE DBA
EAB
FAB FAC FAA
GAB GAA
HAA HAB
IAB
JAA
KAA
LAL LAB
MAA MAB MBA MUM
NAN NAB

到目前为止我的代码是:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>

int main()
{
// Read characters from text file into array
FILE *file = fopen("provision.txt", "r");

char teamList[115];
char teams[32][4];  // Holds team names
int i;

for(i = 0; i < 32; i++){
    fscanf(file, "%s", teams[i]);
}

for(i = 0; i < 32; i++){
        printf("%s \n", teams[i]);  // Test to make sure teams are read in
}

// Clean up
fclose(file);

return 0;
}

如果可能,我想将两轮的输出存储在名为 round1_pairings.txt 和 round2_pairings.txt 的文本文件中。

本程序试图解决一些微妙的问题,例如随机选择偏差、退出死胡同尝试等。如果给定回合由于不足而无法配对,则不能保证终止来自其他学校的团队,这更有可能出现在更多轮数中(不太可能只有两轮和很多学校)。

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define NAMELEN 3
#define ROUNDS 2
#define RETRIES 10 // max attempts before restarting matching                                                           

#define STR_HELPER(x) #x //                                                      
#define STR(x) STR_HELPER(x)
#define NAMEPRINTF "%" STR(NAMELEN) "s"

typedef char team_t[NAMELEN + 1];

typedef struct
{
    team_t team;
    team_t opponents[ROUNDS];
} pairing_t;

// the first round is round=0                                                                                           
// when round>0, prior round matches will be prevented from recurring                                                   
void make_matches(pairing_t* pairings, size_t count, size_t round)
{
    // clip random() range to avoid bias toward first teams                                                             
    long randmax = LONG_MAX - LONG_MAX % count - 1;
  begin:
    for(size_t ii = 0; ii < count; ++ii) {
        if(pairings[ii].opponents[round][0]) continue; // already paired                                                
        //printf("matching: %s\n", pairings[ii].team);                                                                  
        unsigned retry = 0;
        while(retry < RETRIES) {
            long rand = random();
            if (rand > randmax) continue; // avoid bias                                                                 
            pairing_t *opp = &pairings[rand % count];
            if(opp->team[0] == pairings[ii].team[0]) { // same school                                                   
                ++retry;
                continue;
            }
            if(opp->opponents[round][0]) continue; // already paired                                                    
            size_t prior;
            for(prior = 0; prior < round; ++prior) {
                if(!memcmp(opp->team, pairings[ii].opponents[prior], sizeof(team_t))) {
                    break;
                }
            }
            if(prior != round) continue; // duplicate pairing                                                           
            //printf("match made: %s %s\n", opp->team, pairings[ii].team);                                              
            memcpy(pairings[ii].opponents[round], opp->team, sizeof(team_t));
            memcpy(opp->opponents[round], pairings[ii].team, sizeof(team_t));
            break;
        }
        if(retry == RETRIES) { // matching failed, start again                                                          
            for(size_t ii = 0; ii < count; ++ii) {
                memset(pairings[ii].opponents[round], 0, sizeof(team_t));
            }
            goto begin;
        }
    }
}

int main(void)
{
    srandom(time(NULL));

    FILE *file = fopen("provision.txt", "r");

    size_t capacity = 15; // arbitrary initial size                                                                     
    pairing_t *pairings = calloc(capacity, sizeof(pairing_t));
    if(!pairings) abort();

    size_t count = 0;
    while(fscanf(file, NAMEPRINTF, pairings[count].team) != EOF) {
        //printf("%s\n", pairings[count].team);                                                                         
        ++count;
        if(count >= capacity) { // expand array                                                                         
            capacity *= 2;
            pairings = realloc(pairings, capacity * sizeof(pairing_t));
            if(!pairings) abort();
            memset(&pairings[count], 0, (capacity - count) * sizeof(pairing_t));
        }
    }

    for(size_t round = 0; round < ROUNDS; ++round) {
        make_matches(pairings, count, round);
    }

    for(size_t ii = 0; ii < count; ++ii) {
        printf("%s %s %s\n", pairings[ii].team, pairings[ii].opponents[0], pairings[ii].opponents[1]);
    }

    free(pairings);
    fclose(file);
    return 0;
}

输出是一个简单的 table,包含三列:参加比赛的球队、他们的第一个对手和他们的第二个对手。我相信你能弄清楚如何根据需要将它们写入单独的文件。