Игра "Жизнь"

Материал из Department of Theoretical and Applied Mechanics
Версия от 18:52, 8 марта 2015; Wikiadmin (обсуждение | вклад) (Замена текста — «<source lang="(.*)" first-line="(.*)">» на «<syntaxhighlight lang="$1" line start="$2" enclose="div">»)

Перейти к: навигация, поиск
Виртуальная лаборатория > Игра "Жизнь"

Здесь расположена программа, представляющая из себя классическую игру "Жизнь" Джона Конвея с возможностью рисовать курсором клетки на поле.

Скачать программу: CelAut_v2_release.zip Текст программы на языке JavaScript (разработчик Цветков Денис): <toggledisplay status=hide showtext="Показать↓" hidetext="Скрыть↑" linkstyle="font-size:default"> Файл "CelAut_v2_release.js" <syntaxhighlight lang="javascript" line start="1" enclose="div"> function MainChain(canvas) {

   // Предварительные установки
   var context = canvas.getContext("2d");                  // на context происходит рисование
   document.oncontextmenu=function(e){return false};       // блокировка контекстного меню
   // *** Задание вычислительных параметров ***
   var fps = 5;             	    // frames per second - число кадров в секунду
   // Выполнение программы
   var w = canvas.width;		    // ширина окна
   var h = canvas.height;		// высота окна
   var n = 50;                   // количество клеток по горизонтали (желательно, делитель ширины окна)
   var m = 50;                   // количество клеток по горизонтали (желательно, делитель высоты окна)
   var cellW = w/n;              // ширина клетки
   var cellH = h/m;              // высота клетки
   var pause = true;
   var intervalID;                 // для управления работой автомата
   // "Жизнь" Конвея: [B = 000100000, L = 001100000]
   var B = "000100000";            // геном рождения
   var L = "001100000";            // геном выживания
   // Работа с мышью
   var mouseX;     var mouseY;                 // координаты курсора мыши
   canvas.onmousedown = function(e){           // функция при нажатии клавиши мыши
       var life;
       if (e.which == 1) life = true;          // при нажатии левой клавиши мыши клетка рождается
       else if (e.which == 3) life = false;    // при нажатии правой клавиши мыши клетка умирает
       else return;
       setCell(e, life);
       canvas.onmousemove = function(e) {setCell(e, life);};   // функция, выполняющаяся при перемещении курсора мыши
   };
   document.onmouseup = function(e){           // функция при отпускании клавиши мыши
       canvas.onmousemove = null;              // когда клавиша отпущена - функции перемещения нету
   };
   function refreshMouseCoords(e){             // процедура обновляет координаты в переменных mouseX и mouseY
       var rect = canvas.getBoundingClientRect();
       mouseX = e.clientX - rect.left;
       mouseY = e.clientY - rect.top;
   }
   // Работа с массивом
   var cells;                      // массив клеток
   var cellsBuf = [];              // буфер для расчета следующего шага
   for (var i = 0; i < n; i++) cellsBuf[i] = [];
   function generateRandomField(n, m) {        // каждая клетка заполняется случайным значением жива/мертва
       cells = [];
       for (var i = 0; i < n; i++) {
           cells[i] = [];
           for (var j = 0; j < m; j++) {
               cells[i][j] = (Math.random() >= 0.5);
           }
       }
   }
   function setCell(e, life){                  // придать клетке определенное состояние с нажатия клавиши мыши
       refreshMouseCoords(e);                  // обновить координаты в переменных mouseX, mouseY
       if (mouseX < 0 || mouseX >= w || mouseY < 0 || mouseY >= h) return;         // проверка на ошибочные координаты
       var i = Math.floor(mouseX/cellW);       // получаем ячейку по горизонтали
       var j = Math.floor(mouseY/cellH);       // получаем ячейку по вертикали
       if (cells[i][j] != life) {
           cells[i][j] = life;
           draw();
       }
   }
   MainChain.prototype.clear = function(){
       for (var i = 0; i < n; i++)
           for (var j = 0; j < m; j++)
               cells[i][j] = false;
       draw();
       stopSystem();
   };
   // Управление работой автомата
   function step() {
       tick();
       draw();
   }
   MainChain.prototype.changePauseState = function() {          // кнопка паузы
       if (!pause) stopSystem();
       else startSystem()
   };
   MainChain.prototype.nextStep = function(){                   // кнопка "Следующий шаг"
       stopSystem();
       step();
   };
   function startSystem() {
       pause = false;
       intervalID = setInterval(step, 1000/fps);
       document.getElementById('pause').value = "Остановить";
   }
   function stopSystem() {
       pause = true;
       clearInterval(intervalID);
       document.getElementById('pause').value = "Запустить";
   }
   // Расчетная часть программы
   // функции, обеспечивающие периодичность системы
   function next(i, n) {if (i == (n-1)) return 0; else return i+1;}
   function prev(i, n) {if (i == 0) return n-1; else return i-1;}
   function tick(){                             // то, что происходит каждый шаг времени
       // копирование массива cells в cellsBuf
       for (var i0 = 0; i0 < n; i0++)
           for (var j0 = 0; j0 < m; j0++)
               cellsBuf[i0][j0] = cells[i0][j0];
       for (var i = 0; i < n; i++) {
           for (var j = 0; j < m; j++) {
               // подсчет количества живых клеток вокруг рассматриваемой клетки
               var near = 0;
               if (cellsBuf[prev(i, n)] [prev(j, m)])   near++;
               if (cellsBuf[prev(i, n)] [j])            near++;
               if (cellsBuf[prev(i, n)] [next(j, m)])   near++;
               if (cellsBuf[i]          [prev(j, m)])   near++;
               if (cellsBuf[i]          [next(j, m)])   near++;
               if (cellsBuf[next(i, n)] [prev(j, m)])   near++;
               if (cellsBuf[next(i, n)] [j])            near++;
               if (cellsBuf[next(i, n)] [next(j, m)])   near++;
               if (cellsBuf[i][j])                     // рассматриваемая клетка жива
                   cells[i][j] = (L[near] == '1');     // проверка условия выживания по биному L
               else                                    // рассматриваемая клетка мертва
                   cells[i][j] = (B[near] == '1');     // проверка условия рождения по биному B
           }
       }
   }
   // Рисование
   function draw(){
       context.clearRect(0, 0, w, h);          // очистить экран
       for (var i = 0; i < n; i++){
           for (var j = 0; j < m; j++){
               if (cells[i][j]){
                   context.beginPath();
                   context.rect(i*cellW, j*cellH, cellW, cellH);
                   context.closePath();
                   context.fill();
               }
           }
       }
   }
   // Запуск системы
   generateRandomField(n, m);                  // сгенероровать поле
   startSystem();

} </source> Файл "CelAut_v2_release.html" <syntaxhighlight lang="html" line start="1" enclose="div"> <!DOCTYPE html> <html> <head>

   <title>Cellular automaton</title>
   <script src="CelAut_v2_release.js"></script>

</head> <body>

   <canvas id="canvasCelAut" width="600" height="600" style="border:1px solid #000000;"></canvas>
<input id="pause" type="button" name="" style="width: 100px" onclick="app.changePauseState();return false;"/> <input type="button" name="" onclick="app.nextStep();return false;" value="Следующий шаг"/> <input type="button" name="" onclick="app.clear();return false;" value="Очистить поле"/> <script type="text/javascript">var app = new MainChain(document.getElementById('canvasCelAut'));</script>

</body> </html> </source> </toggledisplay>

Здесь вы можете найти предыдущие версии программы.