Немного "Жизни"...
По статистике, как минимум каждый 3-й программист это писал :) Ещё одна js-canvas-манипуляция на тему классической "Жизни" Конвея.
Что-то скучно, делами заниматься не хочется, и спать тоже :(
Играется на тороидальном поле, так законченней, раз бесконечного не сделать :) Настройки видны в тексте. "Мерцание"цвета фигур - просто так :) Для начала игры кликните по полю, для паузы - кликните ещё раз. Клавиша F5 - начать заново.
ConwayLife.html (5 Кб)
Скрипт в работе (нажать правой кнопкой мыши и выбрать пункт для сохранения объекта)
Полный исходник (предполагается, что будет размещён в кодировке Юникода UTF-8):
<!doctype html> <html> <head> <title>Conway's Life Game</title> <meta charset='utf-8' /> </head> <body> <div align="center"><small> <font color="darkred">клик по полю</font>: старт/стоп <font color="darkred">F5</font>: перезагрузить <font color="darkred">крткст</font>: с.т.</small></div> <div id="div" align="center"> <canvas id="canvas" style="border:0px"> <p>Похоже, ваш браузер не поддерживает HTML5 и тег <canvasas>.</p> <p>Попробуйте использовать один из следующих браузеров:</p> <ul> <li>Chrome (>4.0)</li> <li>Opera (>9.0)</li> <li>Opera Mobile (>10.0)</li> <li>Firefox (>2.0)</li> <li>Safari (>3.1)</li> <li>iOS Safari (>3.2)</li> <li>Android Browser (>2.1)</li> <li>Internet Explorer (>=9.0)</li> </ul> </canvas> </div> <script type="application/x-javascript"> var b = document.getElementById("div"); var c = document.getElementById("canvas"); var a = c.getContext("2d"); c.width=document.body.clientWidth; //размеры c.height=screen.height-132; //холста var baseSize = 5; //размер ячейки, пикс., [1-??] var startPerCent = 13; //начальный процент живых клеток, [1-99] var levelRGB=100; //предельная яркость R,G или B для закрашенной клетки, [0-255] var mainDelay=10; //главная задержка, мс., [5-??] function lifeGameFunction (width, height, baseSize) { this.width = width; this.height = height; this.baseSize = baseSize; this.grid = new Array(); this.initGame = function(){ for (var i = 0; i < this.width; i++) { this.grid[i] = new Array(); for (var j = 0; j < this.height; j++) { this.grid[i][j] = false; } } }; this.fillFieldByRandom = function (perCentOfLive) { for (var i = 0; i < this.width; i++) { for (var j = 0; j < this.height; j++) { this.grid[i][j] = Math.floor(Math.random() * 100/perCentOfLive) == 0; } } } this.gridPosition = function(i, widthCanvas) { var gridX = Math.floor((i%widthCanvas)/this.baseSize); var gridY = Math.floor((i/widthCanvas)/this.baseSize); return {x: gridX, y: gridY}; } this.neighbours = function(x,y) { var cnt = 0; if (x == 0) x = this.width; if (y == 0) y = this.height; for (var i=x-1; i<x+2; i++) { for (var j=y-1; j<y+2; j++) { if (!(i == x && j == y)) { var posX = i % this.width; var posY = j % this.height; if (this.grid[posX][posY]) cnt++; } } } return cnt; } this.oneStep = function() { var newGrid = new Array(); for (var i=0; i<this.width; i++) { newGrid[i] = new Array(); for (var j = 0; j < this.height; j++) { newGrid[i][j] = false; } } for (var i=0; i<this.width; i++) { for (var j=0; j<this.height; j++) { var numNeighbours = this.neighbours (i,j); if (this.grid[i][j]) { if (numNeighbours == 2 || numNeighbours == 3) { //классические правила newGrid[i][j] = true; } } else { if (numNeighbours == 3) { newGrid[i][j] = true; } } } } this.grid = newGrid; } this.getRandomInt = function (min, max) { return min + Math.floor(Math.random() * (max - min + 1)); } this.drawField = function (c) { var dataArray = c.createImageData(this.width*this.baseSize, this.height*this.baseSize); var area = dataArray.data.length; var widthCanvas = this.width * this.baseSize; var R = this.getRandomInt(0,levelRGB); var G = this.getRandomInt(0,levelRGB); var B = this.getRandomInt(0,levelRGB); for (var i=0; i<area/4; i++) { var position = this.gridPosition (i, widthCanvas); var gridX = position.x; var gridY = position.y; if (this.grid[gridX][gridY]) { dataArray.data[4*i] = R; //R - The color red (from 0-255) dataArray.data[4*i+1] = G; //G - The color green (from 0-255) dataArray.data[4*i+2] = B; //B - The color blue (from 0-255) dataArray.data[4*i+3] = 255;//A - The alpha channel (from 0-255; 0 is transparent and 255 is fully visible) } } c.putImageData (dataArray,0,0); } } //lifeGameFunction function mainGameCycle() { lifeGame.oneStep(); lifeGame.drawField(a); window.idTimeout = setTimeout(mainGameCycle, mainDelay); } function startOrStopGame(){ if (window.idTimeout) { clearTimeout (window.idTimeout); window.idTimeout = undefined; } else{ window.idTimeout = setTimeout(mainGameCycle, mainDelay); } } function main() { var width = Math.floor(c.width / baseSize); var height = Math.floor(c.height / baseSize); window.lifeGame = new lifeGameFunction (width, height, baseSize); lifeGame.initGame(); lifeGame.fillFieldByRandom(startPerCent); lifeGame.drawField(a); window.onclick = startOrStopGame; } window.onload = main; </script> <noscript> <p><b>Для работы приложения нужен включённый в браузере Javascript!</b></p> </noscript> </body></html>
Несколько раз запустив, обратил внимание, что самодвижущиеся планёры возникают из хаоса достаточно часто, но далеко они не улетают, сражённые неподвижными или крутящимися на месте фигурами. Всё как в большой жизни :)
Golly - open-source приложение для игры "Жизнь", невероятные конфигурации

Планёрное ружьё из "Жизни" Конвея в моей версии анимации GIF
27.01.2016, 23:55 [5557 просмотров]