我有焦虑的网格充满照片网址.如何确保照片不会一起出现在c#中

Mik*_*ike 8 c# sorting algorithm

我基本上有一个网格,比方说100 x 100,其中充满了照片集的网址.其中一些是重复的,因为我可能只有50张照片,但我想复制它们以确保填充100 x 100网格.我随机用URL填充网格,然后显示它们很好.我遇到的问题是,显然有时具有相同URL的照片会随机地放在x轴或y轴上,或者有时两者都放在一起.

如何确保填充网格以使具有相同URL的这些图像尽可能远离,从而防止相同的两张照片彼此相邻.

任何帮助赞赏

麦克风

Gar*_*han 4

如果你真的想要“尽可能远离”,那么(1)我敢打赌你运气不好,(2)如果可以实现,它可能会产生看起来不是很随机的结果。但如果你想要的只是“距离有点远”,那也不算太糟糕。您可以执行以下几项操作。

(1)根据x,y坐标的奇偶性对网格位置进行分类:即奇数和偶数。将照片分成大小大致相等的四批。现在根据坐标的奇偶性从不同批次中进行选择。下面的代码(有点太“聪明”;抱歉)就是这样做的,模数错误和拼写错误。

System.Random rng = new System.Random();
for (int x=0; x<nx; ++x) {
  for (int y=0; y<ny; ++y) {
    k = ((x&1)<<1) + (y&1); // 0..3
    int n_photos_in_batch = (n_photos+3-k) >> 2;
    int photo_number = (rng.Next(0,n_photos_in_batch-1) << 2) + k;
    // use this photo
  }
}
Run Code Online (Sandbox Code Playgroud)

缺点:不会执行任何操作来将照片副本之间的距离移得比一步更远。稍微减少随机性,因为任何给定照片的所有副本都将位于固定的位置子集中;在某些情况下,这可能是可见的并且看起来相当愚蠢。

变化:我们基本上用 2x2 的图块覆盖网格,并限制每个图块中允许出现的照片范围。您可以使用更大的瓷砖或不同形状的瓷砖,或者以不同的方式排列它们。例如,如果您说k = ((x&1)<<1) ^ (y&3)您得到了以某种六边形图案排列的 2x2 瓷砖,这实际上可能比上面的版本更好。

(2) 循环网格中的位置(光栅顺序即可,尽管可能有更好的选择),并为每个位置选择一张 (a) 尚未出现在距离您正在查看的位置太近的照片,并且 ( b) 否则是随机的。下面的代码(同样,模错误和拼写错误)执行类似的操作,但对于大型网格,您可能希望使其更高效。

System.Random rng = new System.Random();
radius = MAX_RADIUS; // preferably not too big, so that the search isn't too slow
while ((2*radius+1)*(2*radius+1) >= n_photos) --radius; // gratuitously inefficient!
for (int x=0; x<nx; ++x) {
  for (int y=0; y<ny; ++y) {
    // which photos already appear too near to here?
    System.Collections.BitArray unseen = new System.Collections.BitArray(n_photos,True);
    for (x1=x-radius; x1<=x+radius; ++x1) {
      for (int y1=y-radius; y1<=y+radius; ++y1) {
        if (0 <= x1 && x1 < nx && 0 <= y1 && y1 < nx && (y1<y || (y1==y && x1<x))) {
          unseen[photos[x1,y1]] = False;
        }
      }
    }
    // now choose a random one of them
    int n_unseen = 0;
    for (int i=0; i<n_photos; ++i) if (unseen[i]) ++n_unseen;
    System.Debug.Assert(n_unseen>0, "no photos available");
    int j = rng.Next(0,n_unseen-1);
    for (int i=0; i<n_photos; ++i) {
      if (unseen[i]) {
        if (j==0) { photos[x,y] = i; break; }
        --j;
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

注意:这比选项 1 昂贵得多。当然,对 x1,y1 的有效性检查在这里效率很低。半径的选择也是如此。然而,如果您采用我即将列出的一些变体,这些明显更高效的版本可能会崩溃。按照目前的情况,如果照片少于 9 个,则不会执行任何操作来将照片分开。对于我使用的网格遍历顺序,半径的选择实际上完全是假的,因为永远不会超过 2r ^2+2r“排除”位置;同样,如果您以不同的顺序遍历网格,情况可能会发生变化。ETC。

变化:没有真正的理由说明您搜索的区域应该是正方形的。例如,圆形可能会更好。您可以通过一些额外的工作构建一个区域,该区域中的点始终与您的照片一样多(尽管如果您这样做,您将获得大部分周期性的照片模式,因此最好不要那么激进) )。最好在不同的位置处理网格条目——例如,从中心螺旋出。

(3) 上面的选项 2 将使照片在一定范围内保持唯一(大约与您拥有多少张不同照片一样大),但不关心将副本保持在远离该范围的范围内。相反,您可以确定在任意给定距离处拥有两张相同照片的情况有多糟糕,然后选择照片以最大程度地减少总体不良情况。这将比选项 2 更昂贵。我不会费心提供示例代码;你或许可以想出如何去做。

[编辑添加...]

(4) 这是(1) 主题的一个可爱的变体。当网格为正方形且其大小为 2 的幂时,它的效果最佳,但您可以调整它以使其更普遍地工作。无论您拥有多少照片,所需时间仅与网格大小成正比。对于每个位置 (x,y):对于某些 k,丢弃坐标中除底部 k 位以外的所有位置。对它们进行位反转并交织位,给出 0 到 2^(2k)-1 之间的数字 m。选择 k,使其约为 n_photos/4。现在,在位置 (x,y) 处,您将把照片编号转为 (n_photos*m/2^(2k) +smallish_random_number)。我将留下一些细节供您填写:-)。