CelAut v2
Материал из Department of Theoretical and Applied Mechanics
Версия от 18:56, 8 марта 2015; Wikiadmin (обсуждение | вклад) (Замена текста — «</source>» на «</syntaxhighligh>»)
Виртуальная лаборатория > Игра "Жизнь" > Клеточный автомат - версии > CelAut v2
Скачать программу: 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();
} </syntaxhighligh> Файл "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> </syntaxhighligh> </toggledisplay>