|
|
(не показаны 3 промежуточные версии 2 участников) |
Строка 1: |
Строка 1: |
− | [[Virtual laboratory]] > [[Conway's Game of Life]] <HR>
| |
| | | |
− | Here is the program, representing a classic game [http://ru.wikipedia.org/wiki/Жизнь_(игра) "Life"] by John Conway with the ability to draw the cells on the field with the help of cursor.
| |
− |
| |
− | {{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/Tcvetkov/CelAut/CelAut_v2_release/CelAut_v2_release.html |width=630 |height=650 |border=0 }}
| |
− |
| |
− | Download program: [[Медиа:CelAut_v2_release.zip|CelAut_v2_release.zip]]
| |
− | <div class="mw-collapsible mw-collapsed" style="width:100%" >
| |
− | '''The Text of the program is written in JavaScript (the developer is [[Цветков Денис]]):''' <div class="mw-collapsible-content">
| |
− | Файл '''"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 = "Stop";
| |
− | }
| |
− |
| |
− | function stopSystem() {
| |
− | pause = true;
| |
− | clearInterval(intervalID);
| |
− | document.getElementById('pause').value = "Next step";
| |
− | }
| |
− |
| |
− | // Расчетная часть программы
| |
− |
| |
− | // функции, обеспечивающие периодичность системы
| |
− | 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();
| |
− |
| |
− | }
| |
− | </syntaxhighlight>
| |
− | Файл '''"CelAut_v2_release.html"'''
| |
− | <syntaxhighlight lang="html5" 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><br>
| |
− | <input id="pause" type="button" name="Stop" style="width: 100px" onclick="app.changePauseState();return false;"/>
| |
− | <input type="button" name="" onclick="app.nextStep();return false;" value="Next step"/>
| |
− | <input type="button" name="" onclick="app.clear();return false;" value="Clear the field"/>
| |
− | <script type="text/javascript">var app = new MainChain(document.getElementById('canvasCelAut'));</script>
| |
− | </body>
| |
− | </html>
| |
− | </syntaxhighlight>
| |
− | </div>
| |
− | </div>
| |
− |
| |
− | [[JavaScript - Клеточный автомат|Here]] you can find the previous versions of the program.
| |
− |
| |
− | [[Category: Virtual Laboratory]]
| |
− | [[Category: Programming]]
| |