Algorithm 多人游戏锦标赛生成器

Algorithm 多人游戏锦标赛生成器,algorithm,Algorithm,如果我有一个多人游戏,每场游戏需要6个人,并且我有100名锦标赛参与者,那么我可以使用什么样的最佳算法来为每个人分配游戏,以便每个人至少玩一次,同时尽量减少玩家玩他们已经玩过的人的游戏数量 本质上,有没有一种方法可以为多人游戏生成循环赛?我正在考虑将此算法用于卡坦锦标赛。解决相关社交高尔夫问题的方法之一是局部搜索。提出的一些方法非常复杂。下面的C程序不可用;它选择一个随机的初始时间表,并进行随机交换,不会增加不玩的玩家对的数量。100名玩家和6人一组至少需要21轮(有些玩家坐了一轮,然后需要ce

如果我有一个多人游戏,每场游戏需要6个人,并且我有100名锦标赛参与者,那么我可以使用什么样的最佳算法来为每个人分配游戏,以便每个人至少玩一次,同时尽量减少玩家玩他们已经玩过的人的游戏数量


本质上,有没有一种方法可以为多人游戏生成循环赛?我正在考虑将此算法用于卡坦锦标赛。

解决相关社交高尔夫问题的方法之一是局部搜索。提出的一些方法非常复杂。下面的C程序不可用;它选择一个随机的初始时间表,并进行随机交换,不会增加不玩的玩家对的数量。100名玩家和6人一组至少需要21轮(有些玩家坐了一轮,然后需要ceil((100-1)/(6-1))=20轮才能与每个人比赛),因此27轮离最佳值不远,尽管我相信使用更复杂的优化技术可以做得更好

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

enum {
  GAMENUMPLAYER = 6,
  NUMPLAYER = 100,
  ROUNDNUMPLAYER = NUMPLAYER - NUMPLAYER % GAMENUMPLAYER,
  NUMROUND = 27
};

static int Schedule[NUMROUND][NUMPLAYER];
static int Numgame[NUMPLAYER][NUMPLAYER];
static int Numunplayed = (NUMPLAYER * (NUMPLAYER - 1)) / 2;

static void count(int r, int i, int delta) {
  int start;
  int stop;
  int j;
  if (i >= ROUNDNUMPLAYER) return;
  start = i - i % GAMENUMPLAYER;
  stop = start + GAMENUMPLAYER;
  for (j = start; j < stop; j++) {
    int p;
    int q;
    if (j == i) continue;
    p = Schedule[r][i];
    q = Schedule[r][j];
    if (q < p) {
      int t;
      t = p;
      p = q;
      q = t;
    }
    if (Numgame[p][q] == 0) Numunplayed--;
    Numgame[p][q] += delta;
    if (Numgame[p][q] == 0) Numunplayed++;
  }
}

static void swap(int r, int i, int j) {
  int t;
  count(r, i, -2);
  count(r, j, -2);
  t = Schedule[r][i];
  Schedule[r][i] = Schedule[r][j];
  Schedule[r][j] = t;
  count(r, i, 2);
  count(r, j, 2);
}

static void validate(void) {
  int nu;
  int q;
  nu = 0;
  for (q = 0; q < NUMPLAYER; q++) {
    int p;
    for (p = 0; p < q; p++) {
      int ng;
      int r;
      ng = 0;
      for (r = 0; r < NUMROUND; r++) {
        int i;
        for (i = 0; i < ROUNDNUMPLAYER; i++) {
          int k;
          if (Schedule[r][i] != p) continue;
          for (k = 0; k < GAMENUMPLAYER; k++) {
            if (Schedule[r][i - i % GAMENUMPLAYER + k] == q) ng++;
          }
        }
      }
      assert(ng * 2 == Numgame[p][q]);
      assert(Numgame[p][q] >= 0);
      if (Numgame[p][q] == 0) nu++;
    }
  }
  assert(nu == Numunplayed);
}

int main(void) {
  int r;
  for (r = 0; r < NUMROUND; r++) {
    int i;
    for (i = 0; i < NUMPLAYER; i++) {
      int j;
      j = rand() % (i + 1);
      Schedule[r][i] = Schedule[r][j];
      Schedule[r][j] = i;
    }
    for (i = 0; i < NUMPLAYER; i++) count(r, i, 1);
  }
  while (Numunplayed > 0) {
    int r;
    int i;
    int j;
    int previous;
    r = rand() % NUMROUND;
    i = rand() % NUMPLAYER;
    j = rand() % NUMPLAYER;
    previous = Numunplayed;
    swap(r, i, j);
    if (Numunplayed < previous) {
      fprintf(stderr, "%d\n", Numunplayed);
    } else if (Numunplayed > previous) {
      swap(r, i, j);
    }
  }
  for (r = 0; r < NUMROUND; r++) {
    int i;
    for (i = 0; i < NUMPLAYER; i++) {
      if (i > 0) putchar(i % GAMENUMPLAYER == 0 ? ';' : ',');
      printf("%d", Schedule[r][i]);
    }
    putchar('\n');
  }
  return EXIT_SUCCESS;
}
#包括
#包括
#包括
枚举{
GAMENUMPLAYER=6,
numlayer=100,
ROUNDNUMPLAYER=NUMPLAYER-NUMPLAYER%GamenNumplayer,
NUMROUND=27
};
静态int调度[NUMROUND][NUMPLAYER];
静态int Numgame[numlayer][numlayer];
静态int numplayed=(numlayer*(numlayer-1))/2;
静态无效计数(整数r、整数i、整数增量){
int启动;
int stop;
int j;
如果(i>=ROUNDNUMPLAYER)返回;
开始=i-i%GAMENUMPLAYER;
停止=开始+游戏玩家;
对于(j=开始;j<停止;j++){
INTP;
int-q;
如果(j==i)继续;
p=附表[r][i];
q=附表[r][j];
if(q=0);
如果(Numgame[p][q]==0)nu++;
}
}
断言(nu==Numunplayed);
}
内部主(空){
INTR;
对于(r=0;r0){
INTR;
int i;
int j;
int-previous;
r=rand()%NUMROUND;
i=rand()%NUMPLAYER;
j=rand()%NUMPLAYER;
上一个=纽曼;
互换(r,i,j);
if(Numunplayed<上一个){
fprintf(stderr,“%d\n”,Numunplayed);
}else if(Numunplayed>previous){
互换(r,i,j);
}
}
对于(r=0;r0)putchar(i%GAMENUMPLAYER==0?';':',');
printf(“%d”,附表[r][i]);
}
putchar('\n');
}
返回退出成功;
}

现在这是一个有趣的问题!你为什么不玩所有可能的1.192B游戏呢?(笑话)。为了清楚起见,假设玩家1在第一场比赛中与玩家2-6打球。稍后,玩家1必须与所有玩家7-100玩不同的游戏才能完成循环赛。对的这对其他所有玩家来说都是一样的。是否有回合,并且同一个玩家不能在一轮中玩两次,请说明这一点,否则你的问题太广泛了jch:正确。维克拉姆:有回合,同一名球员不能在一轮中打两次。这会有很大的不同吗?非常好的解决方案。NUMROUND=27是接近21的合理猜测吗?我翻译成Java来执行。@jch我用试错法设置它——再低一点,我就等不及收敛了。