import React, { useState, useCallback, useRef, useEffect } from 'react'; import { Play, Pause, FastForward, RotateCcw, Shuffle, Trash2, Info } from 'lucide-react'; // 初始网格大小 const numRows = 30; const numCols = 30; // 邻居的坐标偏移量 (上、下、左、右、左上、右上、左下、右下) const operations = [ [0, 1], [0, -1], [1, -1], [-1, 1], [1, 1], [-1, -1], [1, 0], [-1, 0] ]; const generateEmptyGrid = () => { const rows = []; for (let i = 0; i < numRows; i++) { rows.push(Array.from(Array(numCols), () => 0)); } return rows; }; const App = () => { const [grid, setGrid] = useState(() => generateEmptyGrid()); const [running, setRunning] = useState(false); const [generation, setGeneration] = useState(0); const [speed, setSpeed] = useState(100); // 毫秒 const runningRef = useRef(running); runningRef.current = running; // 核心逻辑:计算下一代 const runSimulation = useCallback(() => { if (!runningRef.current) { return; } setGrid((g) => { // 深拷贝当前网格 (类似于我们之前的 Python 练习,不能直接修改原图) const gridCopy = JSON.parse(JSON.stringify(g)); for (let i = 0; i < numRows; i++) { for (let j = 0; j < numCols; j++) { let neighbors = 0; // 检查8个邻居 operations.forEach(([x, y]) => { const newI = i + x; const newJ = j + y; // 边界检查:确保没有越界 (类似于 x >= 0 and x < n) if (newI >= 0 && newI < numRows && newJ >= 0 && newJ < numCols) { neighbors += g[newI][newJ]; } }); // 康威生命游戏规则 if (neighbors < 2 || neighbors > 3) { gridCopy[i][j] = 0; // 死亡 (人口过少或过多) } else if (g[i][j] === 0 && neighbors === 3) { gridCopy[i][j] = 1; // 复活 (繁殖) } // neighbors === 2 || neighbors === 3 时,活细胞保持存活,无需改变 } } return gridCopy; }); setGeneration((gen) => gen + 1); setTimeout(runSimulation, speed); }, [speed]); // 开始/暂停 处理 const toggleRunning = () => { setRunning(!running); if (!running) { runningRef.current = true; runSimulation(); } }; // 单步执行 const stepForward = () => { setRunning(false); runningRef.current = true; // 临时开启以便执行一次逻辑 setGrid((g) => { const gridCopy = JSON.parse(JSON.stringify(g)); for (let i = 0; i < numRows; i++) { for (let j = 0; j < numCols; j++) { let neighbors = 0; operations.forEach(([x, y]) => { const newI = i + x; const newJ = j + y; if (newI >= 0 && newI < numRows && newJ >= 0 && newJ < numCols) { neighbors += g[newI][newJ]; } }); if (neighbors < 2 || neighbors > 3) { gridCopy[i][j] = 0; } else if (g[i][j] === 0 && neighbors === 3) { gridCopy[i][j] = 1; } } } return gridCopy; }); setGeneration((gen) => gen + 1); runningRef.current = false; // 执行完立刻关闭 }; // 随机生成 const randomize = () => { const rows = []; for (let i = 0; i < numRows; i++) { rows.push(Array.from(Array(numCols), () => (Math.random() > 0.7 ? 1 : 0))); } setGrid(rows); setGeneration(0); }; // 清空 const clearGrid = () => { setGrid(generateEmptyGrid()); setGeneration(0); setRunning(false); }; return (

康威生命游戏

Interactive Game of Life

{/* 控制面板 */}
速度 setSpeed(1000 - Number(e.target.value))} className="w-24 h-2 bg-slate-600 rounded-lg appearance-none cursor-pointer accent-green-500" />
{/* 统计信息 */}
{generation}
{/* 游戏网格 */}
{grid.map((rows, i) => rows.map((col, j) => (
{ const newGrid = JSON.parse(JSON.stringify(grid)); newGrid[i][j] = grid[i][j] ? 0 : 1; setGrid(newGrid); }} // 鼠标拖动绘制逻辑可以更复杂,这里仅支持点击 className={` transition-colors duration-100 ease-in-out cursor-pointer ${grid[i][j] ? 'bg-green-500 shadow-[0_0_8px_rgba(34,197,94,0.6)]' : 'bg-slate-900 hover:bg-slate-800'} `} /> )) )}
{/* 规则说明 */}

演化规则 (Rules)

  • 死亡 如果周围活细胞少于 2 个(孤独)或多于 3 个(拥挤),当前细胞死亡。
  • 存活 如果周围活细胞正好是 2 个或 3 个,当前活细胞继续存活。
  • 繁殖 如果一个死细胞周围正好有 3 个活细胞,它会变成活细胞。
编程提示:这正是你刚刚练习的“遍历二维数组”和“检查周围邻居”算法的可视化表现。
); }; export default App;