You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

康威生命游戏(Python+Tkinter)邻居计数问题排查求助

康威生命游戏:邻居计数与状态更新问题修复

问题根源分析

你的代码存在四个核心问题,导致运行效果不符合预期:

  1. 邻居计数重复/遗漏:get_neighbours函数重复计算了(x-1, y+1)方向的邻居,同时遗漏了(x+1, y-1)方向的邻居,导致计数结果错误。
  2. 新状态矩阵未重置:cells_new在每次迭代后未被重置为全0,上一轮的状态会残留到下一次计算中。
  3. 固定维度变量不更新:absvs变量固定为初始值10,当通过滑块调整vs后,矩阵维度和循环范围不匹配,导致逻辑混乱。
  4. 矩阵引用赋值错误:cells = cells_new是引用传递,后续修改cells_new会直接影响cells的状态。

修复方案

1. 修正邻居计数函数

重新编写get_neighbours,遍历所有8个可能的邻居方向,每个方向仅判断一次,写法更简洁且避免遗漏:

def get_neighbours(x, y, grid):
    rows, cols = grid.shape
    total = 0
    # 遍历8个方向的偏移量,跳过自身
    for dx in (-1, 0, 1):
        for dy in (-1, 0, 1):
            if dx == 0 and dy == 0:
                continue
            nx = x + dx
            ny = y + dy
            # 判断邻居是否在网格范围内
            if 0 <= nx < rows and 0 <= ny < cols:
                total += grid[nx, ny]
    return total

2. 修复状态更新逻辑

在recalculate中,每次迭代前重新创建cells_new避免状态残留,使用拷贝赋值而非引用传递:

def recalculate():
    global cells
    rows, cols = cells.shape
    # 每次迭代重新创建新矩阵
    cells_new = np.zeros((rows, cols), dtype=int)
    
    for x in range(rows):
        for y in range(cols):
            neighbor_count = get_neighbours(x, y, cells)
            # 应用康威生命游戏规则
            if cells[x, y] == 1:
                cells_new[x, y] = 1 if (neighbor_count == 2 or neighbor_count == 3) else 0
            else:
                cells_new[x, y] = 1 if neighbor_count == 3 else 0
    # 使用拷贝赋值,避免引用问题
    cells = cells_new.copy()
    canvas.delete("all")
    create_stage()
    redraw_cell()

3. 修复滑块调整逻辑

滑块调整vs时,重新初始化cells矩阵匹配新网格大小,去掉冗余的absvs变量:

def slider_changer(e):
    global vs, cells
    canvas.delete("all")
    vs = w.get()
    # 重新初始化细胞矩阵
    cells = np.zeros((WIDTH//vs, HEIGHT//vs), dtype=int)
    create_stage()
    redraw_cell()

4. 修正细胞创建边界判断

create_cell函数中增加边界判断,避免点击超出网格范围导致的错误:

def create_cell(e):
    global cells
    tx = e.x // vs
    ty = e.y // vs
    rows, cols = cells.shape
    if 0 <= tx < rows and 0 <= ty < cols:
        x = tx * vs
        y = ty * vs
        canvas.create_rectangle(x, y, x + vs, y + vs, fill="gray")
        cells[tx, ty] = 1

完整修复代码

import tkinter as tk
import numpy as np

win = tk.Tk()

WIDTH = 500
HEIGHT = 500
vs = 10
cells = np.zeros((WIDTH//vs, HEIGHT//vs), dtype=int)

def get_neighbours(x, y, grid):
    rows, cols = grid.shape
    total = 0
    for dx in (-1, 0, 1):
        for dy in (-1, 0, 1):
            if dx == 0 and dy == 0:
                continue
            nx = x + dx
            ny = y + dy
            if 0 <= nx < rows and 0 <= ny < cols:
                total += grid[nx, ny]
    return total

def recalculate():
    global cells
    rows, cols = cells.shape
    cells_new = np.zeros((rows, cols), dtype=int)
    
    for x in range(rows):
        for y in range(cols):
            neighbor_count = get_neighbours(x, y, cells)
            if cells[x, y] == 1:
                cells_new[x, y] = 1 if (neighbor_count == 2 or neighbor_count == 3) else 0
            else:
                cells_new[x, y] = 1 if neighbor_count == 3 else 0
    cells = cells_new.copy()
    canvas.delete("all")
    create_stage()
    redraw_cell()

def slider_changer(e):
    global vs, cells
    canvas.delete("all")
    vs = w.get()
    cells = np.zeros((WIDTH//vs, HEIGHT//vs), dtype=int)
    create_stage()
    redraw_cell()

def create_cell(e):
    global cells
    tx = e.x // vs
    ty = e.y // vs
    rows, cols = cells.shape
    if 0 <= tx < rows and 0 <= ty < cols:
        x = tx * vs
        y = ty * vs
        canvas.create_rectangle(x, y, x + vs, y + vs, fill="gray")
        cells[tx, ty] = 1

def redraw_cell():
    rows, cols = cells.shape
    for x in range(rows):
        for y in range(cols):
            if cells[x, y] == 1:
                canvas.create_rectangle(x * vs, y * vs, x * vs + vs, y * vs + vs, fill="gray")

def create_stage():
    for x in range(WIDTH//vs):
        canvas.create_line(x*vs, 0, x*vs, HEIGHT)
    for y in range(HEIGHT//vs):
        canvas.create_line(0, y*vs, WIDTH, y*vs)

canvas = tk.Canvas(width=WIDTH, height=HEIGHT, bg="white")
canvas.pack()

w = tk.Scale(win, from_=10, to=50, orient="horizontal", command=slider_changer, length=500)
w.pack()
w2 = tk.Button(win, text="PRESS ME!!!", command=recalculate)
w2.pack()

create_stage()
canvas.bind("<Button-1>", create_cell)
win.mainloop()

内容的提问来源于stack exchange,提问作者Boggelino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 09:00:51