import React, { useState, useRef } from 'react';
import { Canvas, useFrame } from '@react-three/fiber';
import { OrbitControls, Float, Html } from '@react-three/drei';

// Simple 3D X Component
function XMark({ position }) {
  const groupRef = useRef();

  useFrame((state) => {
    if (groupRef.current) {
      groupRef.current.rotation.y = Math.sin(state.clock.elapsedTime) * 0.1;
    }
  });

  return (
    <group ref={groupRef} position={position}>
      <Float speed={2} rotationIntensity={0.5} floatIntensity={0.2}>
        <group>
          {/* First line of X */}
          <mesh rotation={[0, 0, Math.PI / 4]}>
            <boxGeometry args={[1.5, 0.2, 0.2]} />
            <meshStandardMaterial color="#ff6b6b" />
          </mesh>
          {/* Second line of X */}
          <mesh rotation={[0, 0, -Math.PI / 4]}>
            <boxGeometry args={[1.5, 0.2, 0.2]} />
            <meshStandardMaterial color="#ff6b6b" />
          </mesh>
        </group>
      </Float>
    </group>
  );
}

// Simple 3D O Component using cylinders
function OMark({ position }) {
  const groupRef = useRef();

  useFrame((state) => {
    if (groupRef.current) {
      groupRef.current.rotation.x = Math.sin(state.clock.elapsedTime * 0.5) * 0.1;
      groupRef.current.rotation.z = Math.cos(state.clock.elapsedTime * 0.3) * 0.1;
    }
  });

  return (
    <group ref={groupRef} position={position}>
      <Float speed={1.5} rotationIntensity={0.3} floatIntensity={0.3}>
        <group scale={1}>
          {/* Create O using multiple small cylinders in a circle */}
          {Array.from({ length: 12 }, (_, i) => {
            const angle = (i / 12) * Math.PI * 2;
            const x = Math.cos(angle) * 0.7;
            const y = Math.sin(angle) * 0.7;
            return (
              <mesh key={i} position={[x, y, 0]} rotation={[0, 0, angle]}>
                <cylinderGeometry args={[0.08, 0.08, 0.3]} />
                <meshStandardMaterial color="#4ecdc4" />
              </mesh>
            );
          })}
        </group>
      </Float>
    </group>
  );
}

// Simple cube for testing
function TestCube() {
  const meshRef = useRef();

  useFrame((state) => {
    if (meshRef.current) {
      meshRef.current.rotation.x = state.clock.elapsedTime;
      meshRef.current.rotation.y = state.clock.elapsedTime * 0.5;
    }
  });

  return (
    <mesh ref={meshRef} position={[4, 0, 0]}>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color="orange" />
    </mesh>
  );
}

// Game Board Component
function GameBoard({ board, onCellClick, winningLine }) {
  const positions = [
    [-2, 2, 0], [0, 2, 0], [2, 2, 0],
    [-2, 0, 0], [0, 0, 0], [2, 0, 0],
    [-2, -2, 0], [0, -2, 0], [2, -2, 0]
  ];

  return (
    <group>
      {/* Grid lines */}
      <group>
        {/* Vertical lines */}
        <mesh position={[-1, 0, -0.1]}>
          <boxGeometry args={[0.1, 6, 0.1]} />
          <meshStandardMaterial color="#666" />
        </mesh>
        <mesh position={[1, 0, -0.1]}>
          <boxGeometry args={[0.1, 6, 0.1]} />
          <meshStandardMaterial color="#666" />
        </mesh>
        {/* Horizontal lines */}
        <mesh position={[0, 1, -0.1]}>
          <boxGeometry args={[6, 0.1, 0.1]} />
          <meshStandardMaterial color="#666" />
        </mesh>
        <mesh position={[0, -1, -0.1]}>
          <boxGeometry args={[6, 0.1, 0.1]} />
          <meshStandardMaterial color="#666" />
        </mesh>
      </group>

      {/* Clickable cells */}
      {positions.map((position, index) => (
        <mesh
          key={index}
          position={position}
          onClick={() => onCellClick(index)}
          onPointerOver={(e) => {
            if (!board[index]) {
              e.object.material.color.setHex(0x555555);
              document.body.style.cursor = 'pointer';
            }
          }}
          onPointerOut={(e) => {
            e.object.material.color.setHex(0x333333);
            document.body.style.cursor = 'default';
          }}
        >
          <planeGeometry args={[1.8, 1.8]} />
          <meshStandardMaterial
            color="#333"
            transparent
            opacity={0.3}
          />
        </mesh>
      ))}

      {/* Render X's and O's */}
      {board.map((cell, index) => {
        if (cell === 'X') {
          return <XMark key={`x-${index}`} position={positions[index]} />;
        } else if (cell === 'O') {
          return <OMark key={`o-${index}`} position={positions[index]} />;
        }
        return null;
      })}

      {/* Winning line highlight */}
      {winningLine && (
        <group>
          {winningLine.map((index) => (
            <mesh key={`highlight-${index}`} position={[...positions[index].slice(0, 2), 0.2]}>
              <planeGeometry args={[1.9, 1.9]} />
              <meshStandardMaterial
                color="#ffd93d"
                transparent
                opacity={0.5}
              />
            </mesh>
          ))}
        </group>
      )}
    </group>
  );
}

// Main Game Component
export default function TicTacToe3D() {
  const [board, setBoard] = useState(Array(9).fill(null));
  const [isXNext, setIsXNext] = useState(true);
  const [winner, setWinner] = useState(null);
  const [winningLine, setWinningLine] = useState(null);

  const checkWinner = (squares) => {
    const lines = [
      [0, 1, 2], [3, 4, 5], [6, 7, 8], // rows
      [0, 3, 6], [1, 4, 7], [2, 5, 8], // columns
      [0, 4, 8], [2, 4, 6] // diagonals
    ];

    for (let i = 0; i < lines.length; i++) {
      const [a, b, c] = lines[i];
      if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
        return { winner: squares[a], line: lines[i] };
      }
    }
    return null;
  };

  const handleCellClick = (index) => {
    if (board[index] || winner) return;

    const newBoard = [...board];
    newBoard[index] = isXNext ? 'X' : 'O';
    setBoard(newBoard);

    const result = checkWinner(newBoard);
    if (result) {
      setWinner(result.winner);
      setWinningLine(result.line);
    } else {
      setIsXNext(!isXNext);
    }
  };

  const resetGame = () => {
    setBoard(Array(9).fill(null));
    setIsXNext(true);
    setWinner(null);
    setWinningLine(null);
  };

  const isDraw = !winner && board.every(cell => cell !== null);

  const Header = ({ }) => (
    <div className="text-center py-6 text-white w-64 absolute top-2 left-2">
      <h1 className="text-4xl font-bold mb-4 bg-gradient-to-r from-pink-400 to-purple-400 bg-clip-text text-transparent">
        3D Tic Tac Toe
      </h1>
      <div className="text-xl">
        {winner ? (
          <div className="text-yellow-300 font-semibold">
            🎉 Player {winner} Wins! 🎉
          </div>
        ) : isDraw ? (
          <div className="text-orange-300 font-semibold">It&apos;s a Draw!</div>
        ) : (
          <div>
            Next Player: <span className={isXNext ? 'text-red-400' : 'text-teal-400'}>
              {isXNext ? 'X' : 'O'}
            </span>
          </div>
        )}
      </div>
    </div>
  );

  return (
    <div className="w-full h-screen bg-gradient-to-br from-purple-900 via-blue-900 to-indigo-900 flex flex-col">
      <Header />

      {/* 3D Game */}
      <div className="flex-1 relative">
        <Canvas camera={{ position: [0, 0, 10], fov: 50 }} style={{ background: 'linear-gradient(135deg, #1a1a2e, #16213e)' }}        >
          {/* Lighting */}
          <ambientLight intensity={0.6} />
          <pointLight position={[10, 10, 10]} intensity={1} />
          <pointLight position={[-10, -10, 5]} intensity={0.5} color="#4ecdc4" />

          {/* Game board */}
          <GameBoard board={board} onCellClick={handleCellClick} winningLine={winningLine} />

          {/* Camera controls */}
          <OrbitControls
            enablePan={false}
            enableZoom={true}
            maxPolarAngle={Math.PI / 2}
            minPolarAngle={Math.PI / 6}
            autoRotate={winner || isDraw}
            autoRotateSpeed={2}
          />
        </Canvas>

        {/* Debug info */}
        <div className="absolute top-4 left-4 text-white text-sm bg-black bg-opacity-50 p-2 rounded">
          <div>Canvas Status: Active</div>
          <div>Game State: {winner ? `Winner: ${winner}` : isDraw ? 'Draw' : 'Playing'}</div>
          <div>Next: {isXNext ? 'X' : 'O'}</div>
        </div>
      </div>

      {/* Controls */}
      <div className="text-center pb-6">
        <button
          onClick={resetGame}
          className="px-8 py-3 bg-gradient-to-r from-pink-500 to-purple-600 text-white font-semibold rounded-lg shadow-lg hover:from-pink-600 hover:to-purple-700 transform hover:scale-105 transition-all duration-200"
        >
          New Game
        </button>
        <p className="text-gray-300 text-sm mt-3">
          Click cells to play • Drag to rotate • Scroll to zoom
        </p>
      </div>
    </div>
  );
}

Comments (0)

Loading comments...