从文本文件中随机配对两次[关闭]

问题描述 投票:0回答:1

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

Ab abak ab abg 巴巴巴巴 驾驶室 按dab duck dab 安倍晋三 Fab挂 加布 是中心 磅 展望 的 红色实验室 在Ma Mba妈妈 不,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的文本文件中。

c random readfile
1个回答
0
投票

该程序试图解决一些微妙的问题,如随机选择偏差,退出死胡同匹配尝试等。由于其他学校的团队不足,无法保证在给定轮次无法配对的情况下终止,更有可能发生在更高数量的轮次(不太可能只有两轮和许多学校)。

#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 // http://stackoverflow.com/a/5459929/4323                                                     
#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;
}

输出是一个简单的表格,有三列:球队比赛,他们的第一个对手,以及他们的第二个对手。我相信你可以根据需要弄清楚如何将它们写成单独的文件。

© www.soinside.com 2019 - 2024. All rights reserved.