【问题标题】:How can I find the North, East, South, West and diagonal neighbours in a 2D array?如何在二维数组中找到北、东、南、西和对角线邻居?
【发布时间】:2019-08-21 09:28:37
【问题描述】:

我正在开发一个 2D 程序生成的 Unity 游戏,我想知道如何在四个基本方向(N、E、S、W)以及四个基本方向(NE 、东南、西南、西北)。

我想要实现的示例:

【问题讨论】:

  • 水平邻居在 (x+1,y) 和 (x-1,y)。垂直邻居位于 (x,y+1) 和 x,y-1)。对角邻居是 [x+/-1] 和 [y+/-1] 的所有组合
  • @TedBrownlow 但我将如何在 2D int 数组中执行此操作?
  • @Nitro557 没有。我试图在瓷砖地图中获取瓷砖的相邻瓷砖。

标签: c# unity3d


【解决方案1】:

如果我们将单元格坐标视为rowcolumn,您可以通过查看上一行、同一行和下一行、前一列、同一列和我们正在搜索的单元格后面的列。

要获得这些值,我们只需设置 minRow = cell.Row - 1maxRow = cell.Row + 1minCol = cell.Col - 1maxCol = cell.Col + 1(当然,我们必须检查网格的边界以确保我们不会离开任何边,并且我们不返回 RowCol 与我们正在检查的单元格相同的单元格),并且我们返回具有这些坐标的网格中的所有项目。

例如:

private static List<T> GetNeighbors<T>(int cellRow, int cellCol, T[,] grid)
{
    var minRow = cellRow == 0 ? 0 : cellRow - 1;
    var maxRow = cellRow == grid.GetUpperBound(0) ? cellRow : cellRow + 1;
    var minCol = cellCol == 0 ? 0 : cellCol - 1;
    var maxCol = cellCol == grid.GetUpperBound(1) ? cellCol : cellCol + 1;

    var results = new List<T>();

    for (int row = minRow; row <= maxRow; row++)
    {
        for (int col = minCol; col <= maxCol; col++)
        {
            if (row == cellRow && col == cellCol) continue;
            results.Add(grid[row, col]);
        }
    }

    return results;
}

实际上,它可能看起来像:

private static void Main()
{
    var grid = GetSquareGrid(10);

    var neighbors = GetNeighbors(4, 5, grid);

    Console.Write($"Neighbors of [4,5] are: ");
    Console.Write(string.Join(",", neighbors.Select(n => $"[{n.X},{n.Y}]")));

    GetKeyFromUser("\n\nDone! Press any key to exit...");
}

private static Point[,] GetSquareGrid(int size)
{
    var result = new Point[size, size];

    for (int row = 0; row < size; row++)
    {
        for (int col = 0; col < size; col++)
        {
            result[row, col] = new Point(row, col);
        }
    }

    return result;
}

输出:

【讨论】:

    【解决方案2】:

    所以你有一个二维数组:

    var map = new int[20, 20];
    

    首先我们需要宽度和高度(假设您的数组以map[x, y] 的形式排列数据):

    // + 1 because GetUpperBound returns the highest addressable index, not the length in that dimension
    var width = map.GetUpperBound(0) + 1;
    var height = map.GetUpperBound(1) + 1;
    

    现在我们有了这个,我们可以找到邻居了。我只做过西部、西北、东部和东南部,但我相信你明白了:

    int searchX = 5;
    int searchY = 5;
    
    // I'm using -1 as a "doesn't exist" value, although you could also look at using nullable int (i.e. int? westNeighbour = null)
    int westNeighbour = -1;
    int northwestNeighbour = -1;
    int eastNeighbour = -1;
    int southeastNeighbour = -1;
    
    if (searchX - 1 >= 0) // would this neighbour be on the map?
    {
        westNeighbour = map[searchX - 1, searchY];
    }
    
    if (searchX - 1 >= 0 && searchY - 1 >= 0) // would this neighbour be on the map?
    {
        northwestNeighbour = map[searchX - 1, searchY - 1];
    }
    
    if (searchX + 1 < width) // would this neighbour be on the map?
    {
        eastNeighbour = map[searchX + 1, searchY];
    }
    
    if (searchX + 1 < width && searchY + 1 < height) // would this neighbour be on the map?
    {
        southeastNeighbour = map[searchX + 1, searchY + 1];
    }
    

    请注意,我们正在检查新位置是否仍在数组的边界内,以免出现索引错误。

    【讨论】:

      【解决方案3】:

      假设您使用的是统一的 tilemap,这就是您的操作方式

      public static List<TileBase> GetNeighbours(Tilemap tilemap,  Vector3Int original)
      {
          var tiles = new List<TileBase>();
          for (int x=-1;x<=1;++x)
          {
              for (int y=-1;y<=1;++y)
              {
                  var point = new Vector3Int(original.x + x, original.y + y, 0);
                  if (
                      tilemap.cellBounds.Contains(point) &&
                      x!=0 || y!=0
                  )
                  {
                      tiles.Add(tilemap.GetTile(point));
                  }
              }
          }
          return tiles;
      }
      

      【讨论】:

        【解决方案4】:

        您在评论中提到您正在尝试使用 2D int 数组执行此操作,所以我假设您的图块标有整数。假设您有一个包含所有整数的数组 int[,]。我还将假设您知道要查找邻居的图块的 x,y 位置。

        假设您的数组看起来像这样,带有标记的索引:

        [0,0] [1,0] [2,0] [3,0]
        [0,1] [1,1] [2,1] [3,1]
        [0,2] [1,2] [2,2] [3,2]
        [0,3] [1,3] [2,3] [3,3]
        

        如果你的数组被翻转,你需要翻转下面的一些逻辑,但它仍然适用。

        要让瓷砖向西,它是 x-1。为了让瓷砖向东,它是 x+1。需要注意的是 x 不能大于 2D 数组的宽度,我们将其标记为 int widthOfArray。南北也一样,限制为 heightOfArray

        让我们把它付诸实践:

        //Assumption: [x,y] is the current array position that you want to find neighbors
        //east and west are going to dictate your x index for finding the neighbor.
        westIndex = Mathf.Clamp(x - 1, 0f, widthOfArray);
        eastIndex = Mathf.Clamp(x + 1, 0f, widthOfArray);
        //north and south are going to dictate your y index for finding the neighbor.
        northIndex = Mathf.Clamp(y - 1, 0f, heightOfArray);
        southIndex = Mathf.Clamp(y + 1, 0f, heightOfArray);
        
        int northPoint     = array[x, northIndex];
        int northEastPoint = array[eastIndex, northIndex];
        int eastPoint      = array[eastIndex, y];
        int southEastPoint = array[eastIndex, southIndex];
        int southPoint     = array[x, southIndex];
        //...etc
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-02-12
          • 1970-01-01
          • 2022-12-01
          • 2012-01-21
          • 2013-02-24
          • 1970-01-01
          • 2010-10-13
          相关资源
          最近更新 更多