从2D C数组中的先前“行”获取值

时间:2011-09-18 04:56:52

标签: c arrays conways-game-of-life automaton

我正在进行一维生命游戏(基于Mathworld所列的规则)。基本上,每一代都表示为0或1(死或活)的行,下一代是基于“规则”命令行参数的二进制表示创建的。

例如,规则30变为00011110(二进制为30),这用于确定哪些位模式将在下一代中产生新单元或自行消失。

为了对此进行编程,我需要能够从前一行访问三个一组(以应用规则)中的位。下面是一个示例图像(请注意,起始行始终为0,中间为1):

00000100000  #seed row
11001011001  #generated from seed row
...........
11110010101  #n-th row, generated from n-1 row

为了生成一行,我必须以三个为一组的方式查看上面一行中的位,然后将该规则应用为1/0,live / die决策。

基本上我计划匹配3位模式和规则,并使用它来打印后代的0或1。这是一般的算法:

if three_bit_pattern == 'xxx' && rule[x] == 0/1 {print 0/1} else {print 1/0}

我遇到困难的程序部分是访问上一行的内容。我的所有尝试都会产生垃圾或不正确的数据。

简而言之,我如何以三位组的形式访问前一行的值?

行创建如下:

int i, j, k;
int row = atoi(argv[1]) + 1;
int col = 2 * atoi(argv[1]) + 1;

int arr[col];
int output[col];

char rule[9]; //binary representation of rule (2^8 stores up to 255 + null term)
int2binary(atoi(argv[2]), &rule, 10);

for(i = 0; i < row; i++){
   for(j = 0; j < col; j++){
    if(i == 0){
        if(j == col / 2) //print 1 in center of first row
        arr[i] = 1;     
        else
        arr[i] = 0;
        printf("%d", arr[i]);
    }
    else{
        //output[i] = arr[i-1];
        output[i+1] = arr[i];
        output[i+2] = arr[i+1];
        output[i+3] = arr[i+2];
        printf("%s", output);
    }
    }//end inner for_loop
   printf("\n");
}//end outer for_loop

}

好的,所以我把它变得更简单了,我只想要两个阵列(一个拿着前一列,另一个拿着当前的列)。我不明白为什么打印输出数组产生垃圾?输出[i] = arr [i]不是有效的表达式吗?

1 个答案:

答案 0 :(得分:2)

您尚未指定可能影响要使用的数据结构的输入或输出。例如,如果在计算它们时将它们打印出来,则可能只需保留两行甚至一行。看起来您打算将所有行保留在数组中。

看起来你的初始行有一个逻辑错误:

    if(firstTime == 1){
        if(j == row-1) //print 1 in center of first row
            arr[i][j] = 1;      
        else
            arr[i][j] = 0;
    }

应该是

    if(i == 0){
        if(j == col / 2) //print 1 in center of first row
            arr[i][j] = 1;      
        else
            arr[i][j] = 0;
    }

或更简单的东西。

生成其他行的算法并不复杂。

1)使用上面行的元素构建一个从0到7的数字。

2)按位&amp; 1&lt;(从1开始的数字)与获得结果的规则

parent = 0;
if(j>0 && arr[i-1][j-1]) parent = 4;
if(arr[i-1][j]) parent += 2;
if(j<col-1 && arr[i-1][j+1]) parent += 1;

position = 1 << parent;
arr[i][j] = (rule & position)?1:0;

有一些明显的方法可以让它更快。例如,根据前一列的父节点和右上角的单元格构建此列的父节点:&amp; 3,向左移,|细胞内容。唯一丑陋的部分是分别处理第一列和最后一列。

编辑回应评论:

该算法在具有位操作的整数中有一些自然的实现,这就是“规则XX”思想的来源。

从本质上讲,当前空间的选择取决于它上面的三个空间。这些有8种可能性。我们可以认为这些对应于一个字节的8位。

每个规则是从8种可能性集合到集合{0,1}的对应关系。有2 ^ 8 = 256种可能的对应关系或规则,巧合地与一个字节的可能值的数量相同。

标记规则的最方便的方法是使用一个数字来准确显示当前单元格如何由父单元格确定来填充。例如,

规则30:

30 = 16 + 8 + 4 + 2 = 2 ^ 4 + 2 ^ 3 + 2 ^ 2 + 2 ^ 1

因此规则是在父细胞为:

时填充细胞
4 = 100
3 = 011
2 = 010
1 = 001

另一个例子,仅复制前一行的规则是什么?

在这种情况下,如果上面的单元格已填满,我们会填充单元格,但相邻的单元格可以是任何单元格:

010 = 2
011 = 3
110 = 6
111 = 7

所以这是规则2 ^ 2 + 2 ^ 3 + 2 ^ 6 + 2 ^ 7 =规则4 + 8 + 64 + 128 =规则204.

我希望现在确定细胞的算法更有意义。

1)确定父母的模式数量。

2)确定2 ^模式是否是规则的一部分。如果是这样,请填写单元格。

我的另一个评论是你需要存储多少。如果您按原样输出,则只需要一行数组(即只有一个维度)。在遍历行时,可以使用下一行的值替换条目。唯一的困难是你需要以某种方式保持你要替换的当前值以用于确定下一个单元格。

但是你可以使用相同的技巧保留这个值并减少计算量:保留最后一个父数字; &安培;用3来删除左父母;将它向左移1; |与父母在右边。这将为您提供当前的父编号。小心处理数组的结束条目,你已经完成了。

另一个编辑:

首先实现以前的版本,但是如果你真的想节省空间并且更加烦恼,那么尝试将行存储为整数的位值而不是1和0的数组。如果你想要一个行甚至长于long中的位数,那么你需要一个包含这些位的整数数组,以及一些疯狂的位操作来处理两个这样的整数边界上的单元格。玩得开心!