Cat hungry.png
Здравствуйте! Собираем деньги на перевод материалов по электронике(https://www.allaboutcircuits.com/education/). Реквизиты указаны здесь.

Processing:Примеры/Игра жизни Конвея

Материал из Онлайн справочника
Перейти к: навигация, поиск


Перевод: Максим Кузьмин (Cubewriter)
Перевел 2686 статей для сайта.

Контакты:

Проверка/Оформление/Редактирование: Мякишев Е.А.


Ambox content.png Черновик


Описание[1]

Нажмите на пробел, чтобы остановить клеточный автомат, или на кнопку мышки, чтобы изменить значения клеток. Во время паузы на клетки можно нажимать, активируя и деактивируя их. Нажмите на клавишу «R», чтобы случайно сбросить исходное расположение клеток. Нажмите на клавишу «C», чтобы очистить фоновую решетку.

Клеточный автомат «Игра жизни» был придуман Джоном Конвеем в 1970 году.

Пример

  1. // размер клеток:
  2. int cellSize = 5;
  3.  
  4. // насколько высока вероятность того,
  5. // что клетка будет жива в начале игры (в процентах):
  6. float probabilityOfAliveAtStart = 15;
  7.  
  8. // переменные для таймера:
  9. int interval = 100;
  10. int lastRecordedTime = 0;
  11.  
  12. // цвета для активных/неактивных клеток:
  13. color alive = color(0, 200, 0);
  14. color dead = color(0);
  15.  
  16. // массив клеток:
  17. int[][] cells;
  18. // буфер для записи состояния клеток;
  19. // он также будет использоваться
  20. // для изменения других клеток во время взаимодействий:
  21. int[][] cellsBuffer;
  22.  
  23. // пауза:
  24. boolean pause = false;
  25.  
  26. void setup() {
  27.   size (640, 360);
  28.  
  29.   // инициализируем массивы:
  30.   cells = new int[width/cellSize][height/cellSize];
  31.   cellsBuffer = new int[width/cellSize][height/cellSize];
  32.  
  33.   // строка для отрисовки фоновой клеточной решетки:
  34.   stroke(48);
  35.  
  36.   noSmooth();
  37.  
  38.   // инициализируем клетки:
  39.   for (int x=0; x<width/cellSize; x++) {
  40.     for (int y=0; y<height/cellSize; y++) {
  41.       float state = random (100);
  42.       if (state > probabilityOfAliveAtStart) {
  43.         state = 0;
  44.       }
  45.       else {
  46.         state = 1;
  47.       }
  48.       cells[x][y] = int(state); // сохраняем состояние каждой клетки
  49.     }
  50.   }
  51.   background(0); // закрашиваем фон черным на случай,
  52.                  // если клетки не заполнят все ячейки решетки
  53. }
  54.  
  55.  
  56. void draw() {
  57.  
  58.   // рисуем решетку:
  59.   for (int x=0; x<width/cellSize; x++) {
  60.     for (int y=0; y<height/cellSize; y++) {
  61.       if (cells[x][y]==1) {
  62.         fill(alive); // если жива
  63.       }
  64.       else {
  65.         fill(dead); // если мертва
  66.       }
  67.       rect (x*cellSize, y*cellSize, cellSize, cellSize);
  68.     }
  69.   }
  70.   // итерируем, если таймер дает отсчет:
  71.   if (millis()-lastRecordedTime>interval) {
  72.     if (!pause) {
  73.       iteration();
  74.       lastRecordedTime = millis();
  75.     }
  76.   }
  77.  
  78.   // во время паузы вручную создаем новые клетки:
  79.   if (pause && mousePressed) {
  80.     // масштабируем друг к другу размер экрана
  81.     // и количество ячеек в фоновой решетке;
  82.     // также задаем границы для фоновой решетки:
  83.     int xCellOver = int(map(mouseX, 0, width, 0, width/cellSize));
  84.     xCellOver = constrain(xCellOver, 0, width/cellSize-1);
  85.     int yCellOver = int(map(mouseY, 0, height, 0, height/cellSize));
  86.     yCellOver = constrain(yCellOver, 0, height/cellSize-1);
  87.  
  88.     // сверяемся с клетками в буфере:
  89.     if (cellsBuffer[xCellOver][yCellOver]==1) { // клетка жива
  90.       cells[xCellOver][yCellOver]=0; // убита
  91.       fill(dead); // заполняем цветом убитой клетки
  92.     }
  93.     else { // клетка мертва
  94.       cells[xCellOver][yCellOver]=1; // оживляем
  95.       fill(alive); // заполняем цветом живой клетки
  96.     }
  97.   }
  98.   else if (pause && !mousePressed) { // и сохраняем, когда
  99.                                      // пользователь отпустил мышку
  100.     // сохраняем клетки в буфер
  101.     // (это дает возможность работать
  102.     // с одним массивом, другой оставляя нетронутым):
  103.     for (int x=0; x<width/cellSize; x++) {
  104.       for (int y=0; y<height/cellSize; y++) {
  105.         cellsBuffer[x][y] = cells[x][y];
  106.       }
  107.     }
  108.   }
  109. }
  110.  
  111.  
  112.  
  113. void iteration() { // если счетчик дает отчет
  114.   // сохраняем клетки в буфер
  115.   // (это дает возможность работать
  116.   // с одним массивом, другой оставляя нетронутым):
  117.   for (int x=0; x<width/cellSize; x++) {
  118.     for (int y=0; y<height/cellSize; y++) {
  119.       cellsBuffer[x][y] = cells[x][y];
  120.     }
  121.   }
  122.  
  123.   // проходим через все клетки:
  124.   for (int x=0; x<width/cellSize; x++) {
  125.     for (int y=0; y<height/cellSize; y++) {
  126.       // проходим через всех соседей каждой клетки:
  127.       int neighbours = 0; // считаем соседей
  128.       for (int xx=x-1; xx<=x+1;xx++) {
  129.         for (int yy=y-1; yy<=y+1;yy++) {  
  130.           // проверяем, не вышли ли за пределы экрана:
  131.           if (((xx>=0)&&(xx<width/cellSize))&&((yy>=0)&&(yy<height/cellSize))) {
  132.             if (!((xx==x)&&(yy==y))) { // проверяем клетку
  133.                                        // относительно самой себя
  134.               if (cellsBuffer[xx][yy]==1){
  135.                 neighbours ++; // проверяем живых соседей и считаем их
  136.               }
  137.             } // заканчиваем цикл if()
  138.           } // заканчиваем цикл if()
  139.         } // заканчиваем цикл yy
  140.       } // заканчиваем цикл xx
  141.       // проверили всех соседей: применяем правила!
  142.       if (cellsBuffer[x][y]==1) { // клетка жива:
  143.                                   // если нужно, убиваем ее
  144.         if (neighbours < 2 || neighbours > 3) {
  145.           cells[x][y] = 0; // убиваем, разве что у нее нет 2-3 соседей
  146.         }
  147.       }
  148.       else { // клетка мертва: если нужно, оживляем
  149.         if (neighbours == 3 ) {
  150.           cells[x][y] = 1; // только если у нее 3 соседа
  151.         }
  152.       } // заканчиваем цикл if()
  153.     } // заканчиваем цикл y
  154.   } // заканчиваем цикл x
  155. } // конец функции
  156.  
  157. void keyPressed() {
  158.   if (key=='r' || key == 'R') {
  159.     // перезапуск - повторная инициализация клеток:
  160.     for (int x=0; x<width/cellSize; x++) {
  161.       for (int y=0; y<height/cellSize; y++) {
  162.         float state = random (100);
  163.         if (state > probabilityOfAliveAtStart) {
  164.           state = 0;
  165.         }
  166.         else {
  167.           state = 1;
  168.         }
  169.         cells[x][y] = int(state); // сохраняем состояние каждой клетки
  170.       }
  171.     }
  172.   }
  173.   if (key==' ') { // вкл/выкл для паузы
  174.     pause = !pause;
  175.   }
  176.   if (key=='c' || key == 'C') { // очищаем все
  177.     for (int x=0; x<width/cellSize; x++) {
  178.       for (int y=0; y<height/cellSize; y++) {
  179.         cells[x][y] = 0; // сохраняем все значения как «0»
  180.       }
  181.     }
  182.   }
  183. }

См.также

Внешние ссылки

  1. processing.org - A Processing implementation of Game of Life By Joan Soler-Adillon