Fix this code make it so that I can also l also control with wasd: <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Green Snake Game with 3 Apples</title>
<style>
  body {
    background: #111;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    user-select: none;
    font-family: sans-serif;
    color: #eee;
  }
  canvas {
    background: #222;
    display: block;
    border: 2px solid #0f0;
    border-radius: 8px;
  }
  .info {
    position: absolute;
    top: 10px;
    left: 50%;
    transform: translateX(-50%);
    color: #0f0;
    font-weight: bold;
  }
</style>
</head>
<body>
  <div class="info">Use arrow keys to control the green snake. Eat apples! (Up to 3 apples on screen)</div>
  <canvas id="game" width="400" height="400"></canvas>

<script>
(() => {
  const canvas = document.getElementById('game');
  const ctx = canvas.getContext('2d');

  const gridSize = 20; // size of each grid square in pixels
  const tileCountX = canvas.width / gridSize;
  const tileCountY = canvas.height / gridSize;

  let snake = [
    { x: 10, y: 10 },
    { x: 9, y: 10 },
    { x: 8, y: 10 },
  ];
  let velocity = { x: 1, y: 0 }; // starting moving right
  let apples = [];
  const maxApples = 3;

  let score = 0;
  let gameOver = false;

  // Generate a random position not occupied by snake or apples
  function randomPosition() {
    while (true) {
      const pos = {
        x: Math.floor(Math.random() * tileCountX),
        y: Math.floor(Math.random() * tileCountY),
      };
      // Check if pos is free
      if (
        !snake.some(s => s.x === pos.x && s.y === pos.y) &&
        !apples.some(a => a.x === pos.x && a.y === pos.y)
      ) {
        return pos;
      }
    }
  }

  // Initially spawn apples
  while (apples.length < maxApples) {
    apples.push(randomPosition());
  }

  function gameLoop() {
    if (gameOver) {
      ctx.fillStyle = '#0f0';
      ctx.font = '40px monospace';
      ctx.textAlign = 'center';
      ctx.fillText('Game Over', canvas.width / 2, canvas.height / 2 - 20);
      ctx.font = '20px monospace';
      ctx.fillText('Score: ' + score, canvas.width / 2, canvas.height / 2 + 20);
      ctx.fillText('Press Space to Restart', canvas.width / 2, canvas.height / 2 + 50);
      return;
    }

    update();
    draw();
  }

  function update() {
    // Move snake
    const head = { x: snake[0].x + velocity.x, y: snake[0].y + velocity.y };

    // Wrap around edges
    if (head.x < 0) head.x = tileCountX - 1;
    else if (head.x >= tileCountX) head.x = 0;
    if (head.y < 0) head.y = tileCountY - 1;
    else if (head.y >= tileCountY) head.y = 0;

    // Check collision with self
    if (snake.some(segment => segment.x === head.x && segment.y === head.y)) {
      gameOver = true;
      return;
    }

    snake.unshift(head);

    // Check if apple eaten
    const appleIndex = apples.findIndex(a => a.x === head.x && a.y === head.y);

    if (appleIndex !== -1) {
      score++;
      // Remove eaten apple
      apples.splice(appleIndex, 1);
      // Spawn a new apple if apples < maxApples
      while (apples.length < maxApples) {
        apples.push(randomPosition());
      }
    } else {
      // No apple eaten: remove tail segment
      snake.pop();
    }
  }

  function draw() {
    // Clear canvas
    ctx.fillStyle = '#222';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // Draw apples
    apples.forEach(a => {
      ctx.fillStyle = 'red';
      ctx.beginPath();
      const centerX = a.x * gridSize + gridSize / 2;
      const centerY = a.y * gridSize + gridSize / 2;
      const radius = gridSize / 2 * 0.8;
      ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
      ctx.fill();

      // Optional small white shine on apple
      ctx.fillStyle = 'rgba(255,255,255,0.7)';
      ctx.beginPath();
      ctx.arc(centerX - radius / 3, centerY - radius / 3, radius / 4, 0, 2 * Math.PI);
      ctx.fill();
    });

    // Draw snake
    ctx.fillStyle = 'limegreen';
    snake.forEach((segment, index) => {
      ctx.fillRect(segment.x * gridSize, segment.y * gridSize, gridSize, gridSize);

      // Optional outline for better visibility
      ctx.strokeStyle = 'darkgreen';
      ctx.lineWidth = 2;
      ctx.strokeRect(segment.x * gridSize, segment.y * gridSize, gridSize, gridSize);
    });

    // Draw score
    ctx.fillStyle = '#0f0';
    ctx.font = '18px monospace';
    ctx.textAlign = 'left';
    ctx.fillText('Score: ' + score, 10, 20);
  }

  // Direction control
  window.addEventListener('keydown', e => {
    if (gameOver && e.code === 'Space') {
      restartGame();
      return;
    }
    switch (e.code) {
      case 'ArrowUp':
        if (velocity.y !== 1) {
          velocity = { x: 0, y: -1 };
        }
        break;
      case 'ArrowDown':
        if (velocity.y !== -1) {
          velocity = { x: 0, y: 1 };
        }
        break;
      case 'ArrowLeft':
        if (velocity.x !== 1) {
          velocity = { x: -1, y: 0 };
        }
        break;
      case 'ArrowRight':
        if (velocity.x !== -1) {
          velocity = { x: 1, y: 0 };
        }
        break;
    }
  });

  function restartGame() {
    snake = [
      { x: 10, y: 10 },
      { x: 9, y: 10 },
      { x: 8, y: 10 },
    ];
    velocity = { x: 1, y: 0 };
    apples = [];
    while (apples.length < maxApples) {
      apples.push(randomPosition());
    }
    score = 0;
    gameOver = false;
    loop();
  }

  let frameCount = 0;
  const FPS = 10; // snake move speed

  function loop(timestamp) {
    frameCount++;
    if (frameCount % (60 / FPS) === 0) {
      gameLoop();
    }
    if (!gameOver) requestAnimationFrame(loop);
  }
xasd
  // Start game loop
  loop();

})();
</script>
</body>
</html>