Skip to content

Instantly share code, notes, and snippets.

@oleglomako
Created May 29, 2019 14:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oleglomako/512bd182feb8bc55fb63007ade67c9f8 to your computer and use it in GitHub Desktop.
Save oleglomako/512bd182feb8bc55fb63007ade67c9f8 to your computer and use it in GitHub Desktop.
<style>
#canvas {
width: 500px;
height: 500px;
border: 2px solid black;
margin: 10px;
background-image: url(grid.png);
}
input,
button {
margin-left: 10px;
}
</style>
<div dir="ltr" style="text-align: left;" trbidi="on">
<p>
<span>
<button id="btnRunLife">Run Life</button>
<button id="btnCleanGrid">Clean</button>
<button id="btnNewRandomGeneration">New Random Generation</button>
&nbsp;&nbsp;
Number of Generations: <span id="numberOfGenerations">0</span>
</span>
</p>
<canvas id="canvas" width="500" height="500"></canvas>
</div>
<script>
/**
* Oleg Lomako
* Wed, 8 May 2019 18:46:54
*/
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let grid = []; // массив игрового поля
let newGrid = [];
// размеры игрового поля в пикселях
const WIDTH_GRID_PIXEL = 500;
const HEIGHT_GRID_PIXEL = 500;
// размеры клетки игрового поля
const WIDTH_CELL_PIXEL = 10;
const HEIGHT_CELL_PIXEL = 10;
// размеры игрового поля в количестве клеток
const WIDTH_GRID = Math.floor(WIDTH_GRID_PIXEL / WIDTH_CELL_PIXEL); //500 /10 = 50
const HEIGHT_GRID = Math.floor(HEIGHT_GRID_PIXEL / WIDTH_CELL_PIXEL); //500 /10 = 50
let numberOfGenerations = 0; // счетчик поколений
let timer; // таймер
const TIMEOUT = 300;
// при клике нарисовать живую клетку
canvas.onclick = function (event) {
// координаты клетки игрового поля
let x = event.offsetX;
let y = event.offsetY;
x = Math.floor(x / WIDTH_CELL_PIXEL); //500 /10 = 50
y = Math.floor(y / HEIGHT_CELL_PIXEL); //500 /10 = 50
//при клике отобразить закраш клетку
//если клетка закрашена то стереть клетку
if (grid[y][x] == 1) {
grid[y][x] = 0;
} else {
grid[y][x] = 1;
}
drawGrid();
}
// создаем пустой массив поля и заполняем его нулями
function fillZeroGrid() {
for (let i = 0; i < HEIGHT_GRID; i++) {
grid[i] = [];
for (let j = 0; j < WIDTH_GRID; j++) {
grid[i][j] = 0;
}
}
}
function fillZeroNewGrid() {
for (let i = 0; i < HEIGHT_GRID; i++) {
newGrid[i] = [];
for (let j = 0; j < WIDTH_GRID; j++) {
newGrid[i][j] = 0;
}
}
}
// массив grid заполняем нулями
fillZeroGrid();
// массив newGrid заполняем нулями
fillZeroNewGrid();
// нарисовать игровое поле
function drawGrid() {
ctx.clearRect(0, 0, WIDTH_GRID_PIXEL, HEIGHT_GRID_PIXEL);
for (let i = 0; i < HEIGHT_GRID; i++) {
for (let j = 0; j < WIDTH_GRID; j++) {
if (grid[i][j] == 1) {
ctx.fillRect(j * 10, i * 10, 10, 10);
}
}
}
}
// моделирование жизни
function runLife() {
for (let i = 0; i < HEIGHT_GRID; i++) {
for (let j = 0; j < WIDTH_GRID; j++) {
newGrid[i][j] = result(grid[i][j], countNeighbors(i, j));
}
}
nextStep(); // присваем след поколение текущему массиву
fillZeroNewGrid(); // очищаем массив след поколения
drawGrid();
numberOfGenerations++;
document.getElementById('numberOfGenerations').innerHTML = numberOfGenerations;
timer = setTimeout(runLife, TIMEOUT);
}
// следующее поколение
function nextStep() {
for (let i = 0; i < HEIGHT_GRID; i++) {
for (let j = 0; j < WIDTH_GRID; j++) {
grid[i][j] = newGrid[i][j];
}
}
}
// считаем соседей
function countNeighbors(xCell, yCell) {
let sumNeighbors = 0;
for (let i = -1; i < 2; i++) {
for (let j = -1; j < 2; j++) {
let neighborX = xCell - i;
let neighborY = yCell - j;
// игнорируем проверяемую клетку
if (neighborX == xCell && neighborY == yCell) continue;
let isValid = checkValid(neighborX, neighborY);
if (isValid) {
sumNeighbors += grid[neighborX][neighborY];
}
}
}
return sumNeighbors;
}
// проверка выхода за границы поля
function checkValid(cX, cY) {
return (cX >= 0 && cX < WIDTH_GRID && cY >= 0 && cY < HEIGHT_GRID);
}
// принятие решения о состоянии клетки в след поколении
function result(cellBoard, neighbors) {
if (cellBoard == 0 && neighbors == 3)
return 1;
else if ((cellBoard == 1 && neighbors == 2))
return 1;
else if ((cellBoard == 1 && neighbors == 3))
return 1;
else if ((cellBoard == 1 && neighbors < 2))
return 0;
else if ((cellBoard == 1 && neighbors > 3))
return 0;
else
return cellBoard;
}
// сгенерировать и отобразить рандомно новое поколение
function newRandomGeneration() {
for (let i = 0; i < HEIGHT_GRID; i++) {
for (let j = 0; j < WIDTH_GRID; j++) {
grid[i][j] = randomInteger(0, 1);
}
}
drawGrid();
}
// сгенерировать случайное число
function randomInteger(min, max) {
var rand = min + Math.random() * (max + 1 - min);
rand = Math.floor(rand);
return rand;
}
// остановить игру и обновить страницу
function refreshPage() {
window.location.reload();
};
document.getElementById('btnRunLife').onclick = runLife;
document.getElementById('btnNewRandomGeneration').onclick = newRandomGeneration;
document.getElementById('btnCleanGrid').onclick = refreshPage;
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment