【问题标题】:I'm trying to assign random integers to struct members, but it doesn't work properly我正在尝试将随机整数分配给结构成员,但它无法正常工作
【发布时间】:2014-02-21 22:43:36
【问题描述】:

我正在执行一项任务,我必须将玩家随机放置在具有随机坐标的场地上,但这些坐标必须是唯一的,否则它们必须重新生成。我正在尝试随机化整数并将它们分配给结构成员。但是,根据我的教授的说法,我现在正在做的事情似乎并不正常。这是结构:

struct player {

   int x;
   int y;
   int direction;
   int id;
   int presence;
};

这是我的两个数组,一个用于场地,一个用于场地上的球队规模:

 int field [25][25];
 struct player team [25];

这是我可能犯了错误的函数部分:

int main (){

   int i;
   int j;
   int randx, randy;
   int SIZE_TEAM = 25;


   srand (time(NULL));

    for (i = 0; i < SIZE_TEAM; i++){

       randx = (rand () % 25); <-- Randomizing row position
       randy = (rand () % 25); <-- Randomizing column position

       while (field[randx][randy] != 0){ <-- While loop occurs if position in field is taken.
            randx = (rand () % 25);      <-- In this case, the coordinates are regenerated.
            randy = (rand () % 25);
       }
     team [i].x = randx; <--Where the mistake might lie
     team [i].y = randy; <--Where the mistake might lie
     team [i].id = i + 1;
     team [i].presence = 1;
     field [team [i].x][team [i].y] = team [i].id; <--Where the mistake might lie
  }

我不确定将随机生成的值分配给相关播放器后如何“锁定”它们。你觉得我给玩家分配位置的算法不正确吗?

另外,这是我发布的另一个问题的删节版,但是那个问题太长了,没有人愿意帮助我。

【问题讨论】:

  • 没有必要在循环中重复调用rand() 来搜索未使用的值。 1. 制作一个连续的升序坐标列表。 2 使用适当的洗牌算法(Fisher-Yates、Knuth 等)对其进行洗牌。 3. 通过单个枚举将打乱的坐标分配给玩家。那它。除此之外,在允许运行当前算法之前将 field 初始化为零显然很重要。
  • “连续升序坐标列表”和“单个枚举”是什么意思?另外,建议我不要在我的作业中使用 shuffle,因为我们还没有学会。
  • @Michformer 基本上,contiguous ascending coordinate list 是在允许的坐标范围内不断增加的坐标列表,然后您将它们的顺序打乱,因此它们不再上升。接下来,您一次性分配坐标,也称为single enumeration。至于不允许使用 shuffle,为什么不自己查一下自己学呢?这样你会学到新的东西!
  • It means something like this. 将代码本地化以洗牌坐标并将它们保存在数组中还有一个额外的好处,即您可以清除场地、重新洗牌相同的坐标列表并重新定位所有玩家。最重要的是,它不依赖于您排除随机值。您可以全部使用它们(在随机播放期间,而不是在逐项生成期间)。无论如何,只是一个建议。
  • @WhozCraig:这可能更有效(尚未测试过),但对于这项任务来说似乎是不必要的复杂性。 Michformer:你的代码在什么方面不起作用?

标签: c arrays random position assign


【解决方案1】:

嗯 --- 我不确定这是否是问题的真正原因 --- 但我注意到一个问题:

没有地方初始化字段上的地方的值。所有变量都需要在第一次使用它们的值之前进行初始化。您有一个名为“field”的二维数组,其中您刚刚assume 的每个元素一开始都是零——但您不知道这一点,因为您从未将这些元素设置为零。您需要一个代码,将这个二维数组的所有元素设置为它们的初始值开始让球员上场之前。

关于此声明,我可能会添加(作为旁白):

int SIZE_TEAM = 25;

与其在主函数中将其设为整数,不如将其声明为全局宏——像这样...

int field [25][25];
#define SIZE_TEAM 25
struct player team [SIZE_TEAM];

这样,如果您必须改变团队的规模,您只需在一处而不是两处进行更改。

【讨论】:

  • field 可能如果它是全局或静态的,则初始填充为零,但如果它是本地自动的,则未指定为零,并且肯定会赢如果在没有清除的情况下重做,那么在初始人口之后就不是这样了。我怀疑场地与球员的分歧是有目的的(即,您可以在保持相同球员人数的同时扩大或缩小场地,25人,反之亦然。他们很可能是故意分开的。但我确实怀疑这可能是设置问题。
  • 我已将字段初始化为在我的问题中未提及的函数中到处都是 0
【解决方案2】:

按照@WhozCraig 建议的方式解决它实际上并不复杂:

static void random_permutation(int *x, int n)
{
    int i, r;
    /* mark all elements as "unset" */
    for (i = 0; i < n; i++) {
        x[i] = -1;
    }

    for (i = 0; i < n; i++)
    {
        /* start from a random value and find the first unset element */
        for (r = rand() % n; x[r] >= 0; r = (r + 1) % n)
            ;
        x[r] = i;
    }
}

#define SIZE_TEAM 25

int main (void)
{
    int randx[SIZE_TEAM], randy[SIZE_TEAM];
    srand (time(NULL));

    random_permutation(randx, SIZE_TEAM);
    random_permutation(randy, SIZE_TEAM);

    for (i = 0; i < SIZE_TEAM; i++) {
        int x = randx[i], y = randy[i];
        team[i].x = x;
        team[i].y = y;
        team[i].presence = 1;
        team[i].id = i + 1;
        field[x][y] = team[i].id;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多