Краткое обновление: все еще работаю над этим проектом! Я столкнулся с серьезным препятствием с повторным рендерингом. Вещи начинают отставать, когда я запускаю около 150 компонентов, при этом 0,33–0,75 компонентов обновляются каждые 500 мс; Я прекрасно понимаю, что React — это не инструмент, предназначенный для создания игр. При этом я все еще исследую React, потому что есть несколько других функций, которые я хочу изучить, и которые, я думаю, будут полезны для моего набора инструментов независимо от окончательного результата игры.

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

Теперь к сегодняшней теме:

Манипуляции с массивами!

Цель состоит в том, чтобы превратить это:

В:

Это космический корабль. Известная конфигурация игры жизни Конвея, которая всегда действует одинаково. Я знал, что в конечном итоге я хотел бы позволить пользователю выбирать одну из них без необходимости вручную считать каждую ячейку, пропускать несколько и портить игровой процесс. Итак, с помощью Life Lexicon я смог собрать некоторые базовые конфигурации и преобразовать их в бинарные массивы для использования в своем приложении.

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

  1. Данные, которые представляют, какие ячейки конфигурации активны/мертвы.
  2. Количество индексов, составляющих одну строку конфигурации. Из необработанного массива вверху вы заметите, что нет разделителя, за которым нужно следовать. Я хватаю их, когда соскребаю их из Лексикона.
  3. Размер игрового поля, на которое в данный момент смотрит пользователь.

Я предлагаю пользователю только те конфигурации, которые соответствуют его текущему игровому полю. Это избавляет от необходимости управлять ими, пытаясь сыграть что-то большее, чем то, что доступно. Итак, зная это, я знаю, что до тех пор, пока длина строки для каждой конфигурации меньше, чем длина строки игрового поля, мы в деле.

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

Затем вам нужно решить, где на игровом поле должны быть расположены эти клетки. Я выбрал с серединой или для массивов, которые не состоят из нечетных строк, немного правее/ниже середины. Как только вы в целом узнаете, где что должно располагаться, вы можете приступить к созданию новых массивов (никогда не мутируя!). Я сохраняю верхнее/нижнее и левое/правое заполнение как пары массивов, то есть [0, 1], где справа от массива должна быть добавлена ​​дополнительная ячейка, а слева ничего.

Функция findPadding() выделена как отдельная логика, поскольку технически она может использоваться для обоих сценариев, где исходный стекированный массив необходимо растянуть шире или выше.

Это подводит нас к проблеме определения длины массива. Я решил обработать это аналогично тому, как я нахожу отступы строк. Я использую общую длину массива и длину строк конфигурации, чтобы собрать это. Я мог бы также использовать длину массива массивов, но это кажется несоответствующим.

Итак, этот B29 с длиной строки 17 выглядит так, прежде чем он будет помещен в нашу квадратную сетку:

Допустим, пользователь в данный момент смотрит на сетку 21 x 21. Мы можем ожидать некоторые дополнения, которые необходимо сделать.

Заполнить строки не так уж сложно с помощью оператора распространения:

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

Самое сложное здесь не в том, чтобы свести массив к сглаженному массиву. На самом деле это была попытка создать несколько массивов нулей, [0, 0, 0, 0], не более чем целое число.

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

Array(4).fill([]);
// returns
[[], [], [], []]

Затем мы можем сопоставить их и заменить пустой массив заполненным массивом.

Array(4).fill([]).map(() => Array(2).fill(0)); 
// returns 
[[0,0], [0, 0], [0,0],[0,0]]

И — поскольку мы возвращаем только копии в каждом экземпляре, наш исходный массив никогда не испортится!