Claude 3.7 Sonnetのコーディング能力を試す 9


以前の投稿でClaude 3.7 Sonnetのコーディング能力を試した.

今回は引き続きReactを使ってコードを書いてもらいEden成長モデルのシミュレーションを行ってみた.

すると,今回も完璧なシミュレーションを出してくれた.有名なシミュレーションは一通り動きそうだ.

境界面の成長モデルであるEdenモデルのシミュレーションを行うコードを書いて. 
Reactで動的に処理できるようにして. 
エラーが出ないように自己点検して.
import { useState, useEffect, useRef } from 'react';

export default function EdenModelSimulation() {
  const [gridSize, setGridSize] = useState({ width: 100, height: 100 });
  const [cellSize, setCellSize] = useState(5);
  const [speed, setSpeed] = useState(10);
  const [isRunning, setIsRunning] = useState(false);
  const [resetTrigger, setResetTrigger] = useState(0);
  
  const canvasRef = useRef(null);
  const simulationRef = useRef(null);
  const gridRef = useRef(null);
  
  // グリッドの初期化
  useEffect(() => {
    // 初期状態を設定
    const grid = Array(gridSize.height).fill().map(() => Array(gridSize.width).fill(0));
    
    // 最下行を埋める(種となる部分)
    for (let x = 0; x < gridSize.width; x++) {
      grid[gridSize.height - 1][x] = 1;
    }
    
    gridRef.current = grid;
    
    // キャンバスに描画
    drawGrid();
  }, [gridSize, resetTrigger]);
  
  // キャンバスへの描画
  const drawGrid = () => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    
    const ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    
    if (!gridRef.current) return;
    
    for (let y = 0; y < gridSize.height; y++) {
      for (let x = 0; x < gridSize.width; x++) {
        if (gridRef.current[y][x] === 1) {
          ctx.fillStyle = '#2563eb'; // 青色で塗りつぶし
          ctx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize);
        }
      }
    }
  };
  
  // 成長プロセスの更新
  const updateEdenModel = () => {
    const grid = gridRef.current;
    if (!grid) return false;
    
    // 成長可能部分(既存の粒子に隣接する空セル)を見つける
    const growthSites = [];
    for (let y = 0; y < gridSize.height; y++) {
      for (let x = 0; x < gridSize.width; x++) {
        if (grid[y][x] === 0 && hasOccupiedNeighbor(grid, x, y)) {
          growthSites.push({ x, y });
        }
      }
    }
    
    // 成長可能部分がなければシミュレーション終了
    if (growthSites.length === 0) {
      return false;
    }
    
    // ランダムに1つ選んで成長させる
    const randomSite = growthSites[Math.floor(Math.random() * growthSites.length)];
    grid[randomSite.y][randomSite.x] = 1;
    
    return true;
  };
  
  // 隣接するセルが占有されているかチェック
  const hasOccupiedNeighbor = (grid, x, y) => {
    const directions = [
      { dx: -1, dy: 0 }, // 左
      { dx: 1, dy: 0 },  // 右
      { dx: 0, dy: -1 }, // 上
      { dx: 0, dy: 1 }   // 下
    ];
    
    for (const dir of directions) {
      const nx = x + dir.dx;
      const ny = y + dir.dy;
      
      if (nx >= 0 && nx < gridSize.width && ny >= 0 && ny < gridSize.height) {
        if (grid[ny][nx] === 1) {
          return true;
        }
      }
    }
    return false;
  };
  
  // シミュレーションのステップ実行
  const runSimulationStep = () => {
    const canContinue = updateEdenModel();
    drawGrid();
    return canContinue;
  };
  
  // シミュレーションの開始/停止
  useEffect(() => {
    if (isRunning) {
      simulationRef.current = setInterval(() => {
        const canContinue = runSimulationStep();
        if (!canContinue) {
          setIsRunning(false);
        }
      }, 1000 / speed);
    } else {
      clearInterval(simulationRef.current);
    }
    
    return () => {
      clearInterval(simulationRef.current);
    };
  }, [isRunning, speed]);
  
  // リセットボタンの処理
  const handleReset = () => {
    setIsRunning(false);
    setResetTrigger(prev => prev + 1);
  };
  
  // マニュアルステップ実行の処理
  const handleStep = () => {
    if (!isRunning) {
      runSimulationStep();
    }
  };
  
  return (
    <div className="flex flex-col items-center p-4 bg-gray-100 rounded-lg">
      <h1 className="text-2xl font-bold mb-4">Edenモデルシミュレーション</h1>
      
      <div className="mb-4 p-2 border border-gray-300 bg-white rounded">
        <canvas 
          ref={canvasRef} 
          width={gridSize.width * cellSize} 
          height={gridSize.height * cellSize}
          className="border border-gray-400"
        />
      </div>
      
      <div className="flex flex-wrap gap-4 mb-4">
        <div className="flex flex-col">
          <label className="text-sm font-medium mb-1">速度</label>
          <input 
            type="range" 
            min="1" 
            max="100" 
            value={speed} 
            onChange={(e) => setSpeed(parseInt(e.target.value))} 
            className="w-32"
          />
          <span className="text-xs mt-1">{speed} ステップ/秒</span>
        </div>
        
        <div className="flex flex-col">
          <label className="text-sm font-medium mb-1">セルサイズ</label>
          <select 
            value={cellSize} 
            onChange={(e) => setCellSize(parseInt(e.target.value))}
            className="border border-gray-300 rounded p-1"
          >
            <option value="2">小 (2px)</option>
            <option value="5">中 (5px)</option>
            <option value="10">大 (10px)</option>
          </select>
        </div>
        
        <div className="flex flex-col">
          <label className="text-sm font-medium mb-1">グリッドサイズ</label>
          <select 
            value={`${gridSize.width}x${gridSize.height}`} 
            onChange={(e) => {
              const [width, height] = e.target.value.split('x').map(Number);
              setGridSize({ width, height });
            }}
            className="border border-gray-300 rounded p-1"
          >
            <option value="50x50">小 (50x50)</option>
            <option value="100x100">中 (100x100)</option>
            <option value="200x100">大 (200x100)</option>
          </select>
        </div>
      </div>
      
      <div className="flex gap-2">
        <button 
          onClick={() => setIsRunning(!isRunning)} 
          className={`px-4 py-2 rounded font-medium ${isRunning ? 'bg-red-500 text-white' : 'bg-green-500 text-white'}`}
        >
          {isRunning ? '停止' : '開始'}
        </button>
        
        <button 
          onClick={handleStep} 
          disabled={isRunning} 
          className={`px-4 py-2 rounded font-medium ${isRunning ? 'bg-gray-300 cursor-not-allowed' : 'bg-blue-500 text-white'}`}
        >
          1ステップ
        </button>
        
        <button 
          onClick={handleReset} 
          className="px-4 py-2 bg-gray-500 text-white rounded font-medium"
        >
          リセット
        </button>
      </div>
      
      <div className="mt-4 text-sm text-gray-600">
        <p>Edenモデル: ランダムな選択による境界面成長のシミュレーション</p>
        <p>青色のセルは既に成長した部分を示します</p>
      </div>
    </div>
  );
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です