Python实现生命游戏问题:next_step函数返回结果异常
生命游戏代码问题排查
这个程序负责实现生命游戏的下一代状态计算,核心包含三个部分:计算每个细胞的存活邻居数量、应用生命游戏规则、处理1/0与True/False的类型转换。目前本地测试结果看似正确,但提交到教师评测网站后被判定结果错误,以下是原代码及问题分析:
原代码
from typing import List import copy as cp def next_step(pop: List[List[bool]]) -> List[List[bool]]: ''' renvoie la prochaine population ''' L=[[0]*len(pop) for x in range(len(pop))] #init M=cp.deepcopy(pop) #coins L[0][0]=pop[0][1]+pop[1][1]+pop[1][0]+pop[0][-1]+pop[1][-1]+pop[-1][-1]+pop[-1][0]+pop[-1][1] L[0][-1]=pop[0][0]+pop[1][0]+pop[-1][0]+pop[0][-2]+pop[-1][-2]+pop[-1][-1]+pop[1][-1]+pop[1][-2] L[-1][0]=pop[0][0]+pop[0][1]+pop[-2][0]+pop[-2][-1]+pop[-1][1]+pop[-1][0]+pop[-1][-1]+pop[-2][-1] L[-1][-1]=pop[0][0]+pop[0][-2]+pop[0][-1]+pop[-2][0]+pop[-1][0]+pop[-2][-2]+pop[-2][-1]+pop[-1][-2] #bords for i in range(1,len(pop)-1): L[0][i]=pop[0][i-1]+pop[0][i+1]+pop[1][i]+pop[1][i-1]+pop[1][i+1]+pop[-1][i]+pop[-1][i-1]+pop[-1][i+1] for i in range(1,len(pop)-1): L[-1][i]=pop[-1][i-1]+pop[-1][i+1]+pop[-2][i]+pop[-2][i-1]+pop[-2][i+1]+pop[0][i]+pop[0][i-1]+pop[0][i+1] for j in range(1,len(pop)-1): L[j][0]=pop[j-1][0]+pop[j+1][0]+pop[j][1]+pop[j-1][1]+pop[j+1][1]+pop[j-1][-1]+pop[j][-1]+pop[j+1][-1] for j in range(1,len(pop)-1): L[j][-1]=pop[j-1][-1]+pop[j+1][-1]+pop[j][-2]+pop[j-1][-2]+pop[j+1][-2]+pop[j][0]+pop[j-1][0]+pop[j+1][0] #milieu for u in range(1,len(pop)-1): for v in range(1,len(pop)-1): L[u][v]=pop[u-1][v-1]+pop[u-1][v]+pop[u-1][v+1]+pop[u][v-1]+pop[u][v+1]+pop[u+1][v-1]+pop[u+1][v]+pop[u+1][v+1] for k in range(len(M)): for i in range(len(M)): if L[k][i]==3: if pop[k][i]==False: M[k][i]=True elif L[k][i]==2: if pop[k][i]==True: M[k][i]=True else: M[k][i]=False for k in range(len(M)): for i in range(len(M)): if M[k][i]==0: M[k][i]=False if M[k][i]==1: M[k][i]=True return M
核心问题分析
- 边界邻居计数错误:手动计算角落和边缘细胞的邻居时出现重复统计,比如
L[-1][0]中重复累加了pop[-2][-1],导致邻居数量统计失真,这是评测不通过的主要原因。 - 生命游戏规则实现错误:当邻居数为3时,原代码仅处理原细胞为
False的情况,但根据规则,无论原细胞是否存活,只要有3个邻居就会存活(或复活),这个判断逻辑遗漏了原细胞为True的场景。 - 冗余类型转换:最后循环将0/1转为True/False完全多余,因为
M是从pop深拷贝而来的bool类型矩阵,前面的逻辑已经直接赋值True/False,这一步不仅无用,还可能引入潜在错误。 - 假设输入为方阵:代码默认输入是行列数相等的方阵,但函数参数允许任意二维bool列表,若评测用例包含非方阵输入,会直接报错。
修正后的代码
from typing import List import copy as cp def next_step(pop: List[List[bool]]) -> List[List[bool]]: ''' 返回下一代细胞状态 ''' rows = len(pop) cols = len(pop[0]) if rows > 0 else 0 # 初始化邻居计数矩阵 neighbor_count = [[0] * cols for _ in range(rows)] new_pop = cp.deepcopy(pop) # 遍历每个细胞,计算8个方向的邻居数(循环边界处理) for i in range(rows): for j in range(cols): count = 0 # 遍历所有相邻方向(排除自身) for di in (-1, 0, 1): for dj in (-1, 0, 1): if di == 0 and dj == 0: continue # 模运算实现循环边界(边缘细胞的邻居对应对面边缘) ni = (i + di) % rows nj = (j + dj) % cols count += pop[ni][nj] neighbor_count[i][j] = count # 应用生命游戏规则 for i in range(rows): for j in range(cols): cnt = neighbor_count[i][j] if cnt == 3: new_pop[i][j] = True elif cnt != 2: new_pop[i][j] = False # 邻居数为2时保持原状态,无需修改 return new_pop
修正说明
- 用通用的8方向遍历+模运算处理循环边界,彻底避免手动计算边界时的重复/遗漏问题,代码更简洁易维护。
- 修正规则逻辑:邻居数为3时直接设为
True;邻居数不为2时设为False;邻居数为2时保持原状态(因new_pop是深拷贝,无需额外赋值)。 - 移除冗余的类型转换步骤,保留bool类型的一致性。
- 兼容非方阵输入,扩大代码适用范围。
内容的提问来源于stack exchange,提问作者THIBZ EDIT
相关产品推荐
相关产品推荐

