我正致力于加速康威的生命游戏。现在,代码查看一个单元格,然后在该点周围加上3x3区域,然后在我们正在查看的点处减去该值。以下是正在执行此操作的功能:
static int neighbors2 (board b, int i, int j)
{
int n = 0;
int i_left = max(0,i-1);
int i_right = min(HEIGHT, i+2);
int j_left = max(0,j-1);
int j_right = min(WIDTH, j+2);
int ii, jj;
for (jj = j_left; jj < j_right; ++jj) {
for (ii = i_left; ii < i_right; ii++) {
n += b[ii][jj];
}
}
return n - b[i][j];
}
以下是我一直试图用来迭代碎片的代码:
//Iterates through the first row of the 3x3 area
static int first_row(board b, int i, int j) {
int f = 0;
int i_left = max(0,i-1);
int j_left = max(0,j-1);
int j_right = min(WIDTH, j+2);
int jj;
for (jj = j_left; jj < j_right; ++jj) {
f += b[i_left][jj];
}
return f;
}
//Iterates and adds up the second row of the 3x3 area
static int second_row(board b, int i, int j) {
int g = 0;
int i_right = min(HEIGHT, i+2);
int j_left = max(0,j-1);
int j_right = min(WIDTH, j+2);
int jj;
if (i_right != i) {
for (jj = j_left; jj < j_right; ++jj) {
g += b[i][jj];
}
}
return g;
}
//iterates and adds up the third row of the 3x3 area.
static int third_row(board b, int i, int j) {
int h = 0;
int i_right = min(HEIGHT, i+2);
int j_left = max(0,j-1);
int j_right = min(WIDTH, j+2);
int jj;
for (jj = j_left; jj < j_right; ++jj) {
h += b[i_right][jj];
}
return h;
}
//adds up the surrounding spots
//subtracts the spot we're looking at.
static int addUp(board b, int i, int j) {
int n = first_row(b, i, j) + second_row(b, i, j) + third_row(b, i, j);
return n - b[i][j];
}
但是,由于某种原因,它不起作用。我不明白为什么。
需要注意的事项:
i == i_right
,所以我们不想两次加一行。neighbors2
完全相同。min
和max
是我预先制作的功能。j == j_right
,所以我们不想两次加起来。我非常有信心循环可以解决这个问题。谢谢大家。我现在已经在这个工作了几个小时,不知道出了什么问题。它似乎应该可以工作,但我一直在董事会的随机位置得到不正确的解决方案。
答案 0 :(得分:0)
在neighbors2
中,您设置i_left
和i_right
,以便将“#”限制为网格行。如果当前单元格位于顶行或底行,则只循环两行而不是3行。
在first_row()
和last_row()
中,您还将其限制为网格的行。但结果是这些函数会将单元格添加到与当前单元格相同的行上,这是second_row
的作用。所以你最终将这些行添加两次。
first_row()
时你不应该致电i = 0
,而third_row()
时你不应该致电i == HEIGHT
。
static int addUp(board b, int i, int j) {
int n = (i == 0 ? 0 : first_row(b, i, j)) +
second_row(b, i, j) +
(i == HEIGHT ? 0 : third_row(b, i, j));
return n - b[i][j];
}
另一个选择是检查函数本身:
function first_row((board b, int i, int j) {
if (i == 0) {
return 0;
}
int f = 0;
int j_left = max(0,j-1);
int j_right = min(WIDTH, j+2);
int jj;
for (jj = j_left; jj < j_right; ++jj) {
f += b[i][jj];
}
return f;
}
,同样适用于third_row()
。但是在调用者中执行此操作可以节省函数调用的开销。
i
变量都是行,从上到下,而不是从左到右。
答案 1 :(得分:0)
#include <stdio.h>
#include <stdlib.h>
#define ROWSDISP 50
#define COLSDISP 100
int rows=ROWSDISP+2, cols=COLSDISP+2;
这是为了避免在穿越邻居时出现非法索引。
struct onecell {char alive;
char neibs;} **cells;
这是(动态)二维数组的小型结构的基础。
为每行创建空间,再加上容纳行指针数组的空间:
void init_cells()
{
int i;
cells = calloc(rows, sizeof(*cells));
for(i=0; i<=rows-1; i++)
cells[i] = calloc(cols, sizeof(**cells));
}
我跳过rand_fill()和glider()函数。可以设置一个单元格
cells[y][x].alive=1
。
int main(void) {
struct onecell *c, *n1, *rlow;
int i, j, loops=0;
char nbs;
init_cells();
rand_fill();
glider();
while (loops++ < 1000) {
printf("\n%d\n", loops);
for (i = 1; i <= rows-2; i++) {
for (j = 1; j <= cols-2; j++) {
c = &cells[ i ][ j ];
n1 = &cells[ i ][j+1];
rlow = cells[i+1];
nbs = c->neibs + n1->alive + rlow[ j ].alive
+ rlow[j+1].alive
+ rlow[j-1].alive;
if(c->alive) {
printf("@");
n1->neibs++;
rlow[ j ].neibs++;
rlow[j+1].neibs++;
rlow[j-1].neibs++;
if(nbs < 2 || nbs > 3)
c->alive = 0;
} else {
printf(" ");
if(nbs == 3)
c->alive = 1;
}
c->neibs = 0; // reset for next cycle
}
printf("\n");
}
}
return(0);
}
这里没有迭代3x3正方形。在这8个邻居中 仅检查下游的4个;但同时 他们的柜台都升了。
具有100x100网格的基准:
# time ./a.out >/dev/null
real 0m0.084s
user 0m0.084s
sys 0m0.000s
# bc <<<100*100*1000/.084
119047619
这100M单元中的每一个都需要检查8个邻居,因此这接近CPU频率(每个周期1个邻居检查)。
这似乎是Rosetta代码解决方案的两倍。
也不需要切换电路板。感谢对单元第二个领域的投资。