Conway's Game of Life实现错误排查:代码逻辑问题分析
康威生命游戏代码逻辑问题排查
问题描述
我正在实现康威生命游戏,规则如下:
- 存活细胞(X):
- 存活邻居少于2个 → 死亡(-)
- 存活邻居为2或3个 → 存活(X)
- 存活邻居超过3个 → 死亡(-)
- 死亡细胞(-):
- 存活邻居恰好3个 → 变为存活(X)
给定初始网格:
------- ------- ------X ---XXXX ------X
预期下一代网格:
------- ------- ----X-X ----X-X ----X-X
但代码生成的输出为:
------- ------- ----X-- ----X-- -------
以下是我的代码:
# #mark all places where new life will be born; # mark all organisms which will die; # remove all marked organisms; # fill all marked empty cells with new organisms. # Input data will contain 5 lines of 7 characters each. They represent a 5 by 7 fragment of the game field. def convert(initial_state= ('''------- ------- ------X ---XXXX ------X''')): #convert input into a list, so it is easier to operate on game_list = [] row_start = 0 row_end = 7 for _ in range(5): row_cells = '' for i in range(row_start,row_end): row_cells += initial_state[i] game_list.append(row_cells) row_start += 8 row_end += 8 return(game_list) def mark_cell(): #if cell has 0-1 or 3+ alive neighbours(X) - dies #if 2 neighbours - survives #if 3 neighbours - it becomes alive result = '' #life after day 1 (after one neighbour check for all cells) game_list = convert() for r in range(len(game_list)): result += ''' ''' for c in range(len(game_list[r])): choosen_cell = game_list[r][c] try: born_count = 0 neighbours = [game_list[r-1][c-1],game_list[r-1][c],game_list[r-1][c+1],game_list[r][c-1],game_list[r][c+1],game_list[r+1][c-1],game_list[r+1][c],game_list[r+1][c+1]] if r == 0 and c != 0 and c!= 6: neighbours = neighbours[3:] elif r == 4 and c != 0 and c!= 6: neighbours = neighbours[:5] elif c == 0 and r != 0 and r != 4: del neighbours[5] del neighbours[3] del neighbours[0] elif c == 6 and r != 0 and r != 4: del neighbours[7] del neighbours[4] del neighbours[2] elif r == 0 and c == 0: neighbours = neighbours[3:] del neighbours[2] del neighbours[0] elif r == 0 and c == 6: neighbours = neighbours[3:] del neighbours[4] del neighbours[1] elif r == 4 and c == 0: neighbours = neighbours[:5] del neighbours[3] del neighbours[0] elif r == 4 and c == 6: neighbours = neighbours[:5] del neighbours[4] del neighbours[2] for num in neighbours: if num == "X": born_count +=1 except IndexError: pass finally: pass if born_count < 2 or born_count > 3: result += "-" elif born_count == 3: result += "X" else: result += choosen_cell print (result) return result mark_cell()
核心逻辑问题分析
1. 边界邻居访问错误,异常处理失效
- 负索引陷阱:当访问
r-1(如r=0时r-1=-1),Python会将负索引解析为列表末尾元素,错误地把网格最后一行当作当前行的上一行邻居,而非判定为非法坐标。 - 异常处理逻辑错误:当访问超出列范围的索引(如
c=6时c+1=7),触发IndexError后直接pass,导致born_count保持为0,完全忽略了其他合法邻居的统计。
2. 手动裁剪邻居列表逻辑疏漏
通过先构建包含非法索引的列表再删除元素的方式极易出错,比如当c=6时,触发异常后删除元素的代码根本不会执行,导致邻居统计完全错误。
修复方案
步骤1:正确统计存活邻居
替换手动构建邻居列表的方式,通过遍历方向偏移量并检查坐标合法性,准确统计存活邻居:
def count_alive_neighbors(grid, row, col): rows = len(grid) cols = len(grid[0]) alive_count = 0 # 遍历8个方向的坐标偏移 directions = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)] for dr, dc in directions: r = row + dr c = col + dc # 仅统计网格范围内的邻居 if 0 <= r < rows and 0 <= c < cols: if grid[r][c] == 'X': alive_count += 1 return alive_count
步骤2:简化convert函数
用字符串分割替代索引截取,逻辑更清晰:
def convert(initial_state= ('''------- ------- ------X ---XXXX ------X''')): return [line.strip() for line in initial_state.split('\n') if line.strip()]
步骤3:修正主逻辑函数
基于正确的邻居统计结果,重新实现状态转换逻辑:
def mark_cell(): game_list = convert() rows = len(game_list) cols = len(game_list[0]) result = [] for r in range(rows): new_row = [] for c in range(cols): current_cell = game_list[r][c] alive_neighbors = count_alive_neighbors(game_list, r, c) # 应用生命游戏规则 if current_cell == 'X': if alive_neighbors < 2 or alive_neighbors > 3: new_row.append('-') else: new_row.append('X') else: if alive_neighbors == 3: new_row.append('X') else: new_row.append('-') result.append(''.join(new_row)) # 输出格式化结果 print('\n'.join(result)) return '\n'.join(result) mark_cell()
修复后输出
运行修正后的代码,将得到预期结果:
------- ------- ----X-X ----X-X ----X-X
内容的提问来源于stack exchange,提问作者mudyro
相关产品推荐
相关产品推荐

