anycoder-f6f6087d / index.html
Ivanhoe9's picture
Upload folder using huggingface_hub
d78fa94 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Conway's Game of Life - Built with anycoder</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary: #4a6fa5;
--secondary: #166088;
--accent: #4fc3f7;
--dark: #1a2a3a;
--light: #f8f9fa;
--success: #4caf50;
--danger: #f44336;
--shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
--transition: all 0.3s ease;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: var(--light);
color: var(--dark);
line-height: 1.6;
padding: 20px;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
}
header {
width: 100%;
max-width: 1200px;
margin-bottom: 20px;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 15px;
}
.logo {
font-size: 1.8rem;
font-weight: 700;
color: var(--primary);
text-decoration: none;
display: flex;
align-items: center;
gap: 10px;
}
.logo i {
color: var(--accent);
}
.anycoder-link {
color: var(--secondary);
text-decoration: none;
font-size: 0.9rem;
font-weight: 500;
transition: var(--transition);
}
.anycoder-link:hover {
color: var(--accent);
text-decoration: underline;
}
.controls {
width: 100%;
max-width: 1200px;
background-color: white;
border-radius: 12px;
padding: 20px;
box-shadow: var(--shadow);
margin-bottom: 20px;
display: flex;
flex-wrap: wrap;
gap: 15px;
justify-content: center;
align-items: center;
}
.control-group {
display: flex;
flex-direction: column;
gap: 8px;
}
.control-group label {
font-weight: 600;
font-size: 0.9rem;
color: var(--dark);
}
button, select, input {
padding: 10px 15px;
border-radius: 8px;
border: 1px solid #ddd;
background-color: white;
font-family: inherit;
font-size: 1rem;
cursor: pointer;
transition: var(--transition);
}
button {
background-color: var(--primary);
color: white;
border: none;
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
}
button:hover {
background-color: var(--secondary);
transform: translateY(-2px);
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
transform: none;
}
select, input {
width: 100%;
max-width: 200px;
}
select:focus, input:focus {
outline: 2px solid var(--accent);
border-color: var(--accent);
}
.game-container {
width: 100%;
max-width: 1200px;
background-color: white;
border-radius: 12px;
padding: 20px;
box-shadow: var(--shadow);
display: flex;
flex-direction: column;
align-items: center;
}
.grid-container {
width: 100%;
aspect-ratio: 1 / 1;
max-width: 800px;
display: grid;
grid-template-columns: repeat(var(--cols), 1fr);
gap: 1px;
background-color: #e0e0e0;
border-radius: 8px;
overflow: hidden;
margin: 20px 0;
touch-action: none;
}
.cell {
background-color: white;
aspect-ratio: 1 / 1;
transition: background-color 0.1s ease;
}
.cell.alive {
background-color: var(--primary);
}
.stats {
width: 100%;
display: flex;
justify-content: space-around;
flex-wrap: wrap;
gap: 15px;
margin-top: 10px;
}
.stat {
background-color: rgba(74, 111, 165, 0.1);
padding: 10px 15px;
border-radius: 8px;
font-weight: 600;
color: var(--primary);
}
.stat span {
color: var(--secondary);
margin-left: 5px;
}
.presets {
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: center;
margin-top: 15px;
}
.preset-btn {
background-color: var(--light);
color: var(--dark);
border: 1px solid #ddd;
}
.preset-btn:hover {
background-color: var(--accent);
color: white;
border-color: var(--accent);
}
footer {
margin-top: 20px;
text-align: center;
color: #666;
font-size: 0.9rem;
}
footer a {
color: var(--primary);
text-decoration: none;
font-weight: 600;
}
footer a:hover {
text-decoration: underline;
}
@media (max-width: 768px) {
.controls {
flex-direction: column;
align-items: stretch;
}
.control-group {
width: 100%;
}
.grid-container {
max-width: 100%;
}
}
@media (max-width: 480px) {
body {
padding: 10px;
}
header {
flex-direction: column;
align-items: flex-start;
}
.stats {
flex-direction: column;
align-items: center;
}
}
</style>
</head>
<body>
<header>
<a href="#" class="logo">
<i class="fas fa-gamepad"></i>
<span>Game of Life</span>
</a>
<a href="https://huggingface.co/spaces/akhaliq/anycoder" class="anycoder-link" target="_blank">Built with anycoder</a>
</header>
<div class="controls">
<div class="control-group">
<label for="grid-size">Grid Size</label>
<select id="grid-size">
<option value="20">20x20</option>
<option value="30" selected>30x30</option>
<option value="40">40x40</option>
<option value="50">50x50</option>
</select>
</div>
<div class="control-group">
<label for="speed">Speed (ms)</label>
<input type="range" id="speed" min="50" max="1000" value="200">
</div>
<button id="start-btn">
<i class="fas fa-play"></i>
<span>Start</span>
</button>
<button id="stop-btn" disabled>
<i class="fas fa-stop"></i>
<span>Stop</span>
</button>
<button id="clear-btn">
<i class="fas fa-trash"></i>
<span>Clear</span>
</button>
<button id="random-btn">
<i class="fas fa-random"></i>
<span>Random</span>
</button>
</div>
<div class="game-container">
<div class="grid-container" id="grid"></div>
<div class="stats">
<div class="stat">Generation: <span id="generation">0</span></div>
<div class="stat">Population: <span id="population">0</span></div>
<div class="stat">Status: <span id="status">Stopped</span></div>
</div>
<div class="presets">
<button class="preset-btn" data-preset="glider">Glider</button>
<button class="preset-btn" data-preset="pulsar">Pulsar</button>
<button class="preset-btn" data-preset="spaceship">Spaceship</button>
<button class="preset-btn" data-preset="beacon">Beacon</button>
</div>
</div>
<footer>
<p>Conway's Game of Life - A cellular automaton devised by mathematician John Conway.</p>
<p>Rules: 1. Any live cell with fewer than two live neighbors dies (underpopulation). 2. Any live cell with two or three live neighbors lives on. 3. Any live cell with more than three live neighbors dies (overpopulation). 4. Any dead cell with exactly three live neighbors becomes a live cell (reproduction).</p>
</footer>
<script>
document.addEventListener('DOMContentLoaded', () => {
// DOM Elements
const gridContainer = document.getElementById('grid');
const startBtn = document.getElementById('start-btn');
const stopBtn = document.getElementById('stop-btn');
const clearBtn = document.getElementById('clear-btn');
const randomBtn = document.getElementById('random-btn');
const gridSizeSelect = document.getElementById('grid-size');
const speedInput = document.getElementById('speed');
const generationSpan = document.getElementById('generation');
const populationSpan = document.getElementById('population');
const statusSpan = document.getElementById('status');
const presetButtons = document.querySelectorAll('.preset-btn');
// Game state
let grid = [];
let rows = 30;
let cols = 30;
let isRunning = false;
let generation = 0;
let animationId = null;
let speed = 200;
let isDrawing = false;
let isErasing = false;
// Initialize the game
initGame();
// Event Listeners
startBtn.addEventListener('click', startGame);
stopBtn.addEventListener('click', stopGame);
clearBtn.addEventListener('click', clearGrid);
randomBtn.addEventListener('click', randomizeGrid);
gridSizeSelect.addEventListener('change', changeGridSize);
speedInput.addEventListener('input', updateSpeed);
// Grid interaction
gridContainer.addEventListener('mousedown', startDrawing);
gridContainer.addEventListener('mouseup', stopDrawing);
gridContainer.addEventListener('mouseleave', stopDrawing);
gridContainer.addEventListener('mousemove', drawCell);
// Touch support
gridContainer.addEventListener('touchstart', handleTouchStart);
gridContainer.addEventListener('touchend', stopDrawing);
gridContainer.addEventListener('touchmove', handleTouchMove);
// Preset patterns
presetButtons.forEach(button => {
button.addEventListener('click', () => {
const preset = button.getAttribute('data-preset');
loadPreset(preset);
});
});
// Initialize the game grid
function initGame() {
createGrid();
updateStats();
}
// Create the grid
function createGrid() {
gridContainer.style.setProperty('--cols', cols);
gridContainer.innerHTML = '';
grid = Array(rows).fill().map(() => Array(cols).fill(false));
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
const cell = document.createElement('div');
cell.className = 'cell';
cell.dataset.row = row;
cell.dataset.col = col;
cell.addEventListener('click', toggleCell);
gridContainer.appendChild(cell);
}
}
}
// Change grid size
function changeGridSize() {
const size = parseInt(gridSizeSelect.value);
rows = size;
cols = size;
generation = 0;
stopGame();
createGrid();
updateStats();
}
// Update simulation speed
function updateSpeed() {
speed = parseInt(speedInput.value);
if (isRunning) {
stopGame();
startGame();
}
}
// Start the game
function startGame() {
if (isRunning) return;
isRunning = true;
startBtn.disabled = true;
stopBtn.disabled = false;
statusSpan.textContent = 'Running';
runSimulation();
}
// Stop the game
function stopGame() {
isRunning = false;
startBtn.disabled = false;
stopBtn.disabled = true;
statusSpan.textContent = 'Stopped';
if (animationId) {
cancelAnimationFrame(animationId);
animationId = null;
}
}
// Clear the grid
function clearGrid() {
stopGame();
grid.forEach(row => row.fill(false));
updateGridDisplay();
generation = 0;
updateStats();
}
// Randomize the grid
function randomizeGrid() {
stopGame();
grid = grid.map(row => row.map(() => Math.random() > 0.7));
updateGridDisplay();
generation = 0;
updateStats();
}
// Run the simulation
function runSimulation() {
if (!isRunning) return;
const newGrid = JSON.parse(JSON.stringify(grid));
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
const neighbors = countNeighbors(row, col);
// Apply Conway's rules
if (grid[row][col]) {
// Cell is alive
if (neighbors < 2 || neighbors > 3) {
newGrid[row][col] = false; // Dies
}
} else {
// Cell is dead
if (neighbors === 3) {
newGrid[row][col] = true; // Becomes alive
}
}
}
}
grid = newGrid;
generation++;
updateGridDisplay();
updateStats();
animationId = setTimeout(() => runSimulation(), speed);
}
// Count live neighbors
function 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; // Skip self
const newRow = row + i;
const newCol = col + j;
if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols) {
if (grid[newRow][newCol]) {
count++;
}
}
}
}
return count;
}
// Update the grid display
function updateGridDisplay() {
const cells = gridContainer.querySelectorAll('.cell');
cells.forEach(cell => {
const row = parseInt(cell.dataset.row);
const col = parseInt(cell.dataset.col);
if (grid[row][col]) {
cell.classList.add('alive');
} else {
cell.classList.remove('alive');
}
});
}
// Update statistics
function updateStats() {
generationSpan.textContent = generation;
let population = 0;
grid.forEach(row => {
row.forEach(cell => {
if (cell) population++;
});
});
populationSpan.textContent = population;
}
// Toggle cell state
function toggleCell(e) {
if (e.target.classList.contains('cell')) {
const row = parseInt(e.target.dataset.row);
const col = parseInt(e.target.dataset.col);
grid[row][col] = !grid[row][col];
e.target.classList.toggle('alive');
updateStats();
}
}
// Start drawing
function startDrawing(e) {
if (e.target.classList.contains('cell')) {
isDrawing = true;
isErasing = e.target.classList.contains('alive');
toggleCell(e);
}
}
// Stop drawing
function stopDrawing() {
isDrawing = false;
}
// Draw cells
function drawCell(e) {
if (!isDrawing) return;
e.preventDefault();
if (e.target.classList.contains('cell')) {
const row = parseInt(e.target.dataset.row);
const col = parseInt(e.target.dataset.col);
if (isErasing) {
if (grid[row][col]) {
grid[row][col] = false;
e.target.classList.remove('alive');
updateStats();
}
} else {
if (!grid[row][col]) {
grid[row][col] = true;
e.target.classList.add('alive');
updateStats();
}
}
}
}
// Touch support
function handleTouchStart(e) {
e.preventDefault();
const touch = e.touches[0];
const element = document.elementFromPoint(touch.clientX, touch.clientY);
if (element && element.classList.contains('cell')) {
isDrawing = true;
isErasing = element.classList.contains('alive');
toggleCell({ target: element });
}
}
function handleTouchMove(e) {
e.preventDefault();
if (!isDrawing) return;
const touch = e.touches[0];
const element = document.elementFromPoint(touch.clientX, touch.clientY);
if (element && element.classList.contains('cell')) {
drawCell({ target: element, preventDefault: () => {} });
}
}
// Load preset patterns
function loadPreset(preset) {
stopGame();
clearGrid();
switch(preset) {
case 'glider':
// Glider pattern
if (rows >= 3 && cols >= 3) {
grid[1][2] = true;
grid[2][3] = true;
grid[3][1] = true;
grid[3][2] = true;
grid[3][3] = true;
}
break;
case 'pulsar':
// Pulsar pattern (simplified)
if (rows >= 15 && cols >= 15) {
const centerRow = Math.floor(rows / 2);
const centerCol = Math.floor(cols / 2);
// Top left block
grid[centerRow-2][centerCol-4] = true;
grid[centerRow-2][centerCol-3] = true;
grid[centerRow-2][centerCol-2] = true;
grid[centerRow-1][centerCol-6] = true;
grid[centerRow-1][centerCol-1] = true;
grid[centerRow][centerCol-6] = true;
grid[centerRow][centerCol-1] = true;
grid[centerRow+1][centerCol-6] = true;
grid[centerRow+1][centerCol-1] = true;
grid[centerRow+2][centerCol-4] = true;
grid[centerRow+2][centerCol-3] = true;
grid[centerRow+2][centerCol-2] = true;
// Top right block
grid[centerRow-2][centerCol+2] = true;
grid[centerRow-2][centerCol+3] = true;
grid[centerRow-2][centerCol+4] = true;
grid[centerRow-1][centerCol+1] = true;
grid[centerRow-1][centerCol+6] = true;
grid[centerRow][centerCol+1] = true;
grid[centerRow][centerCol+6] = true;
grid[centerRow+1][centerCol+1] = true;
grid[centerRow+1][centerCol+6] = true;
grid[centerRow+2][centerCol+2] = true;
grid[centerRow+2][centerCol+3] = true;
grid[centerRow+2][centerCol+4] = true;
// Bottom left block
grid[centerRow+4][centerCol-4] = true;
grid[centerRow+4][centerCol-3] = true;
grid[centerRow+4][centerCol-2] = true;
grid[centerRow+5][centerCol-6] = true;
grid[centerRow+5][centerCol-1] = true;
grid[centerRow+6][centerCol-6] = true;
grid[centerRow+6][centerCol-1] = true;
grid[centerRow+7][centerCol-6] = true;
grid[centerRow+7][centerCol-1] = true;
grid[centerRow+8][centerCol-4] = true;
grid[centerRow+8][centerCol-3] = true;
grid[centerRow+8][centerCol-2] = true;
// Bottom right block
grid[centerRow+4][centerCol+2] = true;
grid[centerRow+4][centerCol+3] = true;
grid[centerRow+4][centerCol+4] = true;
grid[centerRow+5][centerCol+1] = true;
grid[centerRow+5][centerCol+6] = true;
grid[centerRow+6][centerCol+1] = true;
grid[centerRow+6][centerCol+6] = true;
grid[centerRow+7][centerCol+1] = true;
grid[centerRow+7][centerCol+6] = true;
grid[centerRow+8][centerCol+2] = true;
grid[centerRow+8][centerCol+3] = true;
grid[centerRow+8][centerCol+4] = true;
}
break;
case 'spaceship':
// Lightweight spaceship
if (rows >= 5 && cols >= 5) {
const centerRow = Math.floor(rows / 2);
const centerCol = Math.floor(cols / 2);
grid[centerRow][centerCol+1] = true;
grid[centerRow][centerCol+4] = true;
grid[centerRow+1][centerCol+4] = true;
grid[centerRow+2][centerCol] = true;
grid[centerRow+2][centerCol+4] = true;
grid[centerRow+3][centerCol+1] = true;
grid[centerRow+3][centerCol+2] = true;
grid[centerRow+3][centerCol+3] = true;
grid[centerRow+3][centerCol+4] = true;
}
break;
case 'beacon':
// Beacon pattern
if (rows >= 4 && cols >= 4) {
const centerRow = Math.floor(rows / 2);
const centerCol = Math.floor(cols / 2);
grid[centerRow][centerCol] = true;
grid[centerRow][centerCol+1] = true;
grid[centerRow+1][centerCol] = true;
grid[centerRow+1][centerCol+1] = true;
grid[centerRow+2][centerCol+2] = true;
grid[centerRow+2][centerCol+3] = true;
grid[centerRow+3][centerCol+2] = true;
grid[centerRow+3][centerCol+3] = true;
}
break;
}
updateGridDisplay();
updateStats();
}
});
</script>
</body>
</html>