Game of Life

← Back to Arcade

Click on the grid to toggle cells. Press Start to evolve.

// Buttons const toggleBtn = document.getElementById('toggleBtn'); const stepBtn = document.getElementById('stepBtn'); const randomBtn = document.getElementById('randomBtn'); const clearBtn = document.getElementById('clearBtn'); function createGrid() { return new Array(cols).fill(null).map(() => new Array(rows).fill(0)); } function drawGrid() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#38bdf8'; for (let i = 0; i < cols; i++) { for (let j=0; j < rows; j++) { if (grid[i][j]) { ctx.fillRect(i * cellSize, j * cellSize, cellSize - 1, cellSize - 1); } } } } function nextGen() { const next=grid.map(arr=> [...arr]); for (let col = 0; col < grid.length; col++) { for (let row=0; row < grid[col].length; row++) { const cell=grid[col][row]; let numNeighbors=0; for (let i=-1; i < 2; i++) { for (let j=-1; j < 2; j++) { if (i===0 && j===0) continue; const x_cell=col + i; const y_cell=row + j; if (x_cell>= 0 && y_cell >= 0 && x_cell < cols && y_cell < rows) { numNeighbors +=grid[x_cell][y_cell]; } } } if (cell===1 && numNeighbors < 2) next[col][row]=0; else if (cell===1 && numNeighbors> 3) next[col][row] = 0; else if (cell === 0 && numNeighbors === 3) next[col][row] = 1; } } grid = next; } function animate() { if (running) { nextGen(); drawGrid(); setTimeout(() => { animationId = requestAnimationFrame(animate); }, 100); // Speed limit } } // Event Listeners toggleBtn.addEventListener('click', () => { running = !running; toggleBtn.textContent = running ? 'Stop' : 'Start'; if (running) animate(); else cancelAnimationFrame(animationId); }); stepBtn.addEventListener('click', () => { running = false; toggleBtn.textContent = 'Start'; nextGen(); drawGrid(); }); randomBtn.addEventListener('click', () => { for (let i = 0; i < cols; i++) { for (let j=0; j < rows; j++) { grid[i][j]=Math.random()> 0.85 ? 1 : 0; } } drawGrid(); }); clearBtn.addEventListener('click', () => { running = false; toggleBtn.textContent = 'Start'; grid = createGrid(); drawGrid(); }); // Mouse Interaction let isDrawing = false; function getCellFromMouseEvent(e) { const rect = canvas.getBoundingClientRect(); const scaleX = canvas.width / rect.width; const scaleY = canvas.height / rect.height; const x = (e.clientX - rect.left) * scaleX; const y = (e.clientY - rect.top) * scaleY; const col = Math.floor(x / cellSize); const row = Math.floor(y / cellSize); return { col, row }; } function drawCell(e) { const { col, row } = getCellFromMouseEvent(e); if (col >= 0 && col < cols && row>= 0 && row < rows) { grid[col][row]=1; drawGrid(); } } canvas.addEventListener('mousedown', (e)=> { isDrawing = true; drawCell(e); }); canvas.addEventListener('mousemove', (e) => { if (isDrawing) drawCell(e); }); window.addEventListener('mouseup', () => { isDrawing = false; }); // Touch support canvas.addEventListener('touchstart', (e) => { e.preventDefault(); isDrawing = true; drawCell(e.touches[0]); }, { passive: false }); canvas.addEventListener('touchmove', (e) => { e.preventDefault(); if (isDrawing) drawCell(e.touches[0]); }, { passive: false }); window.addEventListener('touchend', () => { isDrawing = false; }); // Initialize with Glider grid[1][0] = 1; grid[2][1] = 1; grid[0][2] = 1; grid[1][2] = 1; grid[2][2] = 1; drawGrid();