Processing:Примеры/Игра жизни Конвея: различия между версиями
Материал из Онлайн справочника
				
				
				Перейти к навигацииПерейти к поиску
				
				| Myagkij (обсуждение | вклад) | Нет описания правки | ||
| Строка 212: | Строка 212: | ||
| }} | }} | ||
| <syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS | <syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS"> | ||
| // размер клеток: | // размер клеток: | ||
| int cellSize = 5; | int cellSize = 5; | ||
Версия от 18:22, 14 мая 2023
| Содержание | Среда разработки Processing | Справочник языка Processing | Библиотеки | Примеры | Режимы программирования | 
Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.
|   | Черновик | 
Описание[1]
Нажмите на пробел, чтобы остановить клеточный автомат, или на кнопку мышки, чтобы изменить значения клеток. Во время паузы на клетки можно нажимать, активируя и деактивируя их. Нажмите на клавишу «R», чтобы случайно сбросить исходное расположение клеток. Нажмите на клавишу «C», чтобы очистить фоновую решетку.
Клеточный автомат «Игра жизни» был придуман Джоном Конвеем в 1970 году.
Пример
// размер клеток:
int cellSize = 5;
// насколько высока вероятность того,
// что клетка будет жива в начале игры (в процентах):
float probabilityOfAliveAtStart = 15;
// переменные для таймера:
int interval = 100;
int lastRecordedTime = 0;
// цвета для активных/неактивных клеток:
color alive = color(0, 200, 0);
color dead = color(0);
// массив клеток:
int[][] cells; 
// буфер для записи состояния клеток;
// он также будет использоваться
// для изменения других клеток во время взаимодействий:
int[][] cellsBuffer; 
// пауза:
boolean pause = false;
void setup() {
  size (640, 360);
  // инициализируем массивы: 
  cells = new int[width/cellSize][height/cellSize];
  cellsBuffer = new int[width/cellSize][height/cellSize];
  // строка для отрисовки фоновой клеточной решетки:
  stroke(48);
  noSmooth();
  // инициализируем клетки:
  for (int x=0; x<width/cellSize; x++) {
    for (int y=0; y<height/cellSize; y++) {
      float state = random (100);
      if (state > probabilityOfAliveAtStart) { 
        state = 0;
      }
      else {
        state = 1;
      }
      cells[x][y] = int(state); // сохраняем состояние каждой клетки
    }
  }
  background(0); // закрашиваем фон черным на случай,
                 // если клетки не заполнят все ячейки решетки
}
void draw() {
  // рисуем решетку:
  for (int x=0; x<width/cellSize; x++) {
    for (int y=0; y<height/cellSize; y++) {
      if (cells[x][y]==1) {
        fill(alive); // если жива
      }
      else {
        fill(dead); // если мертва
      }
      rect (x*cellSize, y*cellSize, cellSize, cellSize);
    }
  }
  // итерируем, если таймер дает отсчет:
  if (millis()-lastRecordedTime>interval) {
    if (!pause) {
      iteration();
      lastRecordedTime = millis();
    }
  }
  // во время паузы вручную создаем новые клетки:
  if (pause && mousePressed) {
    // масштабируем друг к другу размер экрана
    // и количество ячеек в фоновой решетке;
    // также задаем границы для фоновой решетки:
    int xCellOver = int(map(mouseX, 0, width, 0, width/cellSize));
    xCellOver = constrain(xCellOver, 0, width/cellSize-1);
    int yCellOver = int(map(mouseY, 0, height, 0, height/cellSize));
    yCellOver = constrain(yCellOver, 0, height/cellSize-1);
    // сверяемся с клетками в буфере:
    if (cellsBuffer[xCellOver][yCellOver]==1) { // клетка жива
      cells[xCellOver][yCellOver]=0; // убита
      fill(dead); // заполняем цветом убитой клетки
    }
    else { // клетка мертва
      cells[xCellOver][yCellOver]=1; // оживляем
      fill(alive); // заполняем цветом живой клетки
    }
  } 
  else if (pause && !mousePressed) { // и сохраняем, когда 
                                     // пользователь отпустил мышку
    // сохраняем клетки в буфер
    // (это дает возможность работать 
    // с одним массивом, другой оставляя нетронутым):
    for (int x=0; x<width/cellSize; x++) {
      for (int y=0; y<height/cellSize; y++) {
        cellsBuffer[x][y] = cells[x][y];
      }
    }
  }
}
void iteration() { // если счетчик дает отчет
  // сохраняем клетки в буфер 
  // (это дает возможность работать
  // с одним массивом, другой оставляя нетронутым):
  for (int x=0; x<width/cellSize; x++) {
    for (int y=0; y<height/cellSize; y++) {
      cellsBuffer[x][y] = cells[x][y];
    }
  }
  // проходим через все клетки:
  for (int x=0; x<width/cellSize; x++) {
    for (int y=0; y<height/cellSize; y++) {
      // проходим через всех соседей каждой клетки:
      int neighbours = 0; // считаем соседей
      for (int xx=x-1; xx<=x+1;xx++) {
        for (int yy=y-1; yy<=y+1;yy++) {  
          // проверяем, не вышли ли за пределы экрана:
          if (((xx>=0)&&(xx<width/cellSize))&&((yy>=0)&&(yy<height/cellSize))) {
            if (!((xx==x)&&(yy==y))) { // проверяем клетку
                                       // относительно самой себя
              if (cellsBuffer[xx][yy]==1){
                neighbours ++; // проверяем живых соседей и считаем их 
              }
            } // заканчиваем цикл if()
          } // заканчиваем цикл if()
        } // заканчиваем цикл yy 
      } // заканчиваем цикл xx
      // проверили всех соседей: применяем правила!
      if (cellsBuffer[x][y]==1) { // клетка жива: 
                                  // если нужно, убиваем ее
        if (neighbours < 2 || neighbours > 3) {
          cells[x][y] = 0; // убиваем, разве что у нее нет 2-3 соседей 
        }
      } 
      else { // клетка мертва: если нужно, оживляем 
        if (neighbours == 3 ) {
          cells[x][y] = 1; // только если у нее 3 соседа
        }
      } // заканчиваем цикл if()
    } // заканчиваем цикл y
  } // заканчиваем цикл x
} // конец функции
void keyPressed() {
  if (key=='r' || key == 'R') {
    // перезапуск - повторная инициализация клеток:
    for (int x=0; x<width/cellSize; x++) {
      for (int y=0; y<height/cellSize; y++) {
        float state = random (100);
        if (state > probabilityOfAliveAtStart) {
          state = 0;
        }
        else {
          state = 1;
        }
        cells[x][y] = int(state); // сохраняем состояние каждой клетки 
      }
    }
  }
  if (key==' ') { // вкл/выкл для паузы
    pause = !pause;
  }
  if (key=='c' || key == 'C') { // очищаем все
    for (int x=0; x<width/cellSize; x++) {
      for (int y=0; y<height/cellSize; y++) {
        cells[x][y] = 0; // сохраняем все значения как «0»
      }
    }
  }
}
См.также
Внешние ссылки
| Примеры на Processing | |
|---|---|
| Основы | 
 | 
| Продвинутые графические эффекты | 
 | 
| Примеры из сторонних библиотек | |
Категории: 
- Страницы, использующие повторяющиеся аргументы в вызовах шаблонов
- Processing
- Перевод от Сubewriter
- Проверка:myagkij
- Оформление:myagkij
- Редактирование:myagkij
- Черновик
- Надо доработать
- Черновой вариант статьи
- Черновой вариант
- SEO
- Страницы, где используется шаблон "Навигационная таблица/Телепорт"
- Страницы с телепортом
