关于选择路径,你说:
我发现细胞之间的差异最小。
我会回到那个。
关于比较相邻单元格,假设每个单元格由数组中的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<short, short>,但您可以做得更好。
-
您可能希望封装检查相邻位置是否不是旧位置并将其添加到列表中的逻辑。这样做的好处是使代码更具可读性并使其不易出错(例如,您不会意外地检查相邻的一个,而是添加一个不同的,这在复制和粘贴时可能会漏掉)。
附录:我猜输出是一个字符串,你可以用StringBuilder 构建它。您添加的角色取决于您选择的相邻角色。如果你选择一个同时保存相邻坐标和要使用的角色的结构,也许会让事情变得更容易。还是需要在控制台中绘制路径?因为那是完全不同的东西。