【问题标题】:C# Comparing adjacent values in a 2d arrayC#比较二维数组中的相邻值
【发布时间】:2017-12-01 02:03:57
【问题描述】:

路径从行索引 80、列索引 0 开始。我必须创建一条到地图另一边的路径(列索引 199)。我无法返回我访问过的上一个单元格,我必须对仅与当前单元格相邻但无法向后移动一列的单元格进行比较,我必须继续向前移动,否则我可以“向上”或“向下”移动" 在我所在的当前列中。我发现单元格之间的差异最小。

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

这是我目前所拥有的:

我不确定如何比较相邻的单元格。我想我需要几个 if 语句,但我不太明白。 至于表示路径,我真的不确定该使用什么。我尝试制作一个单独的方法将这些字符存储到另一个二维数组中,但无法正常工作。

    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;
    }

【问题讨论】:

  • Stack Overflow 并不是一个“为我做”的编码网站。请阅读this article
  • 不要求任何人为我做这件事。我正在寻求帮助。谢谢。
  • 你能告诉我们你的代码有什么问题吗?
  • 它也不是一个招聘人员的网站。提出一个问题。我猜你的代码不起作用......在这种情况下,我们会告诉你它在做什么以及它与你的期望有何不同,然后我们可以告诉你如何修复它。你可以edit your question。
  • 你的问题是你基本上列出了一个规格表。它使遇到您的问题的人认为您没有完成任何工作。是的,您确实添加了代码,但是,您的问题的格式使我们相信您没有特定错误并且您不想做任何工作。正如@Theraot 提到的,它将帮助您根据how to ask article 编辑您的问题,这样我们就可以帮助您解决您的确切问题:)

标签: c# arrays algorithm project


【解决方案1】:

关于选择路径,你说:

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

我会回到那个。


关于比较相邻单元格,假设每个单元格由数组中的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 设置为 cmets,它对应于在列中返回。我还把最后一个条件变成了 cmets,那是因为 while 已经在检查那个了。

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

附录:不,您不需要列表。没有它也可以完成,但会导致更多重复,更难阅读,更容易出错。

// 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&lt;short, short&gt;,但您可以做得更好。

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


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

【讨论】:

  • 非常感谢您的回复!抱歉,如果我不清楚某些要求。路径可以是上下、左右或对角线(上下左右)。
  • 我对元组一点也不熟悉。我们在课堂上没有学到任何关于他们的知识。
猜你喜欢
  • 2021-10-28
  • 1970-01-01
  • 1970-01-01
  • 2021-11-12
  • 1970-01-01
  • 1970-01-01
  • 2015-04-17
  • 2016-07-18
  • 2015-02-10
相关资源
最近更新 更多