Пытаюсь создать игру, используя Arduino Nano и светодиодную матрицу 24x8. Когда я пытаюсь увеличить область, пишет, что недостаточно памяти. Что сделать?

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

>
#include <LedControl.h>

#include "LedControl.h"

// "ДИН" данные в контакте
#define DIN_PIN 12
// "CLK" контакт для часов
#define CLK_PIN 11
// "КС" приколоть
#define CS_PIN 10
// размеры сетки. не должен быть больше 8x8
#define MAX_Y 8
#define MAX_X 24
// сколько пользовательских шаблонов стартовой сетки
#define MAX_C 15
// время ожидания между ходами
#define TURN_DELAY 100
// сколько ходов за игру перед началом новой игры
// вы также можете использовать кнопку сброса на доске
#define TURNS_MAX 40
// сколько ходов ждать, если нет изменений, прежде чем начать новую игру
#define NO_CHANGES_RESET 4

int TURNS = 0;       // счетчик ходов
int NO_CHANGES = 0;  // счетчик ходов без изменений

// состояние игры. 0 — мертвая клетка, 1 — живая клетка
boolean grid[MAX_Y][MAX_X] = {
  {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
};

// пользовательские начальные шаблоны сетки
boolean cgrids[MAX_C][MAX_Y][MAX_X] = {
  {
    {1, 1, 0, 0, 1, 1, 0, 0},
    {1, 1, 0, 0, 1, 1, 0, 0},
    {0, 0, 0, 0, 0, 0, 1, 1},
    {0, 0, 0, 0, 0, 0, 1, 1},
    {1, 1, 0, 0, 0, 0, 0, 0},
    {1, 1, 0, 0, 0, 0, 0, 0},
    {0, 0, 1, 1, 0, 0, 1, 1},
    {0, 0, 1, 1, 0, 0, 1, 1},
  },
  {
    {1, 0, 1, 0, 0, 0, 1, 0},
    {0, 1, 1, 0, 0, 0, 1, 0},
    {0, 1, 0, 0, 0, 0, 1, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 1, 0, 0, 0, 0, 1, 0},
    {0, 1, 0, 0, 0, 1, 1, 0},
    {0, 1, 0, 0, 0, 1, 0, 1},
  },
  {
    {1, 0, 1, 0, 0, 0, 0, 0},
    {0, 1, 1, 0, 0, 0, 0, 0},
    {0, 1, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 1, 0, 0, 0, 0, 0, 0},
    {0, 1, 1, 0, 0, 0, 0, 0},
    {1, 0, 1, 0, 0, 0, 0, 0},
  },
  {
    {1, 0, 1, 0, 0, 1, 0, 1},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 1, 0, 0, 0, 0, 1, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
  },
  {
    {1, 0, 1, 0, 0, 0, 0, 0},
    {0, 1, 1, 0, 0, 0, 0, 0},
    {0, 1, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
  },
  {
    {0, 1, 0, 0, 0, 0, 0, 0},
    {0, 1, 0, 0, 0, 1, 1, 1},
    {0, 1, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 1, 0},
    {1, 1, 1, 0, 0, 0, 1, 0},
    {0, 0, 0, 0, 0, 0, 1, 0},
  },
  {
    // https://conwaylife.com/wiki/Mold
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 1, 1, 0, 0},
    {0, 0, 0, 1, 0, 0, 1, 0},
    {0, 0, 1, 0, 1, 0, 1, 0},
    {0, 0, 1, 0, 0, 1, 0, 0},
    {0, 1, 0, 0, 0, 0, 0, 0},
    {0, 0, 1, 0, 1, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
  },
  {
    // https://conwaylife.com/wiki/Octagon_2
    {0, 0, 0, 1, 1, 0, 0, 0},
    {0, 0, 1, 0, 0, 1, 0, 0},
    {0, 1, 0, 0, 0, 0, 1, 0},
    {1, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 0, 0, 0, 0, 0, 1},
    {0, 1, 0, 0, 0, 0, 1, 0},
    {0, 0, 1, 0, 0, 1, 0, 0},
    {0, 0, 0, 1, 1, 0, 0, 0},
  },
  {
    {1, 0, 1, 0, 0, 1, 0, 1},
    {1, 1, 0, 0, 0, 0, 1, 0},
    {1, 0, 0, 1, 1, 1, 0, 1},
    {0, 0, 1, 1, 0, 1, 0, 0},
    {1, 0, 0, 0, 1, 1, 0, 0},
    {1, 0, 0, 0, 1, 0, 0, 1},
    {0, 0, 0, 0, 0, 0, 1, 0},
    {1, 0, 1, 1, 0, 1, 1, 1},
  },
  {
    {1, 1, 1, 1, 1, 1, 1, 1},
    {1, 1, 0, 0, 0, 0, 1, 1},
    {1, 0, 0, 1, 1, 1, 0, 1},
    {1, 0, 1, 1, 0, 1, 0, 1},
    {1, 0, 1, 0, 1, 1, 0, 1},
    {1, 0, 1, 1, 1, 0, 0, 1},
    {1, 1, 0, 0, 0, 0, 0, 1},
    {1, 1, 1, 1, 1, 1, 1, 1},
  },
  {
    {1, 1, 1, 1, 1, 1, 1, 1},
    {1, 0, 0, 0, 0, 0, 1, 1},
    {1, 0, 0, 1, 1, 1, 0, 1},
    {1, 0, 1, 1, 0, 1, 0, 1},
    {1, 0, 1, 0, 1, 1, 0, 1},
    {1, 0, 1, 1, 1, 0, 0, 1},
    {1, 0, 0, 0, 0, 0, 0, 1},
    {1, 1, 1, 1, 1, 1, 1, 1},
  },
  {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 1, 0, 0, 0, 0, 0},
    {0, 0, 1, 0, 0, 0, 0, 0},
    {0, 1, 1, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {1, 1, 0, 0, 1, 1, 1, 0},
    {1, 0, 1, 0, 1, 0, 0, 0},
    {0, 1, 1, 0, 0, 0, 0, 0},
  },
  {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 1, 0, 0, 0, 0},
    {0, 0, 1, 1, 0, 0, 0, 0},
    {0, 1, 0, 0, 0, 0, 0, 0},
    {0, 0, 1, 1, 0, 0, 0, 0},
    {0, 0, 0, 1, 0, 0, 0, 0},
  },
  {
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 1, 1, 0, 0, 1, 1, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0},
  },
  {
    {1, 0, 0, 0, 0, 1, 0, 0},
    {0, 1, 0, 0, 0, 0, 1, 0},
    {0, 0, 1, 0, 0, 1, 0, 1},
    {0, 0, 0, 1, 0, 0, 0, 0},
    {0, 0, 0, 0, 1, 0, 0, 0},
    {1, 0, 1, 0, 0, 1, 0, 0},
    {0, 1, 0, 0, 0, 0, 1, 0},
    {0, 0, 1, 0, 0, 0, 0, 1},
  },
};

LedControl lc = LedControl(DIN_PIN, CS_PIN, CLK_PIN, 1);

void setup() {
  // случайное начальное значение из неиспользуемого аналогового контакта
  randomSeed(analogRead(0));

  // инициализируем светодиодную матрицу
  lc.shutdown(0, false);
  lc.setIntensity(0, 0);
  lc.clearDisplay(0);

  reset_grid();
  display_grid();

  // Serial.begin(9600);
  // debug_grid();
}

void loop() {
  delay(TURN_DELAY);

  play_gol();

  TURNS++;

  // сбрасываем сетку, если в последнее время не было изменений
  // когда игра переходит в статическое стабильное состояние
  if (NO_CHANGES > NO_CHANGES_RESET) {
    reset_grid();
  }
  // сбрасываем сетку, если цикл выполняется долгое время
  // для случаев, когда игра циклически переключается между несколькими стабильными состояниями
  if (TURNS > TURNS_MAX) {
    reset_grid();
  }

  display_grid();
}

// играем в игру жизни
void play_gol() {
  /*
    1. Any live cell with fewer than two neighbours dies, as if by loneliness.
    2. Any live cell with more than three neighbours dies, as if by
    overcrowding.
    3. Any live cell with two or three neighbours lives, unchanged, to the next
    generation.
    4. Any dead cell with exactly three neighbours comes to life.
  */

  boolean new_grid[MAX_Y][MAX_X] = {
    {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
  };

  for (int y = 0; y < 8; y++) {
    for (int x = 0; x < 8; x++) {
      int neighboughs = count_neighboughs(y, x);
      if (grid[y][x] == 1) {
        if ((neighboughs == 2) || (neighboughs == 3)) {
          new_grid[y][x] = 1;
        } else {
          new_grid[y][x] = 0;
        }
      } else {
        if (neighboughs == 3) {
          new_grid[y][x] = 1;
        } else {
          new_grid[y][x] = 0;
        }
      }
    }
  }

  // обновляем текущую сетку из новой и подсчитываем количество изменений
  // произошло
  int changes = 0;
  for (int y = 0; y < MAX_Y; y++) {
    for (int x = 0; x < MAX_X; x++) {
      if (new_grid[y][x] != grid[y][x]) {
        changes++;
      }
      grid[y][x] = new_grid[y][x];
    }
  }

  // обновляем глобальный счетчик, если изменений не произошло
  if (changes == 0) {
    NO_CHANGES++;
  }
}

// подсчитываем количество соседних живых ячеек для данной ячейки
int count_neighboughs(int y, int x) {
  int count = 0;

  // -- Строка над нами ---
  if (y > 0) {
    // вверху слева
    if (x > 0) {
      count += grid[y - 1][x - 1];
    }
    // выше
    count += grid[y - 1][x];
    // вверху справа
    if ((x + 1) < 8) {
      count += grid[y - 1][x + 1];
    }
  }

  // -- Та же строка -------
  // левый
  if (x > 0) {
    count += grid[y][x - 1];
  }
  // верно
  if ((x + 1) < 8) {
    count += grid[y][x + 1];
  }

  // -- Строка под нами ---
  if ((y + 1) < 8) {
    // внизу слева
    if (x > 0) {
      count += grid[y + 1][x - 1];
    }
    // ниже
    count += grid[y + 1][x];
    // внизу справа
    if ((x + 1) < 8) {
      count += grid[y + 1][x + 1];
    }
  }

  return count;
}

// сбрасываем сетку
void reset_grid() {
  NO_CHANGES = 0;
  TURNS = 0;

  int grid_type = random(0, 4);
  int custom_grid_choice = random(0, MAX_C - 1);

  for (int y = 0; y < MAX_Y; y++) {
    for (int x = 0; x < MAX_X; x++) {
      if (grid_type == 0) {
        // используем собственный шаблон начальной сетки
        grid[y][x] = cgrids[custom_grid_choice][y][x];
      } else {
        // создаем случайный начальный шаблон сетки
        if (random(0, MAX_X) <= 1) {
          grid[y][x] = 1;
        }
      }
    }
  }
}

// отображаем текущую сетку на светодиодной матрице
void display_grid() {
  for (int y = 0; y < MAX_Y; y++) {
    for (int x = 0; x < MAX_X; x++) {
      lc.setLed(0, y, x, grid[y][x]);
    }
  }
}

/*
  // сбрасываем состояние текущей сетки на последовательное соединение
  void debug_grid() {
  for (int y = 0; y < MAX_Y; y++) {
    Serial.print("y(");
    Serial.print(y);
    Serial.print("): ");

    for (int x = 0; x < MAX_X; x++) {
      Serial.print(grid[y][x]);
      Serial.print(", ");
    }

    Serial.println("");
  }
  Serial.println("");
  }
*/

, 👍2


2 ответа


4

Очевидным «легко висящим плодом» оптимизации памяти является cgrids. Это массив из 8×24×15 = 2880 логических значений, которые вы никогда не изменить. Сделав его const и сохранив его в PROGMEM, вам следует сэкономьте столько байтов ОЗУ.

Изменить: Augustus73 спросил

И как мне это сделать?

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

PROGMEM const boolean cgrids[MAX_C][MAX_Y][MAX_X] = { ... };

Затем вам придется использовать один из макросов pgm_read_*(), если вы хотите получить данные, например:

grid[y][x] = pgm_read_byte(&cgrids[custom_grid_choice][y][x]);
,

И как мне это сделать, я не очень силен в программировании?, @Augustus73

@ Augustus73 Augustus73: см. исправленный ответ., @Edgar Bonet

Вы уверены, что ваш код работает правильно, когда MAX_X равен 8? Я попробовал, и у меня просто странное мерцание., @Nick Gammon

@NickGammon: Поскольку у меня нет под рукой светодиодной матрицы, я эмулировал ее с помощью последовательного терминала. У меня программа работает как положено и в 8х8, и в 8х24., @Edgar Bonet

Хммм, я пытался проверить его код. :) Со светодиодами., @Nick Gammon


0

Использование байта на бит в массиве неэффективно.

Я переработал код, чтобы использовать бит для каждого элемента массива, а именно:

#include <LedControl.h>


// "ДИН" данные в контакте
#define DIN_PIN 12
// "CLK" контакт для часов
#define CLK_PIN 11
// "КС" приколоть
#define CS_PIN 10
// размеры сетки. не должен быть больше 8x8
#define MAX_Y 8
#define MAX_X 24
// сколько пользовательских шаблонов стартовой сетки
#define MAX_C 15
// время ожидания между ходами
#define TURN_DELAY 1000
// сколько ходов за игру перед началом новой игры
// вы также можете использовать кнопку сброса на доске
#define TURNS_MAX 40
// сколько ходов ждать, если нет изменений, прежде чем начать новую игру
#define NO_CHANGES_RESET 4

int TURNS = 0;       // счетчик ходов
int NO_CHANGES = 0;  // счетчик ходов без изменений

// состояние игры. 0 — мертвая клетка, 1 — живая клетка

unsigned long grid[MAX_Y]; // Каждый беззнаковый длинный может содержать 32 бита

// Добавил Ник Гаммон
void setBit (unsigned long *whichGrid, const unsigned char y, const unsigned char x, const bool value)
  {
  if (value)
    whichGrid[y] |= (1U << x);
  else
    whichGrid[y] &= ~(1U << x);
  } // конец setBit

bool getBit (unsigned long *whichGrid, const unsigned char y, const unsigned char x)
  {
  return whichGrid[y] & (1U << x);
  } // конец testBit
  
    
// пользовательские начальные шаблоны сетки
unsigned long cgrids[MAX_C][MAX_Y] = {
  {
    0b11001100,
    0b11001100,
    0b00000011,
    0b00000011,
    0b11000000,
    0b11000000,
    0b00110011,
    0b00110011,
  },
  {
    0b10100010,
    0b01100010,
    0b01000010,
    0b00000000,
    0b00000000,
    0b01000010,
    0b01000110,
    0b01000101,
  },

  {
    0b10100000,
    0b01100000,
    0b01000000,
    0b00000000,
    0b00000000,
    0b01000000,
    0b01100000,
    0b10100000,
  },
  {
    0b10100101,
    0b01100110,
    0b01000010,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
  },
  {
    0b10100000,
    0b01100000,
    0b01000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
  },
  {
    0b01000000,
    0b01000111,
    0b01000000,
    0b00000000,
    0b00000000,
    0b00000010,
    0b11100010,
    0b00000010,
  },
  {
    // https://conwaylife.com/wiki/Mold
    0b00000000,
    0b00001100,
    0b00010010,
    0b00101010,
    0b00100100,
    0b01000000,
    0b00101000,
    0b00000000,
  },
  {
    // https://conwaylife.com/wiki/Octagon_2
    0b00011000,
    0b00100100,
    0b01000010,
    0b10000001,
    0b10000001,
    0b01000010,
    0b00100100,
    0b00011000,
  },
  {
    0b10100101,
    0b11000010,
    0b10011101,
    0b00110100,
    0b10001100,
    0b10001001,
    0b00000010,
    0b10110111,
  },
  {
    0b11111111,
    0b11000011,
    0b10011101,
    0b10110101,
    0b10101101,
    0b10111001,
    0b11000001,
    0b11111111,
  },
  {
    0b11111111,
    0b10000011,
    0b10011101,
    0b10110101,
    0b10101101,
    0b10111001,
    0b10000001,
    0b11111111,
  },
  {
    0b00000000,
    0b00100000,
    0b00100000,
    0b01100000,
    0b00000000,
    0b11001110,
    0b10101000,
    0b01100000,
  },
  {
    0b00000000,
    0b00000000,
    0b00000000,
    0b00010000,
    0b00110000,
    0b01000000,
    0b00110000,
    0b00010000,
  },
  {
    0b00000000,
    0b00000000,
    0b01100110,
    0b01100110,
    0b01100110,
    0b01100110,
    0b00000000,
    0b00000000,
  },
  {
    0b10000100,
    0b01000010,
    0b00100101,
    0b00010000,
    0b00001000,
    0b10100100,
    0b01000010,
    0b00100001,
  },
 
};


LedControl lc = LedControl(DIN_PIN, CS_PIN, CLK_PIN, 1);

void setup() {
  // случайное начальное значение из неиспользуемого аналогового контакта
  randomSeed(analogRead(0));

  // инициализируем светодиодную матрицу
  lc.shutdown(0, false);
  lc.setIntensity(0, 0);
  lc.clearDisplay(0);

  reset_grid();
  display_grid();

  Serial.begin(115200);
  debug_grid();
}

void loop() {
  delay(TURN_DELAY);

  play_gol();

  TURNS++;

  // сбрасываем сетку, если в последнее время не было изменений
  // когда игра переходит в статическое стабильное состояние
  if (NO_CHANGES > NO_CHANGES_RESET) {
    reset_grid();
  }
  // сбрасываем сетку, если цикл выполняется долгое время
  // для случаев, когда игра циклически переключается между несколькими стабильными состояниями
  if (TURNS > TURNS_MAX) {
    reset_grid();
  }

  display_grid();
}

// играем в игру жизни
void play_gol() {
  /*
    1. Any live cell with fewer than two neighbours dies, as if by loneliness.
    2. Any live cell with more than three neighbours dies, as if by
    overcrowding.
    3. Any live cell with two or three neighbours lives, unchanged, to the next
    generation.
    4. Any dead cell with exactly three neighbours comes to life.
  */

  unsigned long new_grid[MAX_Y]; // Каждый беззнаковый длинный может содержать 32 бита

  for (int y = 0; y < MAX_Y; y++) {
    for (int x = 0; x < MAX_X; x++) {
      int neighboughs = count_neighboughs(y, x);
      if (getBit (grid, y, x)) {
        if ((neighboughs == 2) || (neighboughs == 3)) {
          setBit (new_grid, y, x, 1);
        } else {
          setBit (new_grid, y, x, 0);
        }
      } else {
        if (neighboughs == 3) {
          setBit (new_grid, y, x, 1);
        } else {
          setBit (new_grid, y, x, 0);
        }
      }
    }
  }

  // обновляем текущую сетку из новой и подсчитываем количество изменений
  // произошло
  int changes = 0;
  for (int y = 0; y < MAX_Y; y++) {
    for (int x = 0; x < MAX_X; x++) {
      if (getBit (new_grid, y, x) != getBit (grid, y, x)) {
        changes++;
      }
      setBit (grid, y, x, getBit (new_grid, y, x));
    }
  }

  // обновляем глобальный счетчик, если изменений не произошло
  if (changes == 0) {
    NO_CHANGES++;
  }
}

// подсчитываем количество соседних живых ячеек для данной ячейки
int count_neighboughs(int y, int x) {
  int count = 0;

  // -- Строка над нами ---
  if (y > 0) {
    // вверху слева
    if (x > 0) {
      count += getBit (grid, y - 1, x - 1);
    }
    // выше
    count += getBit (grid, y - 1, x);
    // вверху справа
    if ((x + 1) < MAX_X) {
      count += getBit (grid, y - 1, x + 1);
    }
  }

  // -- Та же строка -------
  // левый
  if (x > 0) {
    count += getBit (grid, y, x - 1);
  }
  // верно
  if ((x + 1) < MAX_X) {
    count += getBit (grid, y, x + 1);
  }

  // -- Строка под нами ---
  if ((y + 1) < MAX_Y) {
    // внизу слева
    if (x > 0) {
      count += getBit (grid, y + 1, x - 1);
    }
    // ниже
    count += getBit (grid, y + 1, x);
    // внизу справа
    if ((x + 1) < MAX_X) {
      count += getBit (grid, y + 1, x + 1);
    }
  }

  return count;
}

// сбрасываем сетку
void reset_grid() {
  NO_CHANGES = 0;
  TURNS = 0;

  Serial.println("Resetting the grid");

  int grid_type = random(0, 4);
  int custom_grid_choice = random(0, MAX_C - 1);

  for (int y = 0; y < MAX_Y; y++) {
    for (int x = 0; x < MAX_X; x++) {
      if (grid_type == 0) {
        // используем собственный шаблон начальной сетки
        setBit (grid, y, x, getBit (cgrids[custom_grid_choice], y, x));
      } else {
        // создаем случайный начальный шаблон сетки
        if (random(0, MAX_X) <= 1) {
          setBit (grid, y, x, 1);
        }
      }
    }
  }
}

// отображаем текущую сетку на светодиодной матрице
void display_grid() {
  for (int y = 0; y < MAX_Y; y++) {
    for (int x = 0; x < MAX_X; x++) {
      lc.setLed(0, y, x, getBit (grid, y, x));
    }
  }
  debug_grid ();
}
    
// сбрасываем состояние текущей сетки на последовательное соединение
void debug_grid() {
  Serial.print ("      ");
  for (int x = 0; x < MAX_X; x++)
     Serial.print (".");
  Serial.println ();
  

  for (int y = 0; y < MAX_Y; y++) {
    Serial.print("y(");
    Serial.print(y);
    Serial.print("): ");

    for (int x = 0; x < MAX_X; x++) {
      if (getBit (grid, y, x))
        Serial.print ("*");
      else
        Serial.print (" ");
    }

    Serial.println("");
  }
  Serial.println("");
  }

Обратите внимание, в частности, на функции setBit и getBit, которые предназначены для проверки, установки или очистки определенного бита, как это указано в вашей более ранней реализации однобайтовых массивов.

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

// Добавил Ник Гаммон
void setBit (unsigned long *whichGrid, const unsigned char y, const unsigned char x, const bool value)
  {
  if (value)
    whichGrid[y] |= (1U << x);
  else
    whichGrid[y] &= ~(1U << x);
  } // конец setBit

bool getBit (unsigned long *whichGrid, const unsigned char y, const unsigned char x)
  {
  return whichGrid[y] & (1U << x);
  } // конец testBit
  

Я также исправил несколько ошибок в вашем коде, где вы тестировали X или Y, достигающие 8, а не MAX_X или MAX_Y, которые работали бы, когда MAX_X и MAX_Y были 8, но не если бы вы увеличили их.

Эта версия использует намного меньше памяти:

Sketch uses 4876 bytes (15%) of program storage space. Maximum is 32256 bytes.

Я немного переработал ваш дисплей отладки, так как светодиоды у меня не работали. Пример вывода:

      ........................
y(0):           ****          
y(1):   **        * *         
y(2):   **     ** * **        
y(3):          *  * *         
y(4):             *           
y(5):                         
y(6):                         
y(7):                         

      ........................
y(0):            ***          
y(1):   **     *    **        
y(2):   **     ** * **        
y(3):          ** * **        
y(4):              *          
y(5):                         
y(6):                         
y(7):                         

      ........................
y(0):             ***         
y(1):   **     *     *        
y(2):   **    *               
y(3):          ** *  *        
y(4):              **         
y(5):                         
y(6):                         
y(7):                         

      ........................
y(0):              **         
y(1):   **         **         
y(2):   **    * *             
y(3):          *   **         
y(4):              **         
y(5):                         
y(6):                         
y(7):                         

Ради интереса я сделал Game of Life в 2011 году для щита «Много светодиодов». Это забавный проект.

Изменить - честно говоря, я думаю, что код на самом деле был написан автором щита: «Создано Джимми Роджерсом 30 декабря 2009 г.».

Однако я помню, как много лет назад писал Game of Life для Apple II. Исходный код для этого давно исчез. :)

Игра жизни

,