C#比较二维数组

时间:2017-12-01 02:03:58

标签: c# arrays algorithm project

路径从行索引80开始,列索引为0.我必须创建到地图另一边的路径(列索引199)。我不能回到我访问过的前一个单元格,我必须对仅与当前单元格相邻的单元格进行比较,但是我不能向后移动一列,我必须继续前进或者我可以移动"向上&# 34;或" down"在我目前的专栏中。我发现细胞之间的差异最小。

为了表示路径,我必须存储一个(/)来表示你向上和向右移动,()代表我向下移动到右边,( - )代表我移动到右边,或(|)代表我向上或向下移动。

这是我到目前为止所做的:

我不确定如何比较相邻的细胞。我想我需要一些if语句,但我无法弄明白。 至于代表路径,我真的不确定要使用什么。我试图制作一个单独的方法将这些字符存储到另一个2d数组中,但无法使其工作。

    static void Main(string[] args)
    {
        string[,] path = new string[116, 200];
        short[,] map = arrayMethod();

        int rowIndex = 80;
        int colIndex = 0;
        int positionOfX = 0;
        int positionOfY = 0;
        short minValue = short.MaxValue;

        while (colIndex != 199)
        {
            for (short l = -1; l < 2; l++)
            {
                for (short k = 0; k < 2; k++)
                {
                    if (map[l+ rowIndex, k+colIndex] < minValue)
                    {
                        positionOfX = l;
                        positionOfY = k;
                        minValue = map[l, k];
                    }
                }
            }
        }
    }
    // Method to store data into 2d array
    public static short[,] arrayMethod()
    {
        short[,] map = new short[116, 200];

        string fileName = "land.csv";
        StreamReader reader = new StreamReader(File.Open(fileName, 
    FileMode.Open));
        string nextLine;
        int partsCounter = 0;
        while ((nextLine = reader.ReadLine()) != null)
        {
            string[] parts = nextLine.Split(',');

            for (int cols = 0; cols < 200; cols++)
            {
                map[partsCounter, cols] = Convert.ToInt16(parts[cols]);
            }
            partsCounter++;
        }
        return map;
    }

1 个答案:

答案 0 :(得分:0)

关于选择路径,您说:

  

我发现细胞之间的差异最小。

我会回过头来看。

关于比较相邻单元格,假设每个单元格由数组中的short表示,则应该是简单的数值比较。

我相信,问题的关键在于找到相邻的细胞。

嗯,你有一个2D网格,你有一个单元格的坐标......

+-----+-----+-----+-----+
|     |     |     |     |
+-----+-----+-----+-----+
|     |     |     |     |
+-----+-----+-----+-----+
|     |     | x,y |     |
+-----+-----+-----+-----+
|     |     |     |     |
+-----+-----+-----+-----+

您可以通过1:

更改坐标来找到相邻的单元格
+-----+-----+-----+-----+
|     |     |     |     |
+-----+-----+-----+-----+
|     |     |x,y-1|     |
+-----+-----+-----+-----+
|     |x-1,y| x,y |x+1,y|
+-----+-----+-----+-----+
|     |     |x,y+1|     |
+-----+-----+-----+-----+

注意:我代表坐标,假设原点位于左上角。这是计算机图形学的标准惯例。它可能不适用于您的情况。无论如何,这些仍然是你的相邻细胞。

如果我们不应该回到前一列(列的数量必须总是增加),我认为可以安全地忽略那个相邻的列:

+-----+-----+-----+-----+
|     |     |     |     |
+-----+-----+-----+-----+
|     |     |x,y-1|     |
+-----+-----+-----+-----+
|     |     | x,y |x+1,y|
+-----+-----+-----+-----+
|     |     |x,y+1|     |
+-----+-----+-----+-----+

我们可以这样做:

// the map
short[,] map = arrayMethod();

// map dimensions

int numRows = map.GetLength(0);
int numCols = map.GetLength(1);

// current position
int rowIndex = 80;
int colIndex = 0;

while (colIndex < numCols - 1)
{
    var current = map[rowIndex, colIndex];
    if (rowIndex > 0)
    {
         // We are not at the low row edge
         var adjacent = map[rowIndex - 1, colIndex];
         Compare(current, adjacent);
    }
    if (rowIndex < numRows - 1)
    {
        // We are not at the high row edge
        var adjacent = map[rowIndex + 1, colIndex];
        Compare(current, adjacent);
    }
    /*if (colIndex > 0)
    {
         // We are not at the low column edge
         var adjacent = map[rowIndex, colIndex - 1];
         Compare(current, adjacent);
    }*/
    if (/*colIndex < numCols - 1*/ true)
    {
        // We are not at the high column edge
         var adjacent = map[rowIndex, colIndex + 1];
         Compare(current, adjacent);
    }
    // ... update rowIndex, colIndex
}

这里每个if块对应一个相邻的单元格,有一个if的原因是检查我们是否处于边缘,因为 - 如前所述 - 如果你是在边缘处,没有相邻的方向。

另请注意,我已将评论if添加到列中。我还对最后一个条件进行了注释,这是因为while已经检查了那个条件。

我使用Compare方法来表示您想要做的任何比较 - 将回到那个。另请注意,我没有更新rowIndexcolIndex,您上面的内容是无限循环。为了解决这个问题,我建议将相邻的单元格作为列表处理,以后会更容易...

附录:不,你不需要清单。它可以在没有它的情况下完成,但它会导致更多的重复,更难以阅读,并且更容易出错。

// the map
short[,] map = arrayMethod();

// map dimensions

int numRows = map.GetLength(0);
int numCols = map.GetLength(1);

// current position
int rowIndex = 80;
int colIndex = 0;

while (colIndex < numCols - 1)
{
    var current = map[rowIndex, colIndex];
    var adjacents = new List<Tuple</*row*/ short, /*column*/ short>>();
    if (rowIndex > 0)
    {
         adjacents.Add(Tuple.Create(rowIndex - 1, colIndex));
    }
    if (rowIndex < numRows - 1)
    {
         adjacents.Add(Tuple.Create(rowIndex + 1, colIndex));
    }
    adjacents.Add(Tuple.Create(rowIndex, colIndex + 1));
    foreach (var adjacent in adjacents)
    {
        Compare(map[adjacent.Item1, adjacent.Item2], current);
    }
    // ... update rowIndex, colIndex
}

现在...

  

我发现细胞之间的差异最小。

我理解为差异的绝对值,我推测你想要最小化这个(要求不是很清楚)。

根据这种理解,我们可以实施比较:

foreach (var adjacent in adjacents)
{
    var diff = Math.Abs(map[adjacent.Item1, adjacent.Item2] - current);
}

选择我们的目的地:

Tuple<short, short> best;
short bestDiff;
foreach (var adjacent in adjacents)
{
    var diff = Math.Abs(map[adjacent.Item1, adjacent.Item2] - current);
    if (best == null || bestDiff > diff)
    {
        best = adjacent;
        bestDiff = diff;
    }
}
rowIndex = best.Item1;
colIndex = best.Item2;

现在,获得批准后,您不应该返回列或返回前一个单元格。因此,您必须跟踪您的上一个位置,因此您不会检查该位置。

// the map
short[,] map = arrayMethod();

// map dimensions

int numRows = map.GetLength(0);
int numCols = map.GetLength(1);

// current position
int rowIndex = 80;
int colIndex = 0;

// old position
int rowIndexOld = 80;
int colIndexOld = -1; // <-- placing it outside the map

while (colIndex < numCols - 1)
{
    var current = map[rowIndex, colIndex];
    var adjacents = new List<Tuple<short, short>>();
    if (rowIndex > 0 && rowIndexOld != rowIndex - 1 && colIndexOld != colIndex)
    {
         adjacents.Add(Tuple.Create(rowIndex - 1, colIndex));
    }
    if (rowIndex < numRows - 1 && rowIndexOld != rowIndex + 1 && colIndexOld != colIndex)
    {
         adjacents.Add(Tuple.Create(rowIndex + 1, colIndex));
    }
    if (rowIndexOld != rowIndex && colIndexOld != colIndex + 1)
    {
        adjacents.Add(Tuple.Create(rowIndex, colIndex + 1));
    }
    rowIndexOld = rowIndex;
    colIndexOld = colIndex;
    // etc
}

当然,您可以添加逻辑来选择路径并将其写入输出。

说实话,我并不完全理解这些要求......如果你只能向前,向上和向下移动,为什么你有表示对角线运动的符号?无论如何,如果你是对角线,那就不那么难了:

+-------+-------+-------+-------+
|       |       |       |       |
+-------+-------+-------+-------+
|       |x-1,y-1| x,y-1 |x+1,y-1|
+-------+-------+-------+-------+
|       | x-1,y |  x,y  | x+1,y |
+-------+-------+-------+-------+
|       |x-1,y+1| x,y+1 |x+1,y+1|
+-------+-------+-------+-------+

我确定你可以为此编制代码,但更多相同。那些将更接近检查并添加到列表中。

我希望你比我更了解这些要求。

一些建议:

  • 您可以考虑使用类型来表示地图中的位置。由于你经常使用行和列变量对,因此有一个类型是有意义的...我只是使用Tuple<short, short>,但你可以做得更好。

  • 您可能希望封装检查邻居是否不是旧位置并将其添加到列表的逻辑。好处是使代码更具可读性并使其更不容易出错(例如,您不会意外地检查一个相邻但添加不同的代码,这可能会在复制和粘贴中滑落)。

附录:我猜输出是一个字符串,您可以使用StringBuilder构建它。您添加的字符取决于您选择的相邻字符。也许一个结构可以容纳相邻的坐标和你选择使用的角色会使事情变得更容易。或者你需要在控制台中绘制路径?因为那是完全不同的东西。