Python 实施康威的生命游戏

Python implementation of Conway's Game of Life

出于学习目的,我已经开始创建康威生命游戏的实现。我用 numpy 来存储大数组,连接死细胞和活细胞,然后我应用康威规则来创建细胞生命机制。为了管理网格和图形,我使用了 pygame 模块。 看了很多次,改写了很多次代码,也查不出哪里有问题,所以决定问问大家。例如,我曾尝试制作滑翔机(如代码所示),但他在 3 个循环周期后死亡。如果您能提供帮助和提示,我将不胜感激。你能帮我找出为什么细胞不能繁殖吗?提前致谢。 代码:

import pygame
import numpy as np

BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
N = 195
WIDTH = 10
HEIGHT = 10

grid = np.zeros(shape=(N, N), dtype=np.int32)
glider = np.array([[0, 0, 1],
                       [1, 0, 1],
                       [0, 1, 1]])
grid[3:6, 3:6] = glider

pygame.init()

WINDOW_SIZE = [980, 980]
screen = pygame.display.set_mode(WINDOW_SIZE)

pygame.display.set_caption("GAME OF LIFE")

done = False

clock = pygame.time.Clock()

while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
    for row in range(N):
        for column in range(N):
            color = BLACK
            if grid[row][column] == 1:
                color = GREEN
            pygame.draw.rect(screen, color,
                             [WIDTH * column,
                              HEIGHT * row,
                              WIDTH,
                              HEIGHT])

    newGrid = grid.copy()
    for i in range(N):
        for j in range(N):
            total = grid[(i-1) % N:(i+1) % N, (j-1) % N:(j+1) % N].sum() - grid[i, j]
            if grid[i, j] == 1:
                if(total < 2) or (total > 3):
                    newGrid[i, j] = 0
                else:
                    if total == 3:
                        newGrid[i, j] = 1
    grid = newGrid

    clock.tick(60)
    pygame.display.flip()

pygame.quit()

可能是 newGrid 循环中的 else 子句过度缩进了?因为截至目前,网格仅从 1 变为 0 而从未从 0 变为 1。这可能是因为数组切片:[(i-1) % n : (i+1) % n]。有 2 个问题:

  1. 这只计入 (i+1) % n 之前的索引,所以它不包括 (i+1) % n。
  2. 它不会像您预期的那样环绕,例如[9:1] 不会从 9 到 10 再到 0 并在 1 之前停止。它只是 returns 空列表。

这里有一个技巧

a.take(range(-1,2),mode='wrap', axis=0).take(range(-1,2),mode='wrap',axis=1)

来自这个 post Wrap slice around edges of a 2D array in numpy。我用这个技巧修改了下面的代码。

import pygame
import numpy as np

BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
N = 195
WIDTH = 10
HEIGHT = 10

grid = np.zeros(shape=(N, N), dtype=np.int32)
glider = np.array([[0, 0, 1],
                       [1, 0, 1],
                       [0, 1, 1]])
grid[3:6, 3:6] = glider

pygame.init()

WINDOW_SIZE = [980, 980]
screen = pygame.display.set_mode(WINDOW_SIZE)

pygame.display.set_caption("GAME OF LIFE")

done = False

clock = pygame.time.Clock()

while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
    for row in range(N):
        for column in range(N):
            color = BLACK
            if grid[row][column] == 1:
                color = GREEN
            pygame.draw.rect(screen, color,
                             [WIDTH * column,
                              HEIGHT * row,
                              WIDTH,
                              HEIGHT])

    newGrid = grid.copy()
    for i in range(N):
        for j in range(N):
            total = grid.take(range(i-1,i+2),mode='wrap', axis=0).take(range(j-1,j+2),mode='wrap',axis=1).sum() - grid[i, j]
            if grid[i, j] == 1:
                if(total < 2) or (total > 3):
                    newGrid[i, j] = 0
            else:
                if total == 3:
                    newGrid[i, j] = 1
    grid = newGrid

    clock.tick(60)
    pygame.display.flip()

pygame.quit()

我认为您在实现 Conway's rules 的方式中存在一些细微的错误。 详情见我在代码中的注释:

for i in range(N):
    for j in range(N):
        # I changed the range of the extent of the sum, note +2 rather than +1 !
        total = grid[(i-1) % N:(i+2) % N, (j-1) % N:(j+2) % N].sum() - grid[i, j]
        if grid[i, j] == 1:
            if(total < 2) or (total > 3):
                newGrid[i, j] = 0
            # allow for survival in case of total = 2 or 3 (this could be dropped though)
            else:
                newGrid[i, j] = 1
        # allow for reproduction if cell is empty
        else:
            if total == 3:
                newGrid[i, j] = 1

通过这些编辑,滑翔机应该可以滑翔了:)