我的问题是我有一个平方矩阵,代表一个流行病的社区,矩阵中的每个单元代表一所房子。房子有三种不同的情况S代表生病,H代表痊愈,C代表传染。我收到了几天,然后我改变了邻居的初始情况,我每天都按照即将到来的规则改变邻居:
- 如果房子是“H”,它的上/下/左/右邻居是“C”,它变成了“C”房子(不是对角线)。
- 如果房子是“C”,并且至少有两个“C”邻居变成“S”房子(在这种情况下,邻居是上/下/左/右/对角线,这里我们有8个不同的选项)。
- 如果房子是“S”,那么它就变成了“H”房子。
这不是一个很坚韧的问题,但我的问题是,如果我能写一个更简短的条件,为边缘情况。
这是一个功能,当房子是“C”时检查边缘情况:
void limit_C(char **neigh, int i, int j, int d, char **help)
{
int counter = 0;
if ((i == 0) && (j == 0))
{
if(help[i + 1][j] == CONTAGIOUS)
{counter++;}
if(help[i][j + 1] == CONTAGIOUS)
{counter++;}
if(help[i + 1][j + 1] == CONTAGIOUS)
{counter++;}
if(counter >= 2)
{neigh[i][j] = SICK;}
}
else if ((i == d - 1) && (j == d - 1))
{
if(help[i - 1][j] == CONTAGIOUS)
{counter++;}
if(help[i][j - 1] == CONTAGIOUS)
{counter++;}
if(help[i - 1][j - 1] == CONTAGIOUS)
{counter++;}
if(counter >= 2)
{neigh[i][j] = SICK;}
}
else if ((i == d - 1) && (j == 0))
{
if(help[i - 1][j] == CONTAGIOUS)
{counter++;}
if(help[i][j + 1] == CONTAGIOUS)
{counter++;}
if(help[i - 1][j + 1] == CONTAGIOUS)
{counter++;}
if(counter >= 2)
{neigh[i][j] = SICK;}
}
else if ((i == 0) && (j == d - 1))
{
if(help[i + 1][j] == CONTAGIOUS)
{counter++;}
if(help[i][j - 1] == CONTAGIOUS)
{counter++;}
if(help[i + 1][j - 1] == CONTAGIOUS)
{counter++;}
if(counter >= 2)
{neigh[i][j] = SICK;}
}
else if((i == 0) && (j != 0))
{
if(help[i][j + 1] == CONTAGIOUS)
{counter++;}
if(help[i][j - 1] == CONTAGIOUS)
{counter++;}
if(help[i + 1][j] == CONTAGIOUS)
{counter++;}
if(help[i + 1][j + 1] == CONTAGIOUS)
{counter++;}
if(help[i + 1][j - 1] == CONTAGIOUS)
{counter++;}
if(counter >= 2)
{neigh[i][j] = SICK;}
}
else if ((i != 0) && (j == 0))
{
if(help[i][j + 1] == CONTAGIOUS)
{counter++;}
if(help[i - 1][j] == CONTAGIOUS)
{counter++;}
if(help[i + 1][j] == CONTAGIOUS)
{counter++;}
if(help[i - 1][j + 1] == CONTAGIOUS)
{counter++;}
if(help[i + 1][j + 1] == CONTAGIOUS)
{counter++;}
if(counter >= 2)
{neigh[i][j] = SICK;}
}
else if((i == d - 1) && (j != d - 1))
{
if(help[i - 1][j] == CONTAGIOUS)
{counter++;}
if(help[i][j + 1] == CONTAGIOUS)
{counter++;}
if(help[i][j - 1] == CONTAGIOUS)
{counter++;}
if(help[i - 1][j + 1] == CONTAGIOUS)
{counter++;}
if(help[i - 1][j - 1] == CONTAGIOUS)
{counter++;}
if(counter >= 2)
{neigh[i][j] = SICK;}
}
else if((i != d - 1) && (j == d - 1))
{
if(help[i - 1][j] == CONTAGIOUS)
{counter++;}
if(help[i + 1][j] == CONTAGIOUS)
{counter++;}
if(help[i][j - 1] == CONTAGIOUS)
{counter++;}
if(help[i - 1][j - 1] == CONTAGIOUS)
{counter++;}
if(help[i + 1][j - 1] == CONTAGIOUS)
{counter++;}
if(counter >= 2)
{neigh[i][j] = SICK;}
}
}
那么有没有更简单的方法来写同样的代码呢?
4条答案
按热度按时间unftdfkk1#
您可以做的一件事是使用for循环来迭代每个可能的邻居位置以进行检查,而不是使用单独的代码显式地实现每个邻居的检查。类似这样的东西(我意识到我的例子的逻辑与你的程序的逻辑不一样,这只是给予一个大致的概念):
n6lpvg4x2#
你可以创建从
[i-1][j-1]
开始到[i+1][j+1]
的循环,但不包括边。示例:
tcomlyy63#
而不是像这样的代码:
我将引入一个辅助函数来进行比较。类似于:
有了这个辅助函数,你就不需要担心边界情况了。查看全部8个邻居
然后你有简单的代码,如:
d4so4syb4#
总结一下这个问题:当我们想检查邻居时,我们如何优雅地处理网格边缘的情况?
一个选项是只检查每个条件的边界,例如:
因为
&&
运算符是short-circuiting,所以如果条件的第一部分是另一个选项是在每个方向上扩展矩阵-因此,如果输入是
[d][d]
,则分配[d+2][d+2]
。确保将边初始化为一个良好的默认值(您希望考虑“丢失”的邻居,可能是HEALED
?).然后,只需调用“真实的”位置的更新函数--注意索引是如何上移一步的(从1开始,直到 * 包括 *
d
)。这样,你的update函数根本不需要检查边界,因为
i
和j
永远不会小于1(所以i-1
永远不会小于0),也永远不会大于d
(所以i+1
将小于d+2
,这是矩阵的实际大小)。所以你可以自由地做:请记住,使用此选项时,您需要记住索引已移动。例如,当输出结果时。