#include <FastLED.h>
#define WIDTH 16 //Ширина матрицы
#define HEIGHT 16 //Высота матрицы
#define LED_PIN 13 //Пин подключения матрицы на ардуино
#define BUTTON_PIN 2 //Пин подключения кнопки на ардуино
#define NUM_LEDS (WIDTH * HEIGHT) //Общее количество светодиодов
#define BRIGHTNESS 255 //Яркость (0-255)
#define INTENSITY 3 //Интенсивность для 2 режима
int MODE = 1; //1 - автосброс, 2 - бесконечный
CRGB leds[NUM_LEDS]; //Массив для светодиодов
char board[WIDTH][HEIGHT] = {0}; //Инициализация игрового поля
unsigned long hash1 = 0; //Хеш-сумма прошлой итерации
unsigned long hash2 = 0; //Хеш-сумма позапрошлой итерации
unsigned long hash3 = 0; //Хеш-сумма позапозапрошлой итерации
bool flagButton = false;
void SetRandValues() { //Обновление поля
for (char i = 0; i < WIDTH; i++) {
for (char j = 0; j < HEIGHT; j++) {
board[i][j] = 0;
}
}
int count = random(NUM_LEDS / 1.3);
for (int i = 0; i < count; i++) {
board[random(WIDTH)][random(HEIGHT)] = 2;
}
}
void setup() {
FastLED.addLeds<WS2811, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
pinMode(BUTTON_PIN, INPUT_PULLUP);
Serial.begin(9600);
randomSeed(analogRead(0));
if (MODE == 1)
SetRandValues();
else if (MODE == 2)
NewPixels();
}
int liveNeighbors(char row, char col) { //Функция для подсчёта живых соседей
char lives = 0;
for (char i = -1; i <= 1; i++) {
for (char j = -1; j <= 1; j++) {
char r = row + i;
char c = col + j;
if ((r >= 0 && r < WIDTH) && (c >= 0 && c < HEIGHT) && (board[r][c] == 2)) {
lives++;
}
}
}
if (board[row][col] == 2)
lives -= 1;
return lives; //Исключение самой клетки
}
void NextStep() { //Функция обновления состояния доски
char tempBoard[WIDTH][HEIGHT] = {0};
for (char i = 0; i < WIDTH; i++) {
for (char j = 0; j < HEIGHT; j++) {
char neighbors = liveNeighbors(i, j);
if (board[i][j] == 0 && neighbors == 2) {
tempBoard[i][j] = 2;
}
else if (board[i][j] == 2) {
tempBoard[i][j] = 1;
}
else if (board[i][j] == 1) {
tempBoard[i][j] = 0;
}
}
}
for (char i = 0; i < WIDTH; i++) { //Копирование временного массива в основной
for (char j = 0; j < HEIGHT; j++) {
board[i][j] = tempBoard[i][j];
}
}
}
int XY(char x, char y) { //Функция преобразования координат
return (y * WIDTH + x);
}
void CheckingHash() { //Сравнение с предыдущими состояниями
unsigned long hash = 0;
for (int i = 0; i < WIDTH; i++) {
for (int j = 0; j < HEIGHT; j++) {
hash = hash * 31 + board[i][j];
}
}
if (hash == hash1 || hash == hash2 || hash == hash3)
SetRandValues(); //Если игра завершена
else {
hash3 = hash2;
hash2 = hash1;
hash1 = hash;
}
}
void NewPixels() { //Добавление пикселей
bool flag = false;
for (int i = 0; i < WIDTH; i++) {
for (int j = 0; j < HEIGHT; j++) {
if (board[i][j] == 2)
flag = true;
}
}
if (flag == false) { //Если игра завершена
char var = random(4);
char shift = random(-6, 7);
if (var == 0){
board[8 + shift][8 + shift] = 2;
board[8 + 1 + shift][8 + shift] = 2;
board[8 + shift][8 + 1 + shift] = 2;
board[8 + 1 + shift][8 + 1 + shift] = 2;
}
else if (var == 2){
board[8 + shift][8 + shift] = 2;
board[8 + 1 + shift][8 + shift] = 2;
board[8 + 2 + shift][8 + shift] = 2;
board[8 - 1 + shift][8 + shift] = 2;
}
else if (var == 2){
board[8 + shift][8 + shift] = 2;
board[8 + shift][8 + 1 + shift] = 2;
board[8 + shift][8 + 2 + shift] = 2;
board[8 + shift][8 - 1 + shift] = 2;
}
}
else{
for (char i = 0; i < INTENSITY; i++)
board[random(WIDTH)][random(HEIGHT)] = 2;
}
}
void SetNextMode() { //Смена режима
for (int i = 0; i < WIDTH; i++) {
for (int j = 0; j < HEIGHT; j++) {
board[i][j] = 0;
}
}
if (MODE == 1)
MODE = 2;
else if (MODE == 2)
MODE = 1;
}
void loop() {
if (digitalRead(BUTTON_PIN) == LOW && flagButton == false){
flagButton = true;
SetNextMode();
}
if (digitalRead(BUTTON_PIN) != LOW && flagButton == true){
flagButton = false;
}
for (char i = 0; i < WIDTH; i++) { //Отображение текущего состояния на матрице
for (char j = 0; j < HEIGHT; j++) {
if (board[i][j] == 0) { //Выключение светодиода
leds[XY(i, j)] = CRGB(0, 0, 0);
}
else if (board[i][j] == 1) { //Синий цвет для отмирающих клеток
leds[XY(i, j)] = CRGB(0, 0, 255);
}
else if (board[i][j] == 2) { //Белый цвет для живых клеток
leds[XY(i, j)] = CRGB(255, 255, 255);
}
}
}
if (MODE == 1)
CheckingHash();
else if (MODE == 2)
NewPixels();
FastLED.show();
delay(100);
NextStep(); //Переход к следующему поколению
}