'use strict' const b = { curry: function (fn) { const curried = (...args) => { if (args.length >= fn.length) return fn(...args) else return (...rest) => curried(...args, ...rest) } return curried }, pipe: (...fns) => (value) => fns.reduce((acc, fn) => fn(acc), value), }; const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const startPauseButton = document.getElementById('startPauseButton'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; const cellSize = 10; const rows = Math.floor(canvas.height / cellSize); const cols = Math.floor(canvas.width / cellSize); let grid = initializeGrid(); let animationId = null; function initializeGrid() { return Array.from({ length: rows }, () => Array.from({ length: cols }, () => Math.random() > 0.8 ? 1 : 0)); } const drawCell = b.curry((ctx, cellSize, x, y, cell) => { ctx.fillStyle = cell ? 'black' : 'white'; ctx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize); ctx.strokeStyle = 'gray'; ctx.strokeRect(x * cellSize, y * cellSize, cellSize, cellSize); }); const drawGrid = (ctx, cellSize, grid) => { ctx.clearRect(0, 0, canvas.width, canvas.height); grid.forEach((row, y) => row.forEach((cell, x) => drawCell(ctx, cellSize, x, y, cell))); }; const getNeighbors = (grid, x, y) => [ grid[y - 1]?.[x - 1], grid[y - 1]?.[x], grid[y - 1]?.[x + 1], grid[y]?.[x - 1], /* cell */ grid[y]?.[x + 1], grid[y + 1]?.[x - 1], grid[y + 1]?.[x], grid[y + 1]?.[x + 1] ].filter(Boolean).reduce((acc, val) => acc + val, 0); const nextCellState = b.curry((cell, neighbors) => (cell && neighbors === 2) || neighbors === 3 ? 1 : 0); const nextGridState = (grid) => grid.map((row, y) => row.map((cell, x) => nextCellState(cell, getNeighbors(grid, x, y)))); const animate = () => { drawGrid(ctx, cellSize, grid); grid = nextGridState(grid); animationId = requestAnimationFrame(animate); }; const toggleAnimation = () => { if (animationId) { cancelAnimationFrame(animationId); animationId = null; startPauseButton.textContent = 'Start'; } else { animate(); startPauseButton.textContent = 'Pause'; } }; startPauseButton.addEventListener('click', toggleAnimation); canvas.addEventListener('click', (event) => { const rect = canvas.getBoundingClientRect(); const x = Math.floor((event.clientX - rect.left) / cellSize); const y = Math.floor((event.clientY - rect.top) / cellSize); grid[y][x] = grid[y][x] ? 0 : 1; drawGrid(ctx, cellSize, grid); }); const startGame = b.pipe(initializeGrid, (grid) => { drawGrid(ctx, cellSize, grid); return grid; }); grid = startGame();