Sélectionner une page

lo2

import React, { useState, useEffect } from 'react';

// Types de cartes éléments et leurs valeurs
const ELEMENT_COLORS = ['violet', 'blue', 'orange', 'green', 'gray'];
const ELEMENT_VALUES = [1, 2, 3, 5, 8];

// Création du deck complet d'éléments
const createElementDeck = () => {
  const deck = [];
  ELEMENT_COLORS.forEach(color => {
    ELEMENT_VALUES.forEach(value => {
      deck.push({ color, value });
    });
  });
  return deck;
};

// Mélanger un array (Fisher-Yates shuffle)
const shuffleArray = (array) => {
  const shuffled = [...array];
  for (let i = shuffled.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
  }
  return shuffled;
};

const CHARACTERS = {
  tigreblanc: {
    name: "Tigre Blanc",
    stats: [7, 4, 2, 5, 2],
    ability: "Fidèles Compagnons"
  },
  barbare: {
    name: "Barbare Squelette",
    stats: [4, 6, 3, 3, 8],
    ability: "Carnage"
  }
};

const LegendsGame = () => {
  const [gameState, setGameState] = useState({
    playerHand: [],         // Cartes du joueur
    enemyPlacement: [],     // Cartes placées du Barbare
    playerPlacements: {},   // Cartes placées par le joueur
    selectedCard: null,     // Carte sélectionnée pour placement
    phase: 'setup',         // 'setup', 'playing', 'finished'
    currentRound: 1,        // Round actuel
    score: { player: 0, enemy: 0 }, // Score de la partie
    drawPile: [],          // Pioche restante
    tieBreakers: {}        // Cartes de départage pour chaque round
  });

  // Fonction pour initialiser une nouvelle partie
  const initializeGame = () => {
    const deck = shuffleArray(createElementDeck());
    const playerHand = deck.slice(0, 4);
    const enemyCards = deck.slice(4, 7);
    const enemyPlacement = enemyCards.map(card => ({ ...card }));
    const drawPile = deck.slice(7); // Le reste des cartes va dans la pioche

    setGameState({
      playerHand,
      enemyPlacement,
      playerPlacements: {},
      selectedCard: null,
      phase: 'setup',
      currentRound: 1,
      score: { player: 0, enemy: 0 },
      drawPile,
      tieBreakers: {}
    });
  };

  // Initialisation au montage du composant
  useEffect(() => {
    initializeGame();
  }, []);

  // Sélectionner une carte de la main
  const selectCard = (index) => {
    if (gameState.phase !== 'setup') return;
    setGameState(prev => ({
      ...prev,
      selectedCard: index
    }));
  };

  // Placer une carte sur un round
  const placeCard = (round) => {
    if (gameState.phase !== 'setup' || gameState.selectedCard === null) return;
    if (gameState.playerPlacements[round]) return; // Déjà une carte sur ce round
    
    const newPlacements = {
      ...gameState.playerPlacements,
      [round]: gameState.playerHand[gameState.selectedCard]
    };

    // Retirer la carte de la main
    const newHand = gameState.playerHand.filter((_, idx) => idx !== gameState.selectedCard);

    // Vérifier si toutes les cartes sont placées
    const allCardsPlaced = Object.keys(newPlacements).length === 3;

    setGameState(prev => ({
      ...prev,
      playerPlacements: newPlacements,
      playerHand: newHand,
      selectedCard: null,
      phase: allCardsPlaced ? 'playing' : 'setup'
    }));
  };

  // Résoudre un round
  const resolveRound = () => {
    const currentRound = gameState.currentRound;
    
    // Calculer les valeurs totales
    const playerValue = (gameState.playerPlacements[currentRound]?.value || 0) + 
                       CHARACTERS.tigreblanc.stats[currentRound - 1];
    const enemyValue = (gameState.enemyPlacement[currentRound - 1]?.value || 0) + 
                      CHARACTERS.barbare.stats[currentRound - 1];

    // En cas d'égalité, piocher une carte pour départager
    let tieBreaker = null;
    if (playerValue === enemyValue && gameState.drawPile.length > 0) {
      const [newCard, ...remainingDeck] = gameState.drawPile;
      tieBreaker = newCard;
      
      const newTieBreakers = {
        ...gameState.tieBreakers,
        [currentRound]: newCard
      };

      setGameState(prev => ({
        ...prev,
        drawPile: remainingDeck,
        tieBreakers: newTieBreakers
      }));
    }

    // Mettre à jour le score
    const newScore = { ...gameState.score };
    const finalPlayerValue = playerValue + (tieBreaker?.value || 0);
    const finalEnemyValue = enemyValue + (tieBreaker?.value || 0);

    if (finalPlayerValue > finalEnemyValue) {
      newScore.player += 1;
    } else if (finalEnemyValue > finalPlayerValue) {
      newScore.enemy += 1;
    }

    // Vérifier si la partie est terminée
    const isGameOver = currentRound === 3 || newScore.player === 2 || newScore.enemy === 2;

    setGameState(prev => ({
      ...prev,
      currentRound: currentRound + 1,
      score: newScore,
      phase: isGameOver ? 'finished' : 'playing'
    }));
  };

  return (
    <div className="min-h-screen bg-gray-900 text-white p-8">
      <div className="flex gap-8">
        {/* Zone principale du jeu */}
        <div className="flex-1">
          {/* En-tête du jeu */}
          <div className="mb-8 text-center">
            <h1 className="text-3xl font-bold mb-4">Legends</h1>
            <div className="text-xl">
              {gameState.phase === 'setup' && "Placez vos cartes sur les rounds"}
              {gameState.phase === 'playing' && `Round ${gameState.currentRound}`}
              {gameState.phase === 'finished' && "Partie terminée"}
            </div>
            <div className="text-xl mt-2">
              Score - Tigre Blanc: {gameState.score.player} | Barbare: {gameState.score.enemy}
            </div>
          </div>

          {/* Zone de l'ennemi */}
          <div className="mb-12">
            <div className="flex gap-8 items-center">
              {/* Carte du Barbare Squelette */}
              <div className="w-48 bg-gray-800 rounded-lg shadow-lg flex">
                <div className="w-12 py-4 flex flex-col items-center gap-2">
                  <div className="w-8 h-8 bg-red-600 rounded-full flex items-center justify-center text-white font-bold">4</div>
                  <div className="w-8 h-8 bg-blue-600 rounded-full flex items-center justify-center text-white font-bold">6</div>
                  <div className="w-8 h-8 bg-purple-600 rounded-full flex items-center justify-center text-white font-bold">3</div>
                  <div className="w-8 h-8 bg-green-600 rounded-full flex items-center justify-center text-white font-bold">3</div>
                  <div className="w-8 h-8 bg-gray-600 rounded-full flex items-center justify-center text-white font-bold">8</div>
                </div>
                <div className="flex-1 p-4">
                  <h3 className="text-lg font-bold mb-2">{CHARACTERS.barbare.name}</h3>
                  <p className="text-sm text-gray-300">{CHARACTERS.barbare.ability}</p>
                </div>
              </div>
              
              {/* Cartes placées de l'ennemi */}
              <div className="flex gap-8">
                {[1, 2, 3].map(round => (
                  <div key={round} className="relative">
                    <span className="absolute -top-6 w-full text-center">Round {round}</span>
                    <div className="w-32 h-48 bg-gray-800 rounded-lg flex items-center justify-center">
                      {gameState.phase === 'finished' || round < gameState.currentRound ? (
                        <div className={`w-full h-full rounded-lg flex items-center justify-center 
                          ${gameState.enemyPlacement[round-1]?.color === 'violet' ? 'bg-purple-700' :
                            gameState.enemyPlacement[round-1]?.color === 'blue' ? 'bg-blue-700' :
                            gameState.enemyPlacement[round-1]?.color === 'orange' ? 'bg-orange-700' :
                            gameState.enemyPlacement[round-1]?.color === 'green' ? 'bg-green-700' :
                            'bg-gray-700'}`}>
                          <span className="text-2xl font-bold">
                            +{gameState.enemyPlacement[round-1]?.value}
                          </span>
                        </div>
                      ) : (
                        <div className="w-full h-full bg-gradient-to-br from-amber-900 to-yellow-800 rounded-lg" />
                      )}
                    </div>
                  </div>
                ))}
              </div>
            </div>
          </div>

          {/* Zone du joueur */}
          <div className="mb-8">
            <div className="flex gap-8 items-center">
              {/* Carte du Tigre Blanc */}
              <div className="w-48 bg-gray-800 rounded-lg shadow-lg flex">
                <div className="w-12 py-4 flex flex-col items-center gap-2">
                  <div className="w-8 h-8 bg-red-600 rounded-full flex items-center justify-center text-white font-bold">7</div>
                  <div className="w-8 h-8 bg-blue-600 rounded-full flex items-center justify-center text-white font-bold">4</div>
                  <div className="w-8 h-8 bg-purple-600 rounded-full flex items-center justify-center text-white font-bold">2</div>
                  <div className="w-8 h-8 bg-green-600 rounded-full flex items-center justify-center text-white font-bold">5</div>
                  <div className="w-8 h-8 bg-gray-600 rounded-full flex items-center justify-center text-white font-bold">2</div>
                </div>
                <div className="flex-1 p-4">
                  <h3 className="text-lg font-bold mb-2">{CHARACTERS.tigreblanc.name}</h3>
                  <p className="text-sm text-gray-300">{CHARACTERS.tigreblanc.ability}</p>
                </div>
              </div>

              {/* Emplacements pour placer les cartes */}
              <div className="flex gap-8">
                {[1, 2, 3].map(round => (
                  <div 
                    key={round}
                    onClick={() => placeCard(round)}
                    className={`relative cursor-pointer ${gameState.selectedCard !== null ? 'hover:scale-105 transition-transform' : ''}`}
                  >
                    <span className="absolute -top-6 w-full text-center">Round {round}</span>
                    <div className="w-32 h-48 bg-gray-800 rounded-lg flex items-center justify-center">
                      {gameState.playerPlacements[round] && (
                        <div className={`w-full h-full rounded-lg flex items-center justify-center
                          ${gameState.playerPlacements[round].color === 'violet' ? 'bg-purple-700' :
                            gameState.playerPlacements[round].color === 'blue' ? 'bg-blue-700' :
                            gameState.playerPlacements[round].color === 'orange' ? 'bg-orange-700' :
                            gameState.playerPlacements[round].color === 'green' ? 'bg-green-700' :
                            'bg-gray-700'}`}>
                          <span className="text-2xl font-bold">
                            +{gameState.playerPlacements[round].value}
                          </span>
                        </div>
                      )}
                    </div>
                  </div>
                ))}
              </div>
            </div>

            {/* Main du joueur */}
            {gameState.phase === 'setup' && (
              <div className="flex gap-8 mt-8 justify-center">
                {gameState.playerHand.map((card, index) => (
                  <button
                    key={index}
                    onClick={() => selectCard(index)}
                    className={`w-32 h-48 rounded-lg flex items-center justify-center text-2xl font-bold
                      transform transition-all
                      ${gameState.selectedCard === index ? 'ring-4 ring-yellow-400 scale-105' : 'hover:scale-105'}
                      ${card.color === 'violet' ? 'bg-purple-700' :
                        card.color === 'blue' ? 'bg-blue-700' :
                        card.color === 'orange' ? 'bg-orange-700' :
                        card.color === 'green' ? 'bg-green-700' :
                        'bg-gray-700'}`}
                  >
                    +{card.value}
                  </button>
                ))}
              </div>
            )}

            {/* Bouton pour résoudre le round */}
            {gameState.phase === 'playing' && (
              <div className="flex justify-center mt-8">
                <button
                  onClick={resol
× Comment puis-je vous aider ?