Анимация Matplotlib - объект типа 'int' не имеет len () - PullRequest
0 голосов
/ 17 мая 2018

Я пытаюсь оживить игру жизни Конвея , но я застреваю.Мой код ниже.Желаемым поведением является то, что он принимает двоичный массив, обновляет его в соответствии с правилами Конвея несколько раз и показывает каждый шаг анимации.

Обратите внимание, что я пытался реализовать его так, чтобы юниверс был 'обернутый ', сверху вниз, слева направо:

import numpy as np
from matplotlib import animation
from matplotlib import pyplot as plt

def init_world():
    test_world = [[0, 1, 0, 0],
                  [0, 0, 1, 0],
                  [0, 1, 0, 0],
                  [0, 0, 0, 0]]
    return test_world

def get_neighbours(arr, r, c):  # row and column
    # gets list of the 8 neighbours' values
    up = (r - 1) % len(arr)
    down = (r + 1) % len(arr)
    left = (c - 1) % len(arr[0])
    right = (c + 1) % len(arr[0])
    neighbours = [arr[up][left],
                  arr[up][c],
                  arr[up][right],
                  arr[r][left],
                  arr[r][right],
                  arr[down][left],
                  arr[down][c],
                  arr[down][right]]
    return neighbours

fig = plt.figure()
ax = plt.axes()
grid, = ax.plot([])

def tick(arr):
    # tick should update the grid by 1 step
    updated_world = arr
    for row in range(len(arr)):  # move down rows
        for col in range(len(arr[0])):  # move across columns
            neighbours = get_neighbours(arr, row, col)
            # if live and (<2 nbrs | >3 nbrs), die
            #  dead and 3 nbrs, live
            if arr[row][col] == 1 and (sum(neighbours) < 2 or sum(neighbours) > 3):
                updated_world[row][col] = 0
            elif arr[row][col] == 0 and sum(neighbours) == 3:
                updated_world[row][col] = 1
            else:
                pass
    return updated_world

def animate(arr):
    # update the world, and make this into a new graph
    arr = tick(arr)
    grid.set_data(arr)
    return grid

world = init_world()
fig = plt.figure()
plt.axis('off')
game = animation.FuncAnimation(fig, animate)
plt.show()

Полное сообщение об ошибке показано ниже.Почему-то tick не поставляется с массивом, и я не уверен, как это исправить.Буду признателен за любую помощь.

Traceback (most recent call last):
  File "C:\Miniconda3\lib\site-packages\matplotlib\cbook\__init__.py", line 389, in process
    proxy(*args, **kwargs)
  File "C:\Miniconda3\lib\site-packages\matplotlib\cbook\__init__.py", line 227, in __call__
    return mtd(*args, **kwargs)
  File "C:\Miniconda3\lib\site-packages\matplotlib\animation.py", line 1081, in _start
    self._init_draw()
  File "C:\Miniconda3\lib\site-packages\matplotlib\animation.py", line 1792, in _init_draw
    self._draw_frame(next(self.new_frame_seq()))
  File "C:\Miniconda3\lib\site-packages\matplotlib\animation.py", line 1814, in _draw_frame
    self._drawn_artists = self._func(framedata, *self._args)
  File "C:/Users/ocean/PycharmProjects/untitled1/animate.py", line 54, in animate
    arr = tick(arr)
  File "C:/Users/ocean/PycharmProjects/untitled1/animate.py", line 40, in tick
    for row in range(len(arr)):  # move down rows
TypeError: object of type 'int' has no len()

1 Ответ

0 голосов
/ 18 мая 2018

Из документации для matplotlib.animation.FuncAnimation, похоже, ваша функция animate действительно будет вызываться с одним целым числом за один раз, сначала с 0, затем с 1 и так далее. Если хотите, вы можете установить аргумент frames для передачи каких-либо массивов.

...