我使用以下方法根据给定索引(行和列)检查特定单元格周围的单元格(如果它是否为零),请参阅此数组:
我需要检查零周围(水平,垂直或对角)的单元格可以位于第一行,最后一行,第一列,最后一列或其间,即它可以是矩形阵列中的任何单元格,具体取决于到传递给方法的“rowIndex”和“colIndex”。
static Boolean TestZero(int[,] array,int colIndex, int rowIndex)
{
/*Check Corners*/
//First Corner
if ((rowIndex == 0) && (colIndex == 0))
{
if (array[1, 0] == 1 || array[0, 1] == 1 || array[1, 1] == 1) return false;
}
//Second Corner
if ((rowIndex == 0) && colIndex >= array.GetUpperBound(0))
{
if (array[array.GetUpperBound(0) - 1, 0] == 1 || array[array.GetUpperBound(0),1] == 1 || array[array.GetUpperBound(0)-1,1 ] == 1) return false;
}
//Third Corner
if ((rowIndex >= array.GetUpperBound(1)) && (colIndex == 0))
{
if (array[0, array.GetUpperBound(1) - 1] == 1 || array[1, array.GetUpperBound(1)] == 1 || array[1, array.GetUpperBound(1)-1] == 1) return false;
}
//Fourth Corner
if ((rowIndex >= array.GetUpperBound(1)) && (colIndex >= array.GetUpperBound(0)))
{
if (array[array.GetUpperBound(0), array.GetUpperBound(1) - 1] == 1 || array[array.GetUpperBound(0) - 1, array.GetUpperBound(1) - 1] == 1 || array[array.GetUpperBound(0) -1, array.GetUpperBound(1)] == 1) return false;
}
/* Check Boundries But Not Corners */
//First Row
if ((rowIndex == 0) && (colIndex != array.GetUpperBound(0)) && (colIndex != 0))
{
for (int i = rowIndex; i <= rowIndex + 1; i++)
{
for (int j = colIndex - 1; j <= colIndex + 1; j++)
{
if ((i != rowIndex) && (j != colIndex))
{
if (array[j,i] == 1) return false;
}
}
}
}
//Last Row
if ((rowIndex >= array.GetUpperBound(1)) && (colIndex != array.GetUpperBound(0)) && (colIndex != 0))
{
for (int i = rowIndex; i <= rowIndex - 1; i--)
{
for (int j = colIndex - 1; j <= colIndex + 1; j++)
{
if ((i != rowIndex) && (j != colIndex))
{
if (array[j,i] == 1) return false;
}
}
}
}
//First & Last Columns
if ((rowIndex != array.GetUpperBound(1)) && ((rowIndex != 0)))
{
//First column
if(colIndex==0)
{
for (int i = rowIndex-1; i <= rowIndex + 1; i++)
{
for (int j = colIndex; j <= colIndex + 1; j++)
{
if ((i != rowIndex) && (j != colIndex))
{
if (array[j,i] == 1) return false;
}
}
}
}
//Last Column
if (colIndex == array.GetUpperBound(0))
{
for (int i = rowIndex -1; i <= rowIndex + 1; i++)
{
for (int j = colIndex; j <= colIndex - 1; j--)
{
if ((i != rowIndex) && (j != colIndex))
{
if (array[j,i] == 1) return false;
}
}
}
}
}
/* In Between i.e. Not the Array Boundries */
if(colIndex!=0 && colIndex != array.GetUpperBound(0) && rowIndex !=0 && rowIndex != array.GetUpperBound(1)) {
for (int i = rowIndex - 1; i <= rowIndex + 1; i++)
{
for (int j = colIndex - 1; j <= colIndex + 1; j++)
{
if ((i != rowIndex) && (j != colIndex))
{
if (array[j,i] == 1) return false;
}
}
}
} // end if statment
return true;
}
我得到了一些错误的结果,我试图弄清楚问题,但我做不到!。
结果:
1-矩形阵列(遗传算法群体中的染色体):
2-我们需要检查周围环境的细胞的索引:
|(2,3)||(2,3)||(0,1)||(1,3)||(0,3)||(1,3)|
3-在每个预期细胞的至少一个周围细胞中含有零的阵列:
染色体0:真染色体1:真染色体2:假 染色体3:真染色体4:假染色体5:真实
任何帮助,以弄清楚为什么我得到一些错误的结果!!
答案 0 :(得分:4)
从我所看到的,你的方法检查一个单元格是否被填充了1
的单元格包围,如果是,则返回false
。您的代码太复杂了,因为您试图将所有内容视为不同的情况,而不是通过它来使调试变得非常困难。以下方法是实现检查的更好方法的示例:
bool TestZero(int[,] mat, int row, int col)
{
int ones = 0, cells = 0;//define counters
//define bounderies
int rowLen = Math.Min(row + 1, mat.GetLength(0) - 1),
colLen = Math.Min(col + 1, mat.GetLength(1) - 1),
rowIdx = Math.Max(0, row - 1),
colIdx = Math.Max(0, col - 1);
for (int i = rowIdx; i <= rowLen; i++)
{
for (int j = colIdx; j <= colLen; j++)
{
//if it is our given index, continue
if (i == row && j == col)
continue;
++cells;//increment cells counter
if (mat[i, j] == 1)//if the value of the cell is 1
++ones;//increment the ones counter
}
}
return ones < cells;//if there are less cells with '1' then
//surrounding cells, return true.
}
我们在这里做的是:
创建两个计数器:一个计算给定单元格周围的单元格数量,另一个计算围绕它的数量。
我们在变量中保存循环的bounderies:
然后我们迭代我们用bounderies创建的迷你矩阵。对于每个单元格,如果不是我们给定的单元格,我们递增单元格计数器,如果它等于1
,我们递增计数器。
最后,如果一个计数器小于单元格计数器,我们返回true,因为我们的单元格没有被1
包围。
如果并非所有周围单元格都包含1
,则上面的示例返回true。
但是可以更改返回值以匹配不同的情况:
true
的0个单元格时返回1
,请将返回行更改为以下内容:return ones == 0;
在这种情况下,单元格计数器是不必要的,只需要计数器。true
时返回1
,请更改为以下内容:return ones == cells;
您基本上可以将返回值更改为您需要的任何情况,它非常灵活。
答案 1 :(得分:4)
与往常一样,编程时的第一条规则是:将问题分解为更小的位。
我将使用 C#7 功能,只是为了它的乐趣。如果您不使用 C#7 ,请考虑将其翻译为以前的版本作为练习。
好的,第一步。你需要neigbouring细胞?好吧,让我们得到所有可能的相邻细胞,而不是关心它们是否存在。我们稍后会照顾好;记住,一次只有一个小问题。
private static bool IsValidCoordinate((int Row, int Column) coord, int rowCount, int columnCount)
{
Debug.Assert(rowCount >= 0);
Debug.Assert(columnCount >= 0);
if (0 > coord.Row || coord.Row >= rowCount ||
0 > coord.Column || coord.Column >= columnCount)
return false;
return true;
}
好的,现在我们有一个方法可以为我们提供所有可能的8个邻居。我返回它们的顺序是顺时针方向,从左上角开始。在这种情况下,顺序并不重要,因此请将其视为实施细节。
现在,我们需要检查任何给定的单元格是否有效。好吧,这似乎也很容易:
rowCount
好的,那也很简单。看看在简单方法中引入错误有多难?
另外,请注意方法开头的断言。此方法不适用于columnCount
和public static IEnumerable<T> GetNeighbouringCells<T>((int Row, int Column) coord, T[,] cells)
{
if (cells == null)
throw new ArgumentOutOfRangeException();
if (!IsValidCoordinate(coord, cells.GetLength(0), cells.GetLength(1)))
throw new ArgumentOutOfRangeException();
return GetAllNeighbouringCoordinates(coord.Row, coord.Column)
.Where(c => IsValidCoordinate(c, cells.GetLength(0), cells.GetLength(1)))
.Select(c => cells[c.Row, c.Column]);
}
的无意义值,因此我在代码中强制执行。因为该方法是一个私有帮助器方法,我可以简单地断言,而不是抛出异常。如果断言在测试中失败,我知道我的代码中有一个错误。
现在,我们必须将两者结合在一起。让我们构建一个返回所有相邻单元格值的方法。我们将使用一些 LINQ 来删除难看的循环:
public static IEnumerable<(int Row, int Column)> CellsWithAtLeastOneNeighbourEqualTo<T>(
this T[,] cells, T value)
{
for (var row = 0; row < cells.GetLength(0); row++)
{
for (var column = 0; column < cells.GetLength(1); column++)
{
if (GetNeighbouringCells((row, column), cells).Any(c => c.Equals(value)))
{
yield return (row, column);
}
}
}
}
你去了,现在你有一个简单的方法可以返回任何给定单元格的每个相邻值。
现在,您需要至少有一个相邻单元格为零的所有单元格?容易腻:
var cells = new[,] { { 0, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } };
var n = cells.CellsWithAtLeastOneNeighbourEqualTo(0).ToList();
现在,如果你带一小段车:
[0, 1]
[1, 0]
[1, 1]
您将获得预期的结果:
{{1}}
答案 2 :(得分:1)
这似乎是一个简单的生活游戏计划。你不应该不经意地检查所有内容,而是使用一个函数来检查表中是否存在单元格的x和y坐标。
伪代码:
for each cell in celltable
for each cell surrounding
if cell index is valid && alive
alive = alive + 1;
endif
endfor
if alive is valid
add cell to retList
alive = 0;
endfor
没有人想调试巨大的if-else系统。
答案 3 :(得分:1)
性能不佳,但可以解决您的问题。
PS。请注意,我已将您的colIndex
和rowIndex
重命名为x
和y
。
static bool TestZero(int[,] array, int x, int y)
{
try
{
if (array[x - 1, y - 1] == 1) return false;
}
catch { }
try
{
if (array[x, y - 1] == 1) return false;
}
catch { }
try
{
if (array[x + 1, y - 1] == 1) return false;
}
catch { }
try
{
if (array[x - 1, y] == 1) return false;
}
catch { }
try
{
if (array[x, y] == 1) return false;
}
catch { }
try
{
if (array[x + 1, y] == 1) return false;
}
catch { }
try
{
if (array[x - 1, y + 1] == 1) return false;
}
catch { }
try
{
if (array[x, y + 1] == 1) return false;
}
catch { }
try
{
if (array[x + 1, y + 1] == 1) return false;
}
catch { }
return true;
}
我使用您的原始案例(您帖子中的第一张图片)进行测试,请使用以下代码。
private static int[,] array = { { 0, 0, 1, 1 }, { 0, 0, 0, 1 }, { 0, 1, 1, 1 }, { 1, 0, 1, 0 } };
static void Main(string[] args)
{
for (int i = 0; i <= array.GetUpperBound(0); i++)
{
for (int j = 0; j <= array.GetUpperBound(1); j++)
{
Console.Write(TestZero(array, i, j) + " ");
}
Console.WriteLine();
}
Console.ReadKey();
}
结果是
True False False False
False False False False
False False False False
False False False False
我要测试更多案例,但最后你可以尝试一下。