C语言疫情邻域矩阵边缘情况判断代码的简化问询
问题描述
我有一个代表疫情社区的方形矩阵,每个单元格对应一户住宅,住宅有三种状态:S(患病)、H(痊愈)、C(传染期)。输入天数后,需要按以下规则每日更新社区状态:
- 若住宅状态为
H,且上下左右(非对角线)邻域存在C,则转为C; - 若住宅状态为
C,且8个方向(含对角线)的邻域中至少有2个C,则转为S; - 若住宅状态为
S,则转为H。
我已经实现了判断C类住宅边缘情况的limit_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;} } }
请问有没有更简洁的写法实现这个函数的功能?
优化方案
有更简洁的写法,核心思路是用循环遍历8个方向的偏移量,同时判断每个偏移后的坐标是否在矩阵范围内,彻底避免大量重复的条件分支。
优化后的代码如下:
// 定义8个方向的坐标偏移量,覆盖所有邻域方向 static const int dirs[8][2] = {{-1,0}, {1,0}, {0,-1}, {0,1}, {-1,-1}, {-1,1}, {1,-1}, {1,1}}; void limit_C(char **neigh, int i, int j, int d, char **help) { int counter = 0; // 遍历所有8个邻域方向 for (int k = 0; k < 8; k++) { int ni = i + dirs[k][0]; int nj = j + dirs[k][1]; // 检查坐标是否在矩阵有效边界内 if (ni >= 0 && ni < d && nj >= 0 && nj < d) { if (help[ni][nj] == CONTAGIOUS) { counter++; } } } // 满足条件则转换状态 if (counter >= 2) { neigh[i][j] = SICK; } }
优化说明
- 消除冗余分支:原代码针对角落、边缘、中心位置分别写判断逻辑,重复代码多。优化后用统一的循环和边界检查,一次性覆盖所有位置的情况,逻辑更紧凑。
- 扩展性更强:如果后续需要调整邻域方向(比如增减方向),只需修改
dirs数组即可,无需改动大量条件判断。 - 可读性更高:代码逻辑清晰,一眼就能看出是遍历所有邻域并计数,维护成本大幅降低。
- 功能完全等价:新代码的计数逻辑和原代码完全一致,只是实现方式更高效简洁,不会改变原有功能。
内容的提问来源于stack exchange,提问作者The Bulletbroof Joker
相关产品推荐
相关产品推荐

