模拟康威生命游戏:状态更新函数失效无输出,求调试
康威生命游戏状态更新函数修复
我在模拟康威生命游戏时,前两个生成初始状态的函数能正常运行,但最后一个更新状态的one_generation_later函数完全没有输出,没法按照游戏规则更新数组。要求不能修改前两个生成数组的函数,只修复第三个函数。
原代码如下:
import numpy as np import random # helper function no. 1 def seed_probabilities(i,j): rand_num = random.random() x = 1/(abs(i - j) + 2) if rand_num < x: y = 1 else: y = 0 return y def create_world(nr, nc): # make array values = np.empty((nr,nc), dtype=int) # index array for i in range(0,nr): for j in range(0, nc): y = seed_probabilities(i,j) values[i,j]=y return values values = create_world(6,7) def one_generation_later(w): (nc, nr) = np.shape(w) for i in range(0,nr): for j in range(0, nc): L = [w[i,j-1], w[i,j+1], w[i-1,j], w[i-1,j-1], w[i-1,j+1], w[i+1,j], w[i+1, j-1], w[i+1,j+1]] neighborhood = [] for k in L: if L[k]==1: neighborhood.append(L[k]) num_alive = len(neighborhood) if w[i,j] == 1 and num_alive > 3: w[i,j] = 0 elif w[i,j] == 1 and num_alive <2: w[i,j] = 0 elif w[i,j] == 1 and 2 < num_alive < 3: w[i,j] = 1 elif w[i,j] == 0 and num_alive == 3: w[i,j] = 1 return w one_generation_later(values)
我原本打算把初始数组传入第三个函数,遍历每个单元格获取邻域列表,通过列表长度判断细胞生死,但完全没成功。
问题分析与修复
原函数存在几个关键错误:
- 数组形状顺序颠倒:
np.shape(w)返回的是(行数, 列数),原代码写成(nc, nr),导致循环范围错误,遍历逻辑完全混乱。 - 边界索引越界未处理:比如i=0时
i-1=-1,numpy会取数组最后一行,不符合生命游戏“边界外细胞全死”的规则,需要手动处理边界情况。 - 邻居统计逻辑错误:遍历邻域列表时用元素值当索引(
L[k]==1)完全错误,应该直接统计列表中1的数量;且不能边统计边修改原数组,必须基于当前代的完整状态计算下一代,否则后续单元格会使用已修改的状态,导致结果错误。 - 直接修改原数组:遍历过程中修改原数组会干扰后续计算,必须创建原数组的副本,在副本上更新状态。
修复后的one_generation_later函数:
def one_generation_later(w): nr, nc = np.shape(w) # 创建原数组的副本,避免修改原数据影响计算 new_w = w.copy() for i in range(nr): for j in range(nc): num_alive = 0 # 遍历8个方向的邻居 for di in [-1, 0, 1]: for dj in [-1, 0, 1]: # 跳过当前单元格本身 if di == 0 and dj == 0: continue ni, nj = i + di, j + dj # 检查邻居是否在数组范围内,不在则视为死细胞(0) if 0 <= ni < nr and 0 <= nj < nc: num_alive += w[ni, nj] # 根据生命游戏规则更新状态 if w[i,j] == 1: if num_alive < 2 or num_alive > 3: new_w[i,j] = 0 # 存活数为2或3时保持存活,无需修改 else: if num_alive == 3: new_w[i,j] = 1 return new_w
修复点说明
- 修正数组形状的顺序,确保循环能遍历所有单元格。
- 用双重循环遍历8个方向邻居,手动处理边界:超出数组范围的邻居视为死细胞,不计入存活数。
- 先完整统计当前单元格的存活邻居数量,再根据规则更新副本数组,保证所有计算都基于当前代的初始状态。
- 使用原数组的副本存储下一代状态,避免修改原数组导致的计算错误。
现在调用one_generation_later(values)就能得到正确的下一代状态,比如可以打印结果查看:
print(one_generation_later(values))
内容的提问来源于stack exchange,提问作者Etaoin Shrdlu
相关产品推荐
相关产品推荐

