将2D矩形网格划分为较小网格的算法

时间:2012-01-06 17:23:30

标签: java algorithm grid partitioning

我在Java中使用ArrayLists构建了一个2D网格,并希望将网格拆分为给定数量的较小网格。

我正在开发的任务是开发一个模拟器,用于在多个服务器上分发游戏地图,这就是我需要将较小的地图拆分成服务器的原因。

我真的有两个问题,第一个给出一个X×Y矩形(地图)和一些将它分成N的部分,我怎样才能将规则划分为N个更小(但最好是面积相等)的矩形

其次,我很欣赏有关如何在2D arraylists方面实施上述方法的建议。

2 个答案:

答案 0 :(得分:2)

回答关于将X-by-Y矩形分割为N个相等面积的较小矩形的第一个问题......

我认为最好的办法是打破N个子区域中的矩形,每个子区域保持与主矩形相同的宽高比。

N应该是 sqrt(N)产生一个完整的答案(例如 N = 36 sqrt(N)= 6 ) 。因此,X-by-Y被分解为 sqrt(N) -by- sqrt(N)子项。子矩形(Xs,Ys)的计算如下:

Xs = X / sqrt(N)

Ys = Y / sqrt(N)

只要 sqrt(N)是一个整数值,这种方法总会给你N个相等的子项。根据N的值,您可能必须通过使某些子区域稍微大一些来完全覆盖整个主矩形来补偿整数截断错误。

还有另一种方法是通过将主矩形的面积除以N来计算,然后取该结果的平方根得出一个M-by-M的子平方,但是& #39;比上述方法更粗糙。

答案 1 :(得分:1)

如果n恰好是正方形,则可以通过在每个方向上切割成sqrt(n)个切片来分割网格。否则,横条纹将起作用(如果这些碎片的形状与整个地图不相似则不是问题)。如果保持形状合理比保持它们大小相同更重要,可以考虑一种算法,从整个网格开始,并将最大的一半分成两半,直到你有所需的数量。

当涉及到切割网格的切片时,我假设通过2D ArrayList表示List<List<?>>,其中list.get(x).get(y)是(x,y)处的项目)。然后,您可以在两个方向上使用subList()

List<List<?>> split(List<List<?>> in, int x1, int y1, int x2, int y2) {
   List<List<?>> out = new ArrayList<List<?>>(w);
   for(List<?> column : in.sublist(x1, x2)) {
      out.add(column.subList(y1, y2));
   }
   return out;
}

List<List<List<?>>> partitionEqualAspect(List<List<?>> grid, int n) {
   int w = grid.size();
   int h = grid.get(0).size();
   int cols = (int)(sqrt(n) + .5);

   // This many columns have (cols - 1) rows
   int shortCols = Math.max(0, cols * cols - n);
   // This many columns have (cols + 1) rows
   int longCols = Math.max(0, n - cols * cols);

   List<List<List<?>>> tiles = new ArrayList<List<List<?>>>();
   for(int c = 0; c < cols; ++c) {
      int rows = cols + (c < shortCols ? -1 : c >= cols - longCols ? 1 : 0);
      for(int r = 0; r < rows; ++r) {
         tiles.add(split(grid, 
                         w * c / cols, h * r / rows, 
                         w * (c + 1) / cols, h * (r + 1) / rows));
      }
   }
   return tiles;
}

请注意,此处创建的网格切片会引用回原始网格,切片的更改将反映在整个网格中。如果你想避免这种情况,你可以复制一切。