Last active
November 10, 2024 13:13
-
-
Save cravelweb/9a5661d339100007614441de4624ae22 to your computer and use it in GitHub Desktop.
Conway's Game of Life JavaScript - ライフゲーム.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Game of Life</title> | |
<style> | |
canvas { | |
border: 1px solid black; | |
display: block; | |
margin: 20px auto; | |
cursor: crosshair; | |
} | |
#controls { | |
text-align: center; | |
margin: 10px auto; | |
} | |
</style> | |
</head> | |
<body> | |
<canvas id="gameCanvas" width="800" height="800"></canvas> | |
<div id="controls"> | |
<button id="startStopButton">Play</button> | |
<button id="clearButton">Clear</button> | |
<button id="randomButton">Random Setup</button> | |
<label for="speedRange">Speed:</label> | |
<input type="range" id="speedRange" min="10" max="1000" value="100"> | |
<label for="patternSelect">Pattern:</label> | |
<select id="patternSelect"> | |
<option value="cell">cell</option> | |
<option value="random">random</option> | |
<option value="gliderGun">Glider Gun</option> | |
<option value="pufferTrain">Puffer Train</option> | |
<option value="glider">Glider</option> | |
<option value="lightweightSpaceship">Lightweight Spaceship</option> | |
</select> | |
</div> | |
<script src="life-game.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const canvas = document.getElementById('gameCanvas'); | |
const ctx = canvas.getContext('2d'); | |
const gridSize = 100; | |
const cellSize = canvas.width / gridSize; | |
let grid = createGrid(gridSize); | |
let isRunning = false; | |
let intervalId; | |
let speed = 100; | |
let isMouseDown = false; | |
// Initialize with random setup | |
initializeRandomGrid(); | |
// Get control elements | |
const startStopButton = document.getElementById('startStopButton'); | |
const clearButton = document.getElementById('clearButton'); | |
const randomButton = document.getElementById('randomButton'); | |
const speedRange = document.getElementById('speedRange'); | |
const patternSelect = document.getElementById('patternSelect'); | |
// Event listener for play/stop button | |
startStopButton.addEventListener('click', () => { | |
if (isRunning) { | |
stopGame(); | |
} else { | |
startGame(); | |
} | |
}); | |
// Event listener for clear button | |
clearButton.addEventListener('click', () => { | |
stopGame(); | |
grid = createGrid(gridSize); | |
drawGrid(grid); | |
}); | |
// Event listener for random setup button | |
randomButton.addEventListener('click', () => { | |
stopGame(); | |
initializeRandomGrid(); | |
drawGrid(grid); | |
}); | |
// Event listener for speed slider | |
speedRange.addEventListener('input', (event) => { | |
speed = event.target.value; | |
if (isRunning) { | |
stopGame(); | |
startGame(); | |
} | |
}); | |
// Function to start the game | |
function startGame() { | |
isRunning = true; | |
startStopButton.textContent = 'Stop'; | |
intervalId = setInterval(() => { | |
drawGrid(grid); | |
grid = nextGeneration(grid); | |
}, speed); | |
} | |
// Function to stop the game | |
function stopGame() { | |
isRunning = false; | |
startStopButton.textContent = 'Play'; | |
clearInterval(intervalId); | |
} | |
// Function to draw the grid | |
function drawGrid(grid) { | |
ctx.clearRect(0, 0, canvas.width, canvas.height); | |
for (let i = 0; i < gridSize; i++) { | |
for (let j = 0; j < gridSize; j++) { | |
if (grid[i][j] === 1) { | |
ctx.fillStyle = 'black'; | |
ctx.fillRect(i * cellSize, j * cellSize, cellSize, cellSize); | |
} | |
} | |
} | |
} | |
// Function to calculate the next generation of the grid | |
function nextGeneration(grid) { | |
let newGrid = createGrid(gridSize); | |
for (let i = 0; i < gridSize; i++) { | |
for (let j = 0; j < gridSize; j++) { | |
const aliveNeighbors = countAliveNeighbors(grid, i, j); | |
if (grid[i][j] === 1) { | |
newGrid[i][j] = (aliveNeighbors === 2 || aliveNeighbors === 3) ? 1 : 0; | |
} else { | |
newGrid[i][j] = (aliveNeighbors === 3) ? 1 : 0; | |
} | |
} | |
} | |
return newGrid; | |
} | |
// Function to count the number of alive neighbors of a cell | |
function countAliveNeighbors(grid, x, y) { | |
let count = 0; | |
for (let i = -1; i <= 1; i++) { | |
for (let j = -1; j <= 1; j++) { | |
if (i === 0 && j === 0) continue; // Skip the cell itself | |
const nx = (x + i + gridSize) % gridSize; // Wrap around the edges | |
const ny = (y + j + gridSize) % gridSize; // Wrap around the edges | |
count += grid[nx][ny]; | |
} | |
} | |
return count; | |
} | |
// Function to initialize the grid | |
function createGrid(size) { | |
let grid = new Array(size); | |
for (let i = 0; i < size; i++) { | |
grid[i] = new Array(size).fill(0); | |
} | |
return grid; | |
} | |
// Function to initialize the grid with random cells | |
function initializeRandomGrid() { | |
grid = createGrid(gridSize); | |
for (let i = 0; i < gridSize; i++) { | |
for (let j = 0; j < gridSize; j++) { | |
grid[i][j] = Math.random() > 0.8 ? 1 : 0; | |
} | |
} | |
} | |
// Function to place a specific pattern on the grid | |
function placePattern(pattern, offsetX, offsetY) { | |
pattern.forEach(([x, y]) => { | |
const gridX = (x + offsetX) % gridSize; | |
const gridY = (y + offsetY) % gridSize; | |
grid[gridX][gridY] = 1; | |
}); | |
} | |
// Event listener for mouse actions to handle cell placement | |
canvas.addEventListener('mousedown', () => { | |
isMouseDown = true; | |
}); | |
canvas.addEventListener('mouseup', () => { | |
isMouseDown = false; | |
}); | |
canvas.addEventListener('mousemove', (event) => { | |
if (isMouseDown) { | |
handlePatternPlacement(event); | |
} | |
}); | |
canvas.addEventListener('click', (event) => { | |
handlePatternPlacement(event); | |
}); | |
// Function to handle pattern placement based on mouse click | |
function handlePatternPlacement(event) { | |
const rect = canvas.getBoundingClientRect(); | |
const scaleX = canvas.width / rect.width; | |
const scaleY = canvas.height / rect.height; | |
const x = Math.floor((event.clientX - rect.left) * scaleX / cellSize); | |
const y = Math.floor((event.clientY - rect.top) * scaleY / cellSize); | |
if (x >= 0 && x < gridSize && y >= 0 && y < gridSize) { | |
const selectedPattern = patternSelect.value; | |
if (selectedPattern === 'cell') { | |
grid[x][y] = grid[x][y] === 1 ? 0 : 1; // Toggle cell | |
} else if (selectedPattern === 'random') { | |
for (let i = -5; i <= 5; i++) { | |
for (let j = -5; j <= 5; j++) { | |
const nx = (x + i + gridSize) % gridSize; | |
const ny = (y + j + gridSize) % gridSize; | |
if (Math.random() > 0.5) { | |
grid[nx][ny] = 1; | |
} | |
} | |
} | |
} else if (selectedPattern === 'gliderGun') { | |
placePattern(gliderGunPattern, x, y); | |
} else if (selectedPattern === 'pufferTrain') { | |
placePattern(pufferTrainPattern, x, y); | |
} else if (selectedPattern === 'glider') { | |
placePattern(gliderPattern, x, y); | |
} else if (selectedPattern === 'lightweightSpaceship') { | |
placePattern(lightweightSpaceshipPattern, x, y); | |
} | |
drawGrid(grid); | |
} | |
} | |
// Definition of patterns | |
const gliderGunPattern = [ | |
[0, 4], [1, 4], [1, 5], [0, 5], [10, 4], [10, 5], [10, 6], | |
[11, 3], [11, 7], [12, 2], [12, 8], [13, 2], [13, 8], [14, 5], | |
[15, 3], [15, 7], [16, 4], [16, 5], [16, 6], [17, 5], [20, 2], | |
[20, 3], [20, 4], [21, 2], [21, 3], [21, 4], [22, 1], [22, 5], | |
[24, 0], [24, 1], [24, 5], [24, 6], [34, 2], [34, 3], [35, 2], | |
[35, 3] | |
]; | |
const pufferTrainPattern = [ | |
[0, 0], [1, 1], [1, 2], [2, 2], [2, 3], [3, 3], [4, 3], | |
[5, 2], [5, 1], [6, 1], [6, 0], [7, 0], [8, 0], [9, 0] | |
]; | |
const gliderPattern = [ | |
[0, 1], [1, 2], [2, 0], [2, 1], [2, 2] | |
]; | |
const lightweightSpaceshipPattern = [ | |
[0, 1], [0, 4], [1, 0], [2, 0], [3, 0], [3, 4], [4, 0], | |
[4, 1], [4, 2], [4, 3] | |
]; | |
// Initial drawing of the grid | |
drawGrid(grid); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment