Эксперимент с клеточными автоматами

В этом руководстве вы узнаете, как создать очень простую симуляцию в Python. Вместе мы создадим мир крошечных квадратов, танцующих в ритме пульса нашей программы.

Это будет упражнение в клеточных автоматах, области вычислительной науки со многими приложениями. Наши цели будут простыми и двоякими: искусство и образование. Мы будем использовать библиотеку Pygame, чтобы визуализировать симуляцию.

Используя подробные пояснения и множество примеров кода, мы рассмотрим все шаги, необходимые для создания симуляции на Python. И наша окончательная программа будет состоять менее чем из 100 строк кода!

Краткий обзор клеточных автоматов

Прежде чем начать, нам нужно представить инструменты, которые мы будем использовать для моделирования нашего крошечного мира. Надеюсь, вы уже знаете о Python. Мы также будем использовать Cellular Automata. Этот теоретический инструмент полезен для моделирования нашего мира.

С помощью Cellular Automata мы создаем сетку ячеек, каждая из которых имеет определенное состояние. С каждым тактом моделирующих часов к каждой ячейке сетки применяется набор правил. Мы называем это новым поколением.

С каждым поколением симуляция меняется. Изменяя правила этапа моделирования, автоматы можно использовать для достижения различных результатов.

Начало работы с Pygame

Pygame — это библиотека с открытым исходным кодом для создания мультимедийных программ на Python. Мы будем использовать его для создания графики для нашего смоделированного мира.

Самый простой способ установить Pygame — использовать pip из командной строки.

pip install pygame

Как только pip установит Pygame, мы сможем использовать его в нашем проекте с ключевым словом import.

import pygame

Настройка цикла моделирования

Установив Pygame, мы готовы написать код нашего игрового цикла. Игровой цикл повторяется вечно. Таким образом, наша симуляция будет продолжать работать до тех пор, пока мы не скомандуем ей завершиться. Для этого нам нужно использовать цикл while.

Условие окончания цикла будет, когда игрок нажмет кнопку выхода. С каждым тиком симуляции мы будем проверять, нажал ли игрок кнопку выхода или нет. Если они есть, мы закончим программу. В противном случае симуляция продолжится до следующего шага.

import pygame, random
from random import randrange, shuffle
pygame.init()
screen = pygame.display.set_mode([400,400])
clock = pygame.time.Clock()
cells = []
MAP_WIDTH = 20
MAP_HEIGHT = 20
size = 20
steps = 0

Установите частоту кадров

Мы можем установить частоту кадров Pygame так, чтобы симуляция проходила с заданными интервалами. Для этого нужно сделать два шага.

Сначала нам нужно захватить объект часов.

clock = pygame.time.Clock()

Когда у нас есть часы, мы можем установить любую частоту кадров в игре, какую захотим. Мы начнем с 3 кадров в секунду, что даст нам время для наблюдения за этапами моделирования. Используя метод часов tick(), мы установим частоту кадров часов. Это утверждение находится внутри нашего цикла while.

done = False
while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
    screen.fill((255,255,255))
    draw_map()
    do_step()
    pygame.display.flip()
    clock.tick(3)
    print("Steps: " + str(steps))
    steps+=1
pygame.quit()

Создание сотовых объектов

Чтобы создать наши ячейки, мы создадим новый класс Python. Этот класс будет хранить информацию о ячейках нашей сетки. Например, расположение каждой ячейки и является ли ячейка живой.

Сохраняя каждую ячейку как отдельный объект, мы можем отслеживать каждую ячейку в сетке. Для этого мы сохраним все ячейки в список Python.

size = 20
# the model for our cells
class Cell:
    def __init__(self,x,y,dead,value):
        self.x = x
        self.y = y
        self.dead = dead
        self.value = value

Настройка среды моделирования

Далее мы настроим среду моделирования. Мы сделаем это, сначала определив ширину и высоту нашей карты. Мы определим эти размеры с точки зрения количества ячеек. В этом примере мы будем использовать карту шириной 20 ячеек и высотой 20 ячеек, всего 400 ячеек.

MAP_WIDTH = 20
MAP_HEIGHT = 20
steps = 0

Инициализация карты

Определив размеры карты, мы можем создать наши ячейки. Используя вложенный цикл for, наша программа создаст новую ячейку для каждой позиции на карте. Каждая ячейка получает случайно сгенерированные данные для начала. Для этого нам понадобится помощь метода randrange().

# initialize the simulation map
def init_map():
    for y in range(MAP_HEIGHT):
        for x in range(MAP_WIDTH):
            dead  = True if randrange(10) > 3 else False
            power = randrange(1,255)
            cell = Cell(x,y,dead,power)
            cells.append(cell)

Рисование карты

После определения карты можно создать ее графическое представление с помощью библиотеки Pygame. Чтобы нарисовать карту, мы нарисуем прямоугольник для каждой ячейки сетки. Цвет ячейки будет зависеть от значения, которое было ей приписано случайным образом. размер ячейки был определен ранее, когда мы создавали наш объект ячейки.

# draw graphics for the map with Pygame
def draw_map():
    for cell in cells:
        color = (0, 0, cell.value)
        pygame.draw.rect(screen, color, pygame.Rect(cell.x*size, cell.y*size, size, size))

Кодирование шага моделирования

Прежде чем наша симуляция начнет танцевать, нам нужно создать цикл симуляции. Этот цикл будет отвечать за создание каждого нового поколения симуляции.

Во-первых, функция перемешивает ячейки. Во-вторых, проверяется каждая живая ячейка в сетке, и, если у ячейки есть соседи, мы меняем ячейки местами, создавая небольшой танец. Кадриль.

# do the next simulation step (generation)
def do_step():
    shuffle(cells)
    for cell in cells:
        if not cell.dead:
            neighbors = get_living_neighbors(cell)
            if len(neighbors) > 0:
                shuffle(neighbors)
                prey = neighbors[randrange(len(neighbors))]
                swap_cells(cell, prey)

Получение ячейки с карты

Шаг симуляции закодирован, но в нем отсутствуют некоторые функции. Прежде чем это заработает, нам нужно закодировать способ извлечения ячейки из сетки. Таким образом, мы можем найти соседей ячейки. Мы напишем небольшую вспомогательную функцию, чтобы сделать это возможным.

# get a cell from the grid
def get_cell(x,y):
    for cell in cells:
        if cell.x == x and cell.y == y:
            return cell

Поиск соседей ячейки

Поиск соседей ячейки является распространенной проблемой. Хотя есть много способов найти эти данные, мы воспользуемся вложенным циклом for. Этот код проверит соседей данной ячейки, сначала убедившись, что ячейка находится внутри границ сетки. Если это так, код проверяет, жива ли ячейка. Если клетка жива, она добавляется в список живых клеток.

# find the neighbors of a cell that are alive
def get_living_neighbors(cell):
    neighbors = []
    for y in range(-1,1):
        for x in range(-1,1):
            if cell.x + x < 0 or cell.x + x > MAP_WIDTH-1 or cell.y + y < 0 or cell.y + y > MAP_HEIGHT-1:
                pass
            else:
                neighbor_cell = get_cell(cell.x + x, cell.y + y)
                if not neighbor_cell.dead:
                    neighbors.append(neighbor_cell)
   return neighbors

Обмен ячейками

Чтобы заставить симуляцию танцевать, нужно поменять местами ячейки. Как и на настоящем танцполе, наши клетки будут двигаться и меняться местами. Замена ячеек — еще одна распространенная задача, которую легко выполнить с помощью переменной temp.

def swap_cells(cellA, cellB):
    tempX = cellB.x
    tempY = cellB.y
    cellB.x = cellA.x
    cellB.y = cellA.y
    cellA.x = tempX
    cellA.y = tempY

Запуск моделирования

Когда все части на месте, мы можем запустить код и увидеть, как наши квадраты танцуют на нашем экране.

# we start the program here
init_map()
done = False
while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
    screen.fill((255,255,255))
    draw_map()
    do_step()
    pygame.display.flip()
    clock.tick(3)
    print("Steps: " + str(steps))
    steps+=1
pygame.quit()

Похожие сообщения

Надеюсь, вам понравился этот урок по созданию симуляций в Python. Хотя результат был немного причудливым, применение нашей работы имеет далеко идущие последствия. Как геймдизайнерам, так и криптографам полезно знать Cellular Automata.

Если вам понравился этот пост и вы хотите узнать больше о компьютерном программировании и Python, перейдите по этим ссылкам для получения дополнительных руководств.