康威生命游戏双问题求助:网格关联异常与Matplotlib绘图失效
Hey there! Let's tackle your Conway's Game of Life issues one by one—they're both common pitfalls, so you're not alone here.
Problem 2: grid_1 and grid_2 update synchronously (you were right about line 91!)
Your hunch about line 91 is on track, but there's a hidden issue in your __update_table method that's making things worse. Here's the breakdown:
- grid_2 isn't being reset between cycles: Right now, you're modifying cells in
grid_2without clearing its old state first. That means cells that should turn 0 stay at their previous value if your code doesn't explicitly set them—leading to stale data bleeding into new cycles. - Incomplete state updates in
__update_table: Your code only sets values for cells that meet specific conditions, but doesn't handle cases where a cell should stay 0. This leaves old values lingering ingrid_2.
Fixes:
Option 1: Reset grid_2 at the start of each cycle
def cycle(self): ''' Call method to cycle through game one time ''' # Wipe grid_2 clean before calculating new state self.grid_2 = np.zeros((Game.SIZE, Game.SIZE), dtype=int) for r in range(Game.SIZE): for c in range(Game.SIZE): self.__get_neighbours(r, c) self.__update_table(r, c) # Safely copy the new state to grid_1 self.grid_1 = self.grid_2.copy()
Option 2: Complete all state updates in __update_table
def __update_table(self, r, c): ''' Table is updated with Conway's Rules ''' if self.grid_1[r][c] == 1: if self.total < 2 or self.total > 3: self.grid_2[r][c] = 0 else: self.grid_2[r][c] = 1 else: if self.total == 3: self.grid_2[r][c] = 1 else: # Explicitly set to 0 if no birth condition is met self.grid_2[r][c] = 0
Either fix will ensure grid_2 only holds fresh, calculated values each cycle, so grid_1 won't sync with it unexpectedly.
Problem 1: All cells show a single value in the animation
This is mostly a side effect of the grid sync issue, but a small Matplotlib tweak will make your animation behave as expected:
- Use a discrete colormap: The default colormap is continuous, which can cause weird rendering for binary 0/1 data. Switch to a discrete one like
cm.binaryfor clear black/white cells. - Update the correct grid: After
cycle()runs,grid_1holds the latest state (since you copygrid_2into it), so you should passgrid_1toset_array().
Fixed animation code:
def update_grid(*args): grid.cycle() # Update with the latest state stored in grid_1 im.set_array(grid.grid_1) return im, fig, ax = plt.subplots() ax.axis('off') # Initialize with grid_1's starting state and use a binary colormap im = plt.imshow(grid.grid_1, interpolation="nearest", animated=True, cmap=cm.binary) anim = animation.FuncAnimation(fig, update_grid, frames=60, interval=150, blit=True) plt.show()
Optional Quality-of-Life Tweak
You can simplify your __get_neighbours method using numpy slicing to avoid nested loops (it's faster too, especially for larger grids):
def __get_neighbours(self, r, c): ''' Calculates number of live neighbours around a given cell ''' # Handle edge cases by clamping slice bounds to the grid size start_r, end_r = max(0, r-1), min(Game.SIZE, r+2) start_c, end_c = max(0, c-1), min(Game.SIZE, c+2) # Sum the 3x3 neighborhood and subtract the cell itself self.total = np.sum(self.grid_1[start_r:end_r, start_c:end_c]) - self.grid_1[r][c]
内容的提问来源于stack exchange,提问作者Gandalf

