TSwangming 发表于 2020-7-14 16:16:00

如何以单循环赛制随机选出两两对战,每轮比赛胜者再次随机两两对战直至最后决出冠军

我的代码是输入比赛人数,是偶数的话,比如8,就先利用evenchoose函数将键盘输入的八位选手随即排序,两两为一组输出,每输出一组随机输入该组的winner并作为元素储存在winner[]数组中,这是第一轮。第二轮是将以第一轮的winner(共四位)为元素的数组winner[]进行evenchoose处理后,再两两为一组输出,每输出一组随机输入该组的winner并作为元素储存在winner[]数组中,这是第二轮。第三轮就是将第二轮的winner做和之前几轮的winner同样的操作,最后决出冠军champin。但是我的代码的执行结果是1.排序的结果并不随机,比如我输入了Bob Lisa Lily Bill Mike John Ann Sara八位选手,第一轮应该是随机的两两分组,Bob Lily和John Sara和Bill Lisa和Ann Mike这样的随机结果,但是我的运行结果是按顺序从第一个Bob直到Sara两两分组输出的,不知道我的程序哪里出错导致了这个结果?2.在执行到第二轮的时候,当输入第一组的winner后,比如是Bob,点回车直接输出了一个Bob,而不是手动输入第二组的winner,即使想手动输入也输不进去,我想知道这个是什么原因?#include <stdio.h>
#include <stdlib.h>
#include<time.h>
void evenchoose(char *p[],int b);
int main() {
      int i,j;int number;
      printf("number of gamers:");
      scanf("%d",&number);
      char *name;
      char winner;
      for(i=0;i<number;i++)
      {
            scanf("%s",name+i);
      }/*键盘输入最一开始各个选手的名字*/
      if(number%2==0)
      {evenchoose(name,number);
         for( i=0; i<number; i++) {
                printf("%-8s",name);
                if( (i+1)%2==0 ) {
                        printf("\n");
                        printf("the winner of this one match is:");
                        int k=(i+1)/2;
                        scanf("%s",winner);

                }/*第一轮结束*/
      }   number=number/2;
            evenchoose(winner,number);

            while(number!=2)
            {for( i=0; i<number; i++) {
                printf("%-4s",winner);
                if( (i+1)%2==0 ) {
                        printf("\n");
                        printf("the winner of this one match is:");
                        int k=(i+1)/2;
                        scanf("%s",winner);

                }number=number/2;
               evenchoose(winner,number);
      }


            }/*第二轮至倒数第二轮结束*/
            for( i=0; i<number; i++) {
                printf("%-4s",winner);
                if( (i+1)%2==0 ) {
                        printf("\n");
                        printf("the champin is:");
                        int k=(i+1)/2;
                        scanf("%s",winner);}

      }/*输入champin的名字后最后一轮结束*/}}
/*给数组随机排序的函数*/void evenchoose(char *p[],int b) {
      int j;
      int last=b-1;
      srand((unsigned)time(NULL));
      for(j=0; j<b-1; j++) {
                int random=rand()%b;
                char *temp=p;
                p=p;
                p=temp;
                last--;
      }
}
我的理想运行结果示例如下:
number of gamers:8
Bob Lily
the winner of this one match is:Bob
John Sara
the winner of this one match is:Sara
Bill Lisa
the winner of this one match is:Bill
Ann Mike
the winner of this one match is:Mike
Bob Bill
the winner of this one match is:Bob
Sara Mike
the winner of this one match is:Sara
Bob Sara
the champin is:Bob
(冒号后面都是程序运行时要键盘输入的)





TSwangming 发表于 2020-7-14 16:20:30

我的程序运行还有乱码现象要怎么解决呢?

赚小钱 发表于 2020-7-14 17:52:42

第一反应是 merkle tree

如果是我做的话,使用面向过程的做法就是,声明两个队列 Q0, Q1

1. 对所有选手进行一次 shuffle,全部进入 Q0
2. 每次从 Q0 中取出两个选手进行 Battle,胜者进入 Q1, 如果只从 Q0 取出一个人,即轮空,直接进入 Q1
3. 队列从满到空表示一个 Round,当 Round 结束之后,另 Q0 = Q1, Q1 置空,重复2
4. 如果 Q0 只有一个选手,即为冠军

懒得写代码。

如果是面向对象,就去定义 Player, Round, Battle 等类

TSwangming 发表于 2020-7-14 18:04:56

赚小钱 发表于 2020-7-14 17:52
第一反应是 merkle tree

如果是我做的话,使用面向过程的做法就是,声明两个队列 Q0, Q1


我刚刚去搜了一下shuffle发现那个好像不是C语言的东西,我目前只学过C语言{:5_100:}。我想问一下我的代码要怎么改呢?源代码搞了好久,不太想变换做法{:9_221:}

赚小钱 发表于 2020-7-14 20:16:50

本帖最后由 赚小钱 于 2020-7-14 20:20 编辑

TSwangming 发表于 2020-7-14 18:04
我刚刚去搜了一下shuffle发现那个好像不是C语言的东西,我目前只学过C语言。我想问一下我的代码 ...

#include <time.h>
#include <stdlib.h>

void shuffle(int *array, int length) {
    time_t t;
    // 初始化随机因子,让每次执行具有一定的随机性
    srand((unsigned int) time(&t));
    for (int i = 0; i < length; i++) {
      // 找到一个随机的位置 j 与第 i 个位置交换
      int j = (rand() % (length - i)) + i;

      int temp = array;
      array = array;
      array = temp;
    }
}

TSwangming 发表于 2020-7-14 23:10:25

赚小钱 发表于 2020-7-14 17:52
第一反应是 merkle tree

如果是我做的话,使用面向过程的做法就是,声明两个队列 Q0, Q1


答主可以发一个完整代码吗,时间比较紧急,如果可以的话太谢谢答主了{:9_221:}

赚小钱 发表于 2020-7-15 11:03:27

TSwangming 发表于 2020-7-14 23:10
答主可以发一个完整代码吗,时间比较紧急,如果可以的话太谢谢答主了

>= c++ 17

#include <string>
#include <queue>
#include <optional>
#include <iostream>   // std::cout
#include <algorithm>    // std::shuffle
#include <vector>       // std::vector
#include <random>       // std::default_random_engine
#include <chrono>       // std::chrono::system_clock

class Player {
public:
    Player(std::string name) : name(name) {}

    std::string name;
};

class Battle {
public:
    Battle(Player p1, Player p2) : p1(p1), p2(p2) {}

    Player battle() {
      time_t t;
      srand((unsigned int) time(&t));
      if ((rand() & 0x01) != 0) {
            return p1;
      }
      return p2;
    }

private:
    Player p1;
    Player p2;
};

class Round {
public:
    Round(int index) {
      this->next == nullptr;
      this->index = index;
    }

    void enter(Player p) {
      this->players.push(p);
    }


    std::optional<Player> peak() {
      if (this->players.empty()) {
            return std::nullopt;
      }
      auto result = this->players.front();
      this->players.pop();
      return std::optional<Player>(result);
    }

    bool finished() {
      return this->players.size() <= 1;
    }

    Round *start() {
      if (this->next == nullptr) {
            this->next = new Round(this->index + 1);
      }
      while (true) {
            auto player1_result = this->peak();
            if (!player1_result.has_value()) {
                return this->next;
            }
            Player p1 = player1_result.value();

            auto player2_result = this->peak();
            if (!player2_result.has_value()) {
                printf("Round: %2d Player: %s 轮空\n", this->index, p1.name.c_str());
                this->next->enter(p1);
                return this->next;
            }
            Player p2 = player2_result.value();
            Battle battle(p1, p2);
            Player winner = battle.battle();
            printf("Round: %2d %s vs. %s Winner: %s\n",
                   this->index, p1.name.c_str(), p2.name.c_str(), winner.name.c_str());
            this->next->enter(winner);
      }
    }

private:
    std::queue<Player> players;
    Round *next;
    int index;
};


int main() {
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    std::default_random_engine e(seed);

    std::vector<std::string> players = {"Ada", "Barbara", "Calista", "Daisy", "Eartha",
                                        "Faithe", "Gabrielle", "Hannah", "Ida", "Jacqueline"};
    std::shuffle(players.begin(), players.end(), e);

    Round *round = new Round(0);
    for (auto it = players.begin(); it != players.end(); it++) {
      round->enter(Player(*it));
    }

    while (!round->finished()) {
      auto next_round = round->start();
      round = next_round;
    }

    return 0;
}

赚小钱 发表于 2020-7-15 11:06:22

本帖最后由 赚小钱 于 2020-7-15 11:09 编辑

赚小钱 发表于 2020-7-15 11:03
>= c++ 17

运行结果, 在每一个 Round 开始对所有运动员 shuffle 一下会更好。交给你自己修改吧
Round:0         Ada vs.      Hannah Winner:      Hannah
Round:0   Calista vs.      Eartha Winner:      Eartha
Round:0       Daisy vs.      Faithe Winner:      Faithe
Round:0Jacqueline vs.   Gabrielle Winner:   Gabrielle
Round:0         Ida vs.   Barbara Winner:   Barbara
Round:1      Hannah vs.      Eartha Winner:      Eartha
Round:1      Faithe vs.   Gabrielle Winner:   Gabrielle
Round:1                           Player:   Barbara 轮空
Round:2      Eartha vs.   Gabrielle Winner:   Gabrielle
Round:2                           Player:   Barbara 轮空
Round:3   Gabrielle vs.   Barbara Winner:   Barbara

TSwangming 发表于 2020-7-15 11:59:02

赚小钱 发表于 2020-7-15 11:06
运行结果, 在每一个 Round 开始对所有运动员 shuffle 一下会更好。交给你自己修改吧

太感谢了,剩下的我自己完善{:5_95:}
页: [1]
查看完整版本: 如何以单循环赛制随机选出两两对战,每轮比赛胜者再次随机两两对战直至最后决出冠军