我正在为生活游戏编写代码。其中一个功能应该“演化”当前单元格。这意味着我必须具有一些条件,如果if语句满足条件,则该单元将变为DEAD或ALIVE单元。
但是,只有一些下一个正在初始化的单元格,因此我必须将其余不受条件影响的下一个单元格设置为DEAD。
由于有四个条件,我想将我的if语句压缩到最小的数量。
条件是:
我已经尝试将多个条件分别拟合到一个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`”中。
答案 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。如果DEAD
和ALIVE
是枚举数,则可能需要调整语法。
由于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是其邻居数。