Python实现康威生命游戏:如何检测数组边角/边界单元格?
解决康威生命游戏的边界索引错误问题
嘿,这个索引错误的坑我当初写生命游戏的时候也踩过!问题出在你直接访问x-1、x+1这类坐标时,没有考虑单元格处于数组边界或边角的情况——比如当x=0时,x-1就是-1,这在普通列表里直接就会抛出索引错误,就算是NumPy数组也会默认做环绕(但你明确说不需要环绕),所以咱们得先判断邻居坐标是否在数组的有效范围内。
问题根源
你的代码直接把8个方向的邻居都列出来,但对于边界单元格来说,有些邻居根本不存在(比如左上角的单元格没有左上方、上方、左方的邻居),强行访问这些不存在的索引就会报错。另外你当前返回的updated_array是一维列表,和输入的二维数组结构不匹配,后续迭代也会出问题。
修复方案:先验证邻居坐标的有效性
我们可以先定义所有8个邻居的坐标偏移量,然后逐个检查每个偏移后的坐标是否在数组的行和列范围内,只有有效的坐标才计入邻居数量,同时把输出改成和输入一致的二维结构。
修改后的代码(兼容普通嵌套列表)
import numpy def new_state(array): rows = len(array) cols = len(array[0]) if rows > 0 else 0 # 初始化和输入同尺寸的二维结果数组 updated_array = [[0 for _ in range(cols)] for _ in range(rows)] # 定义8个邻居的坐标偏移(上下左右+四个对角线) neighbor_offsets = [(-1, -1), (0, -1), (1, -1), (1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0)] for x in range(rows): for y in range(cols): cell = array[x][y] neighbours_count = 0 # 遍历每个邻居偏移,检查坐标是否在有效范围内 for dx, dy in neighbor_offsets: nx = x + dx ny = y + dy # 只有当坐标在数组边界内时,才统计这个邻居 if 0 <= nx < rows and 0 <= ny < cols: neighbours_count += array[nx][ny] # 根据生命游戏规则更新单元格状态 if cell == 1: updated_array[x][y] = 1 if neighbours_count in (2, 3) else 0 else: updated_array[x][y] = 1 if neighbours_count == 3 else 0 return updated_array
关键改进点
- 边界检查:通过
0 <= nx < rows和0 <= ny < cols过滤无效坐标,彻底避免索引错误 - 二维结果结构:保证输出和输入的二维数组结构一致,方便后续迭代使用
- 简化规则判断:用
in (2,3)替代多个elif,让代码逻辑更清晰
如果你想用NumPy优化(更高效)
既然你提到结合NumPy,其实可以用卷积操作快速统计邻居数量,处理大网格时速度会快很多,而且不需要手动写边界检查:
import numpy as np from scipy.signal import convolve2d def new_state_numpy(array): arr = np.array(array) # 定义3x3卷积核,中心为0(不统计自身),周围8个位置为1 kernel = np.array([[1,1,1], [1,0,1], [1,1,1]]) # 计算邻居数量,边界外的单元格视为0 neighbours_count = convolve2d(arr, kernel, mode='same', boundary='fill', fillvalue=0) # 根据规则生成新状态 new_arr = np.where( (arr == 1) & ((neighbours_count == 2) | (neighbours_count == 3)), 1, np.where((arr == 0) & (neighbours_count == 3), 1, 0) ) return new_arr.tolist() # 如需转回列表格式可调用此方法
这个版本利用NumPy的向量化操作和卷积功能,省去了嵌套循环的繁琐,边界处理也更简洁。
内容的提问来源于stack exchange,提问作者coding girl
相关产品推荐
相关产品推荐

