C中的更简单的条件

eqfvzcg8  于 2023-06-05  发布在  其他
关注(0)|答案(4)|浏览(126)

我的问题是我有一个平方矩阵,代表一个流行病的社区,矩阵中的每个单元代表一所房子。房子有三种不同的情况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;}
        
    }
}

那么有没有更简单的方法来写同样的代码呢?

unftdfkk

unftdfkk1#

您可以做的一件事是使用for循环来迭代每个可能的邻居位置以进行检查,而不是使用单独的代码显式地实现每个邻居的检查。类似这样的东西(我意识到我的例子的逻辑与你的程序的逻辑不一样,这只是给予一个大致的概念):

void limit_C(char **neigh, int i, int j, int d, char **help)
{
   int counter = 0;
   for (int di=-1; di<=1; di++)
   {
      for (int dj=-1; dj<=1; dj++)
      {
         if ((di==0)&&(dj==0)) continue;  // no point checking a house against itself!

         const int neighborX = (i+di);
         const int neighborY = (i+dj);

         // avoid checking grid-positions that aren't valid
         if ((neighborX < 0)||(neighborX >= d)) continue;
         if ((neighborY < 0)||(neighborY >= d)) continue;

         if (help[neighborX][neighborY] == 'C') counter++;
      }
   }
   if (counter >= 2) neigh[i][j] = SICK;
}
n6lpvg4x

n6lpvg4x2#

你可以创建从[i-1][j-1]开始到[i+1][j+1]的循环,但不包括边。
示例:

void limit_C(char **neigh, int i, int j, int d, char** help) {
    int counter = 0;
    int ys = i + (i > 0 ? -1 : 0);
    int xs = j + (j > 0 ? -1 : 0);
    int ye = i + (i < d - 1 ? 1 : 0);
    int xe = j + (j < d - 1 ? 1 : 0);

    for (int y = ys; y <= ye; ++y) {
        for (int x = xs; x <= xe; ++x) {
            if(y == i && x == j) continue;
            if (help[y][x] == CONTAGIOUS) counter++;
        }
    }
    if (counter >= 2) neigh[i][j] = SICK;
}
tcomlyy6

tcomlyy63#

而不是像这样的代码:

if(help[i + 1][j] == CONTAGIOUS)
   {counter++;}

我将引入一个辅助函数来进行比较。类似于:

int is_C(char **neigh, int i, int j, int d)
{
    if (i < 0) return 0;
    if (i >= d) return 0;
    if (j < 0) return 0;
    if (j >= d) return 0;
    return neigh[i][j] == CONTAGIOUS;
}

有了这个辅助函数,你就不需要担心边界情况了。查看全部8个邻居

int count_C(char **neigh, int i, int j, int d)
{
    int cnt = 0;
    cnt += is_C(neigh, i-1, j-1, d);
    cnt += is_C(neigh, i-1, j, d);
    cnt += is_C(neigh, i-1, j+1, d);
    cnt += is_C(neigh, i, j-1, d);
    cnt += is_C(neigh, i, j+1, d);
    cnt += is_C(neigh, i+1, j-1, d);
    cnt += is_C(neigh, i+1, j, d);
    cnt += is_C(neigh, i+1, j+1, d);
    return cnt;
}

然后你有简单的代码,如:

for (int i = 0; i < d; ++i)
{ 
    for (int j = 0; j < d; ++j)
    { 
        if (neigh[i][j] == CONTAGIOUS && count_C(neigh, i, j, d) >= 2)
        {
            neigh[i][j] = SICK;  // or tmp_neigh[i][j] = SICK; See note
        }
     }
}
  • 注意:* 可能是“游戏”的规则需要一个临时矩阵来保存更新期间的新状态。
d4so4syb

d4so4syb4#

总结一下这个问题:当我们想检查邻居时,我们如何优雅地处理网格边缘的情况?

一个选项是只检查每个条件的边界,例如:

if(j + 1 < d && help[i][j + 1] == CONTAGIOUS)

因为&&运算符是short-circuiting,所以如果条件的第一部分是

另一个选项是在每个方向上扩展矩阵-因此,如果输入是[d][d],则分配[d+2][d+2]。确保将边初始化为一个良好的默认值(您希望考虑“丢失”的邻居,可能是HEALED?).

然后,只需调用“真实的”位置的更新函数--注意索引是如何上移一步的(从1开始,直到 * 包括 * d)。

for (int i=1; i<=d; ++i) {
    for (int j=1; j<=d; ++j) {
        limit_C(neigh, i, j, d, help)
    }
}

这样,你的update函数根本不需要检查边界,因为ij永远不会小于1(所以i-1永远不会小于0),也永远不会大于d(所以i+1将小于d+2,这是矩阵的实际大小)。所以你可以自由地做:

if (help[i][j+1] == CONTAGIOUS)

请记住,使用此选项时,您需要记住索引已移动。例如,当输出结果时。

相关问题