如何将许多if语句压缩为更小,更易读的内容?

时间:2019-06-10 15:17:11

标签: c if-statement switch-statement conways-game-of-life

我正在为生活游戏编写代码。其中一个功能应该“演化”当前单元格。这意味着我必须具有一些条件,如果if语句满足条件,则该单元将变为DEAD或ALIVE单元。

但是,只有一些下一个正在初始化的单元格,因此我必须将其余不受条件影响的下一个单元格设置为DEAD。

由于有四个条件,我想将我的if语句压缩到最小的数量。

条件是:

  • 有0个或1个活着的邻居的细胞下一代死亡。
  • 一个拥有2或3个生存邻居的细胞下一代。
  • 有四个或四个以上活着的邻居的细胞下一代死亡。
  • 一个完全有3个活着邻居的空单元变成了活着 细胞下一代。

我已经尝试将多个条件分别拟合到一个if语句和一个if语句中的else语句,这意味着如果没有一个单元格满足条件,它将自动设置为DEAD。这样field[i][j].next中的所有单元格都将消失或存活。

我想提到数组field[i][j].current已经用DEAD和ALIVE单元初始化了。

  void evolve(const int rows,const int cols,cell field[rows][cols], int 
    NeighbourCounter[i][j]){

       CellNeighbour(rows, cols,field,NeighbourCounter);

       for(int i = 0;i<rows;i++){
         for(int j =0;j<cols;j++){
           if(field[i][j].current == ALIVE  && NeighbourCounter[i][j] < 2){
              field[i][j].next == DEAD;
           }
           if(field[i][j].current == ALIVE && NeighbourCounter[i][j] == ||NeighbourCounter[i][j] == 2){
               field[i][j].next = ALIVE;
           } 
           if(field[i][j].current == ALIVE && NeighbourCounter[i][j] >= 4){
                field[i][j].next = DEAD;
           }
           if(field[i][j].current == DEAD && NeighbourCounter[i][j] == 3){
                field[i][j].next = ALIVE;
           }
         }
     else{
            field[i][j].next = DEAD;
     }
    }

NeighbourCounter是一个数组,用于计算每个单元格具有多少个ALIVE邻居。

预期输出应该是field[rows][cols]应该被更新,并且更新的版本存储在``field [rows] [cols] .next`”中。

4 个答案:

答案 0 :(得分:3)

  

如何将许多if语句压缩为越来越小的内容   可读吗?

您使用的代码格式错误。 例如,不清楚后面的else语句使用哪个if语句进行解析。

 else{
        field[i][j].next = DEAD;
 }

错误的代码格式通常会导致许多错误(包括逻辑错误)。:)

所有这些if语句

      if(field[i][j].current == ALIVE  && NeighbourCounter[i][j]<2){
           field[i][j].next == DEAD;
        }
         if(field[i][j].current == ALIVE && NeighbourCounter[i][j] ==3 
||NeighbourCounter[i][j] ==2 ){
          field[i][j].next = ALIVE;
        }
         if(field[i][j].current == ALIVE && NeighbourCounter[i][j] >= 4 
){
           field[i][j].next = DEAD;
         }
//...

可以像

那样重写
if ( field[i][j].current == ALIVE )
{
    if ( NeighbourCounter[i][j] < 2 )
    {
        field[i][j].next == DEAD;
    }
    else if ( NeighbourCounter[i][j] < 4 )
    {
        field[i][j].next = ALIVE; 
    }
    else 
    {
        field[i][j].next = DEAD;     
    }
}
else if ( field[i][j].current == DEAD )
{
    if ( NeighbourCounter[i][j] == 3 )
    {
        field[i][j].next = ALIVE;
    }    
}
// ... 

这使代码更具可读性。

作为一种替代方法,您可以使用以下switch语句

switch ( field[i][j].current )
{
    case ALIVE:
    {
        // ...
    }

    case DEAD:
    {
        // ...
    }

    default:
    {
        // ...
    }
}

答案 1 :(得分:1)

简单地switch来计算邻居计数的值可能是最简单,最清晰的,就像这样:

for (int i = 0;  i < rows;  ++i) {
    for (int j = 0;  j < cols;  ++j) {
        switch (NeighbourCounter[i][j]) {
        case 0:
        case 1:
            /* cell dies without enough support */
            field[i][j].next = DEAD; /* I assume you meant =, not == */
            break;
        case 2:
            /* two neighbours can support a live cell */
            field[i][j].next = field[i][j].current;
            break;
        case 3:
            /* three neighbours can resurrect a dead one */
            field[i][j].next = ALIVE;
            break;
        case 4:
        case 5:
        case 6:
        case 7:
        case 8:
            /* more than three is a crowd */
            field[i][j].next = DEAD;
            break;
        default:
            fprintf(stderr, "Invalid value %d from NeighbourCounter\n",
                    NeighbourCounter[i][j]);
        }
    }
}

您将看到case 2是唯一需要current值的值;其他所有都只取决于邻居的数量。

答案 2 :(得分:1)

一种用于编码函数的强大技术是lookup tables。邻居数限制为0 ... 9,状态数为2,因此您可以使用大小为20的查找表:

bool NewStateLUT[2][10] = {
    {0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, // new states for dead cells
    {0, 0, 1, 1, 0, 0, 0, 0, 0, 0}  // new states for alive cells
};

使用此表的代码:

whatever.next = NewStateLUT[whatever.current][NeighbourCounter];

此代码假定DEAD为0且ALIVE等于1。如果DEADALIVE是枚举数,则可能需要调整语法。


由于LUT仅包含0和1,因此使用位图代替数组很容易:

uint32_t NewStateBitmap = 0b0000000100'0000001100;
whatever.next = (NewStateBitmap >> (whatever.current * 10 + NeighbourCounter)) & 1;

答案 3 :(得分:0)

如果一个小区有3个邻居,或者当前是否还活着并且有两个邻居,则它是下一代的活体。

这也许有点异端,但我想知道ALIVE和DEAD的构架是否没有妨碍。另一种方法是将当前字段重命名为now_alive,然后将其重命名为next_alive,然后在其中存储0或1。

然后可以编写下一个活着的计算

C->next_alive = (N == 3) || (C->now_alive+N) == 3;

其中C指向该单元格,N是其邻居数。