Changed around line 1
+ class GameOfLife {
+ constructor(canvas) {
+ this.canvas = canvas;
+ this.ctx = canvas.getContext('2d');
+ this.cellSize = 10;
+ this.running = false;
+ this.speed = 5;
+
+ this.resizeCanvas();
+ this.initGrid();
+ this.addEventListeners();
+
+ window.addEventListener('resize', () => this.resizeCanvas());
+ }
+
+ resizeCanvas() {
+ this.canvas.width = this.canvas.offsetWidth;
+ this.canvas.height = this.canvas.offsetHeight;
+ this.cols = Math.floor(this.canvas.width / this.cellSize);
+ this.rows = Math.floor(this.canvas.height / this.cellSize);
+ this.initGrid();
+ this.draw();
+ }
+
+ initGrid() {
+ this.grid = Array(this.rows).fill().map(() =>
+ Array(this.cols).fill(false)
+ );
+ }
+
+ addEventListeners() {
+ this.canvas.addEventListener('click', (e) => {
+ const rect = this.canvas.getBoundingClientRect();
+ const x = e.clientX - rect.left;
+ const y = e.clientY - rect.top;
+ const col = Math.floor(x / this.cellSize);
+ const row = Math.floor(y / this.cellSize);
+ this.grid[row][col] = !this.grid[row][col];
+ this.draw();
+ });
+
+ document.getElementById('startBtn').addEventListener('click', () => {
+ this.running = !this.running;
+ document.getElementById('startBtn').textContent = this.running ? 'Stop' : 'Start';
+ if (this.running) this.animate();
+ });
+
+ document.getElementById('clearBtn').addEventListener('click', () => {
+ this.initGrid();
+ this.draw();
+ });
+
+ document.getElementById('randomBtn').addEventListener('click', () => {
+ this.grid = this.grid.map(row =>
+ row.map(() => Math.random() > 0.8)
+ );
+ this.draw();
+ });
+
+ document.getElementById('speed').addEventListener('input', (e) => {
+ this.speed = e.target.value;
+ });
+ }
+
+ countNeighbors(row, col) {
+ let count = 0;
+ for (let i = -1; i <= 1; i++) {
+ for (let j = -1; j <= 1; j++) {
+ if (i === 0 && j === 0) continue;
+ const r = (row + i + this.rows) % this.rows;
+ const c = (col + j + this.cols) % this.cols;
+ if (this.grid[r][c]) count++;
+ }
+ }
+ return count;
+ }
+
+ nextGeneration() {
+ const newGrid = Array(this.rows).fill().map(() =>
+ Array(this.cols).fill(false)
+ );
+
+ for (let row = 0; row < this.rows; row++) {
+ for (let col = 0; col < this.cols; col++) {
+ const neighbors = this.countNeighbors(row, col);
+ if (this.grid[row][col]) {
+ newGrid[row][col] = neighbors === 2 || neighbors === 3;
+ } else {
+ newGrid[row][col] = neighbors === 3;
+ }
+ }
+ }
+
+ this.grid = newGrid;
+ }
+
+ draw() {
+ this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+
+ for (let row = 0; row < this.rows; row++) {
+ for (let col = 0; col < this.cols; col++) {
+ if (this.grid[row][col]) {
+ this.ctx.fillStyle = '#3498db';
+ this.ctx.fillRect(
+ col * this.cellSize,
+ row * this.cellSize,
+ this.cellSize - 1,
+ this.cellSize - 1
+ );
+ }
+ }
+ }
+ }
+
+ animate() {
+ if (!this.running) return;
+ this.nextGeneration();
+ this.draw();
+ setTimeout(() => requestAnimationFrame(() => this.animate()), 1000 / this.speed);
+ }
+ }
+
+ document.addEventListener('DOMContentLoaded', () => {
+ const canvas = document.getElementById('gameCanvas');
+ new GameOfLife(canvas);
+ });