矩阵中的每个点代表一个生存或死亡的细胞。我必须计算每个细胞有多少个ALIVE邻居。我有一个功能,但它检查边界之外的单元格。我不知道如何在不执行大量if-else语句的情况下同时检查邻居并跟踪边缘。
void Neighbours(int rows,
int cols, cell world[rows][cols],
int neighbors[rows][cols]) {
//Loop through each cell in the matrix.
for(int rCell = 0; rCell < rows; rCell++){
for(int cCell = 0; cCell < cols; cCell++) {
//Reset neighbor count for each cell.
neighbors[rCell][cCell] = 0;
//Check cell status in cell's vicinity of each cell.
for(int surroundR = -1; surroundR <= 1; surroundR++){
for(int surroundC = -1; surroundC <= 1; surroundC ++) {
//CONDITIONS
//1. If the cell is alive,
//2. if the cell is not itself,
//3. if it does exist within the boundaries of the matrix.
if(field[rCell - surroundR][cCell - surroundC].status == ALIVE) {
if(!(surroundR == 0 && surroundC == 0) && (rCell-surroundR < rows) && (cCell-surroundC < cols) && (cCell-surroundC >= 0) && (rCell-surroundR >= 0)) {
neighbors[rCell][cCell] += 1;
}
}
}
}
}
}
}
答案 0 :(得分:3)
处理此问题最简单的方法是添加两个虚拟行和列:矩阵上方的一行,矩阵下方的一行,矩阵左侧的一列以及矩阵右侧的一列。您将它们一次性设置为DEAD,并仅在原始矩阵中的单元格上运行循环。
答案 1 :(得分:2)
总是在进行此类检查时 - 在索引到数组之前检查索引是否在您要索引的数组的大小范围内。在索引到数组之前,您必须先执行此操作。之前由于访问数组索引超出限制,您有未定义的行为。
if( (rCell - surroundR) <= rows-1 && (cCell - surroundC)<= cols-1 && (rCell - surroundR)>=0 && (cCell - surroundC)>=0 ) {
/* then do rest of work */
}
答案 2 :(得分:2)
您可以通过使用仅包含 dead 元素的每一行包含一行的数组来轻松销售一些内存以节省时间,并且仅在内部进行处理。算法变得更简单,错误风险更小,但必须更改整个代码以添加2行和2行:
void Neighbours(int rows,
int cols, cell world[rows][cols],
int neighbors[rows][cols]) {
//Loop through each cell in the matrix.
for(int rCell = 1; rCell < rows-1; rCell++){ // limit to the interior
for(int cCell = 1; cCell < cols-1; cCell++) {
// remaining part of the loops is unchanged
答案 3 :(得分:2)
一种方法是在阵列的边缘用行和列的死单元填充数组。
另一种方法是编写单独的代码片段:
一个循环处理数组的内部单元格(省略边缘行和列),检查所有邻居。
一个循环处理顶行,仅检查顶行单元格的实际邻居。只处理行内部的单元格,省略角落。
同样,底行有一个循环,左栏有一个循环,右栏有一个循环。
分别检查四个角。
虽然这是更多代码,但它执行的检查次数少于检查每个单元格的一个循环。请注意,可以组合顶行和底行的循环(因为它们共享列坐标),并且可以组合左边缘和右边缘的循环。
可以进一步减少计算负荷。例如,主阵列中每个3 * 1条带中的活细胞计数可以被缓存(在辅助阵列中或简单地在精心制作的循环中的变量中)以便重复使用。主阵列内部的每个这样的条带在计算各个单元周围的3 * 3方块时使用了三次,因此缓存它们的计数可以消除一些重复的工作。
(关于填充:要使用正确的C代码,您需要两列,一个在左侧,一个在右侧。但是,如果您的C实现支持访问子阵列元素超出范围,只要被寻址的元素在完整的数组,或者手动将两个维度映射到一维数组,然后一个填充列就足够了,因为它既可以在数组左边缘的左边,也可以在右边缘的右边。)< / p>