如何在C中创建一个随机的2d数组,其值只重复两次

时间:2010-11-03 09:12:17

标签: c unique dynamic-arrays

我对c编程非常新,并且只做了if / else,循环,数组,指针,函数和结构。如果有人能告诉我如何创建一个包含随机时间的二维数组,我会很高兴,但是它的值只重复两次......

意思是例如:

1 2 3 6
8 7 4 5
7 5 6 3
2 1 4 8

实际上我需要数组为6x6,到目前为止,我已经到了这个阶段,这是行不通的:

int x,y;
int i,j;

srand (time(NULL));

for ( x=0 ; x<6 ; x++){
    for ( y=0 ; y<6 ; y++) {
        sBoard[x][y] = rand() %36;          /*randomization*/

        for ( i=0 ; i<6 ; i++){  /*trying to create an unique array*/
            for ( j=0 ; j<6 ; j++) {
                if ((sBoard[x][y] == sBoard[i][j])) {
                    x--;
                    y--;
                }
            }
        }
        printf ("%i",sBoard[x][y]);
    }
    printf("\n");
}

=============================================== ======================================== 我的讲师让我尝试使用if函数来检查值是否在矩阵的其他任何地方重复...这就是为什么我使用'if'...如果你能帮助我,我将非常感激.. 。 提前谢谢你......

4 个答案:

答案 0 :(得分:1)

问题是你的if-then块仍然不能保证唯一性水平。你必须有一个while循环才能让它正常工作。这个while循环理论上永远不会终止,并且(更有可能)每次运行时执行的时间会有很大的不同。

使用所有值填充二维数组可能会更容易,然后随机播放。您可以作弊,并将其视为一维数组,它仍将以相同的方式工作。这是一些伪代码:

pointer-to-array pArray;
for i = 0 to 35
    pArray[i] = i
numShuffle = 2;
for s = 1 to numShuffle
    for i = 0 to 35
        swap pArray[i] with pArray[random 0 to 34 - if equal, add 1]

这将保证不存在重复项,并且您的代码将始终花费相同的执行时间(而不是上面提到的while循环可能永远不会终止)。

您可以将numShuffle设置为1并获得有利的结果。如果你发现这是真的,你甚至不需要那个外循环。

答案 1 :(得分:0)

允许的值范围是多少?假设它不是太大,有些N,我建议使用以下算法:

  • seen初始化为N个int计数器的数组,指定每个值生成的时间。
  • 浏览目标2D数组,使用num生成数字rand
    • 如果seen[num]为2,请重新生成num并重试
    • 否则请增加seen[num]并将num放入2D数组的插槽中

当然,必须使用全零来初始化seen

如果数字范围很大(比如整个整数范围),我会使用哈希表而不是seen数组。

答案 2 :(得分:0)

我对以下内容有点困惑:2d数组是允许(a)包含两次最大值的特定值,还是(b)2d数组是否始终保持每个值两次?

(a):构建一个包含所有允许值的辅助数组,每个数组两次。然后生成一个随机数作为此辅助数组的索引,以选择其中一个数字并将其存储到所需的2d数组的“下一个”位置。不要忘记从辅助数组中删除所选的值。

(b):最初,您可以创建一个6x6数组,每个数组包含1到18的所有值。然后,通过每次迭代交换两个值来重新调整值。

编辑:关于您自己的方法和其他一些解决方案提案:我认为尝试错误方法并不是确保每个值(仅)存储两次的最佳方法。因为从理论上讲,它可能导致无限循环。是的,我知道,这不太可能发生,但在我看来,无论如何它都有点脏。我更喜欢具有确定性/持续执行时间的解决方案,以防止不必要的操作。

答案 3 :(得分:0)

首先,随机不排除重复本身 - 随机分布只是随机分布,没有均匀分布的集合,这意味着不会再出现任何项目。 所以我将(为简单起见)将6x6 2d阵列展平为36x 1d阵列,然后再重新组织。

所以使用1d数组,你可以循环遍历,并且对于每个位置,在do循环中,生成一个随机数,然后你可以有一个内部for循环,它遍历现有数组,从0到当前位置如果在其中一个位置看到随机数,请标记一个标记,表示已经看到它。这样你就可以用“while(notUnique)”结束do循环。

好的 - 告诉我代码!

int board1d[36];
int pos;
for(pos = 0; pos < 36; pos ++) {
  int newRand;
  int notUnique;
  do {
    int innerPos;
    notUnique = 0;
    newRand = rand() % 36;
    for(innerPos = pos; innerPos > 0 && notUnique==0; innerPos--) {
      notUnique = (newRand == board1d[innerPos]);
    }
  } while(notUnique);
  board1d[pos] = newRand;
}

如上所述,这可能意味着如果随机生成器生成重复的序列,则循环将花费更多周期。 随机集中无法保证均匀分布。