为何我的初等元胞自动机按规则集无法显示正确图像?
问题分析与修复方案
核心问题1:原数组被实时修改,状态污染
你在计算每个细胞的下一代状态时,直接把新值写到gen[procces]里,后面的细胞计算时,用到的邻居状态已经是更新后的,不是最初的上一代状态——这直接打乱了元胞自动机的演化逻辑,只有规则2这种极简单的规则碰巧没出问题。
核心问题2:数组边界越界,读取随机值
处理第一个细胞(procces=0)时,procces-1是-1,访问gen[-1]属于数组越界,会读内存里的随机垃圾值;处理最后一个细胞时,procces+1超出数组长度,同样越界读随机值,这就是你看到随机输出的主要原因。
修复后的完整代码
#include <stdio.h> // 初始状态,统一格式避免长度混乱 int gen[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; // 示例规则集:规则30,可自行替换成其他规则 int ruleset[] = {0,0,0,1,1,1,1,0}; int size = sizeof(gen) / sizeof(gen[0]); const int alive = 1; const int dead = 0; int rules(int a, int b, int c) { // 把三位邻居状态转成二进制索引,比一堆if简洁多了 int index = (a << 2) | (b << 1) | c; // 反转索引对应你原来的if顺序(从111到000对应ruleset[0]到[7]) return ruleset[7 - index]; } int main(void) { // 用临时数组存下一代状态,避免修改原数组影响计算 int next_gen[sizeof(gen)/sizeof(gen[0])]; int iterations; int process; // 先打印初始状态,原来的代码直接跳过了这一步 for (process = 0; process < size; process++) { printf(gen[process] == alive ? "@" : " "); } printf("\n"); for (iterations = 0; iterations < 100; iterations++) { for (process = 0; process < size; process++) { // 循环边界处理:首尾细胞的邻居绕到数组另一端,符合初等元胞自动机常规设定 int left = (process == 0) ? gen[size - 1] : gen[process - 1]; int right = (process == size - 1) ? gen[0] : gen[process + 1]; int cell = gen[process]; next_gen[process] = rules(left, cell, right); } // 所有细胞计算完再更新原数组,同时打印当前代 for (process = 0; process < size; process++) { gen[process] = next_gen[process]; printf(gen[process] == alive ? "@" : " "); } printf("\n"); } return 0; }
关键修复点
- 临时数组
next_gen:先把所有细胞的下一代状态算完存到临时数组,再覆盖原数组,保证每一步都用上一代的完整状态计算。 - 边界处理:用循环边界解决越界问题,让数组首尾相连,符合初等元胞自动机的标准行为。
- 简化规则函数:用二进制转索引的方式替代一堆
if,既高效又不容易写错。 - 补全初始状态打印:原来的代码直接开始迭代,现在先输出初始状态,逻辑更完整。
内容的提问来源于stack exchange,提问作者Saw
相关产品推荐
相关产品推荐

