• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed REACT - BlackJack - Tasowanie i wyświetlanie 4 kart duplikuje się

VPS Starter Arubacloud
0 głosów
95 wizyt
pytanie zadane 18 stycznia w JavaScript przez neo1020 Dyskutant (8,690 p.)
zamknięte 20 stycznia przez neo1020

Witajcie, Mam taki problem i nie wiem jak go rozwiązać albo gdzie mam błąd, będę wdzięczny za pomoc

Uczę się reacta i przyszło mi do głowy napisanie Black Jacka, i gdy wywołuje funkcję drawInitialCards z 

drawCard(crupierCards, setCrupierCards, crupierPoints, setCrupierPoints);
drawCard(crupierCards, setCrupierCards, crupierPoints, setCrupierPoints);
drawCard(playerCards, setPlayerCards, playerPoints, setPlayerPoints);
drawCard(playerCards, setPlayerCards, playerPoints, setPlayerPoints);

generuje mi 4 identyczne karty za każdym razem, walczę już z tym tyle że mam dość

a tu cały kod 

import React, { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
import cards from "./cards";
import "./blackJack.css";

function BlackJack() {
  const { t } = useTranslation();
  const [playerCards, setPlayerCards] = useState([]);
  const [crupierCards, setCrupierCards] = useState([]);
  const [deck, setDeck] = useState([]);
  const [isGameStarted, setIsGameStarted] = useState(false);
  const [playerPoints, setPlayerPoints] = useState(0);
  const [crupierPoints, setCrupierPoints] = useState(0);

  const cardWidth = 226;
  const cardHeight = 314;

  const initializeDeck = () => {
    const newDeck = Array.from({ length: 52 }, (_, index) => {
      return {
        number: index + 1,
        image: cards[index].image,
        value: cards[index].value,
      };
    });

    const shuffledDeck = shuffleDeck(newDeck);
    setDeck(shuffledDeck);
  };

  const shuffleDeck = (deck) => {
    return deck.sort(() => Math.random() - 0.5);
  };

  const drawCard = (targetCards, setTargetCards, targetPoints, setTargetPoints) => {
    if (deck.length === 0) {
      return;
    }

    const [drawnCard, ...remainingDeck] = deck;

    if (targetCards.some((card) => card.number === drawnCard.number)) {
      drawCard(targetCards, setTargetCards, targetPoints, setTargetPoints);
      return;
    }

    setTargetCards((prevCards) => [...prevCards, drawnCard]);
    setTargetPoints((prevPoints) => prevPoints + calculateCardValue(drawnCard));

    setDeck(remainingDeck);
  };

  const calculateCardValue = (card) => {
    return parseInt(card.value);
  };

  const drawInitialCards = () => {
    drawCard(crupierCards, setCrupierCards, crupierPoints, setCrupierPoints);
    drawCard(crupierCards, setCrupierCards, crupierPoints, setCrupierPoints);
    drawCard(playerCards, setPlayerCards, playerPoints, setPlayerPoints);
    drawCard(playerCards, setPlayerCards, playerPoints, setPlayerPoints);
  };

  useEffect(() => {
    if (!isGameStarted) {
      initializeDeck();
      setIsGameStarted(true);
      drawInitialCards();
    }
  }, [isGameStarted]);

  return (
    <div className="blackjack-outside">
      <div>
        <button
          className="btn-blackjack-start"
          onClick={() => drawInitialCards()}
        >
          Draw Card
        </button>
      </div>

      <div className="blackjack">
        <div className="crupier-div">
          <div className="crupier-div-name">Crupier</div>
          <div className="crupier-div-points">{crupierPoints}</div>
          <div className="flex">
            {crupierCards.map((card, index) => (
              <div
                key={index}
                style={{
                  width: cardWidth,
                  height: cardHeight,
                  backgroundImage: `url(${card.image})`,
                }}
              />
            ))}
          </div>
        </div>

        <div className="player-div">
          <div className="player-div-name">Player</div>
          <div className="player-div-points">{playerPoints}</div>
          <div className="flex">
            {playerCards.map((card, index) => (
              <div
                key={index}
                style={{
                  width: cardWidth,
                  height: cardHeight,
                  backgroundImage: `url(${card.image})`,
                }}
              />
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

export default BlackJack;

a tu importuje karty 

import EmptyCard from "../blackjack/img/empty-card.png";

import AS from "../blackjack/img/AS.png";
import AD from "../blackjack/img/AD.png";
import AC from "../blackjack/img/AC.png";
import AH from "../blackjack/img/AH.png";

import S2 from "../blackjack/img/2S.png";
import C2 from "../blackjack/img/2C.png";
import H2 from "../blackjack/img/2H.png";
import D2 from "../blackjack/img/2D.png";

import S3 from "../blackjack/img/3S.png";
import D3 from "../blackjack/img/3D.png";
import H3 from "../blackjack/img/3H.png";
import C3 from "../blackjack/img/3C.png";

import S4 from "../blackjack/img/4S.png";
import D4 from "../blackjack/img/4D.png";
import H4 from "../blackjack/img/4H.png";
import C4 from "../blackjack/img/4C.png";

import S5 from "../blackjack/img/5S.png";
import D5 from "../blackjack/img/5D.png";
import H5 from "../blackjack/img/5H.png";
import C5 from "../blackjack/img/5C.png";

import S6 from "../blackjack/img/6S.png";
import D6 from "../blackjack/img/6D.png";
import H6 from "../blackjack/img/6H.png";
import C6 from "../blackjack/img/6C.png";

import S7 from "../blackjack/img/7S.png";
import D7 from "../blackjack/img/7D.png";
import H7 from "../blackjack/img/7H.png";
import C7 from "../blackjack/img/7C.png";

import S8 from "../blackjack/img/8S.png";
import D8 from "../blackjack/img/8D.png";
import H8 from "../blackjack/img/8H.png";
import C8 from "../blackjack/img/8C.png";

import S9 from "../blackjack/img/9S.png";
import D9 from "../blackjack/img/9D.png";
import H9 from "../blackjack/img/9H.png";
import C9 from "../blackjack/img/9C.png";

import S0 from "../blackjack/img/0S.png";
import D0 from "../blackjack/img/0D.png";
import H0 from "../blackjack/img/0H.png";
import C0 from "../blackjack/img/0C.png";

import JS from "../blackjack/img/JS.png";
import JD from "../blackjack/img/JD.png";
import JH from "../blackjack/img/JH.png";
import JC from "../blackjack/img/JC.png";

import QS from "../blackjack/img/QS.png";
import QD from "../blackjack/img/QD.png";
import QH from "../blackjack/img/QH.png";
import QC from "../blackjack/img/QC.png";

import KS from "../blackjack/img/KS.png";
import KD from "../blackjack/img/KD.png";
import KH from "../blackjack/img/KH.png";
import KC from "../blackjack/img/KC.png";


const cards = [
  { image: AS, suit: 'SPADES', value: '1' },
  { image: AD, suit: 'DIAMONDS', value: '1' },
  { image: AC, suit: 'CLUBS', value: '1' },
  { image: AH, suit: 'HEARTS', value: '1' },

  { image: S2, suit: 'SPADES', value: '2' },
  { image: D2, suit: 'DIAMONDS', value: '2' },
  { image: C2, suit: 'CLUBS', value: '2' },
  { image: H2, suit: 'HEARTS', value: '2' },

  { image: S3, suit: 'SPADES', value: '3' },
  { image: D3, suit: 'DIAMONDS', value: '3' },
  { image: C3, suit: 'CLUBS', value: '3' },
  { image: H3, suit: 'HEARTS', value: '3' },

  { image: S4, suit: 'SPADES', value: '4' },
  { image: D4, suit: 'DIAMONDS', value: '4' },
  { image: C4, suit: 'CLUBS', value: '4' },
  { image: H4, suit: 'HEARTS', value: '4' },
  
  { image: S5, suit: 'SPADES', value: '5' },
  { image: D5, suit: 'DIAMONDS', value: '5' },
  { image: C5, suit: 'CLUBS', value: '5' },
  { image: H5, suit: 'HEARTS', value: '5' },

  { image: S6, suit: 'SPADES', value: '6' },
  { image: D6, suit: 'DIAMONDS', value: '6' },
  { image: C6, suit: 'CLUBS', value: '6' },
  { image: H6, suit: 'HEARTS', value: '6' },

  { image: S7, suit: 'SPADES', value: '7' },
  { image: D7, suit: 'DIAMONDS', value: '7' },
  { image: C7, suit: 'CLUBS', value: '7' },
  { image: H7, suit: 'HEARTS', value: '7' },

  { image: S8, suit: 'SPADES', value: '8' },
  { image: D8, suit: 'DIAMONDS', value: '8' },
  { image: C8, suit: 'CLUBS', value: '8' },
  { image: H8, suit: 'HEARTS', value: '8' },

  { image: S9, suit: 'SPADES', value: '9' },
  { image: D9, suit: 'DIAMONDS', value: '9' },
  { image: C9, suit: 'CLUBS', value: '9' },
  { image: H9, suit: 'HEARTS', value: '9' },

  { image: S0, suit: 'SPADES', value: '10' },
  { image: D0, suit: 'DIAMONDS', value: '10' },
  { image: C0, suit: 'CLUBS', value: '10' },
  { image: H0, suit: 'HEARTS', value: '10' },

  { image: S0, suit: 'SPADES', value: '10' },
  { image: D0, suit: 'DIAMONDS', value: '10' },
  { image: C0, suit: 'CLUBS', value: '10' },
  { image: H0, suit: 'HEARTS', value: '10' },

  { image: JS, suit: 'SPADES', value: '10' },
  { image: JD, suit: 'DIAMONDS', value: '10' },
  { image: JC, suit: 'CLUBS', value: '10' },
  { image: JH, suit: 'HEARTS', value: '10' },

  { image: QS, suit: 'SPADES', value: '10' },
  { image: QD, suit: 'DIAMONDS', value: '10' },
  { image: QC, suit: 'CLUBS', value: '10' },
  { image: QH, suit: 'HEARTS', value: '10' },

  { image: KS, suit: 'SPADES', value: '10' },
  { image: KD, suit: 'DIAMONDS', value: '10' },
  { image: KC, suit: 'CLUBS', value: '10' },
  { image: KH, suit: 'HEARTS', value: '10' },
];

export default cards;

 

komentarz zamknięcia: Problem rozwiązany napisaniem nowego kodu mniej skomplikowanego
komentarz 19 stycznia przez Marak123 Stary wyjadacz (11,190 p.)
Opisz bardziej to w czym masz problem, bo podałeś jakieś 3 kawałki kodu i napisałeś ze generuje 4 identyczne, ale w czym jest problem?
komentarz 20 stycznia przez neo1020 Dyskutant (8,690 p.)
już ogarnąłem, w tym był że miały być 4 różne karty  a zawsze miałem identyczne ale już ogarnąłem to useState i jego asynchroniczność

1 odpowiedź

0 głosów
odpowiedź 20 stycznia przez rafal.budzis Szeryf (85,340 p.)

Ustawianie stanu z useState w React działa asynchronicznie dlatego też można w set używać funkcji aby mieć pewność że operujesz na najnowszym stanie :) 
 

setDeck(remainingDeck);


wykona się prawdopodobnie dopiero po skończeniu wykonywania się wszystkich 4 funkcji :) Możesz to obejść tak: 
 

const drawCard = (targetCards, setTargetCards, targetPoints, setTargetPoints) => {
  setDeck(deck => {
    if (deck.length === 0) {
      return deck;
    }
    const [drawnCard, ...remainingDeck] = deck;

    if (targetCards.some((card) => card.number === drawnCard.number)) {
      drawCard(targetCards, setTargetCards, targetPoints, setTargetPoints);
      return;
    }

    setTargetCards((prevCards) => [...prevCards, drawnCard]);
    setTargetPoints((prevPoints) => prevPoints + calculateCardValue(drawnCard));

    return remainingDeck;
  });
};

Sety powinny na siebie poczekać ;) Jednak ja bym nie używał useState do trzymania talii ponieważ JSX nie musi się przerenderować po jej zmianie. Uzyj useRef i nie bedziesz miał problemów z asynchronicznym SETerem ;) 

komentarz 20 stycznia przez neo1020 Dyskutant (8,690 p.)

Dzięki za podpowiedź z tym useRef wypróbuję, właśnie nie mogłem ogarnąć tej asynchroniczności już zdążyłem przepisać kod 3 razy od kiedy wstawiłem posta :D już prawie działa ale wypróbuję useRef na pewno

import React, { useEffect, useState } from "react";
import Deck, { createDeck, shuffleDeck } from "./core/Deck";
import Player from "./core/Player";
import Crupier from "./core/Crupier";

const BlackJack = () => {
  const [deck, setDeck] = useState([]);
  const [playerDeck, setPlayerDeck] = useState([]);
  const [crupierDeck, setCrupierDeck] = useState([]);
  const [isStart, setStart] = useState(false);
  const [revealCrupierCard, setRevealCrupierCard] = useState(false);
  const [playerPoints, setPlayerPoints] = useState(0);
  const [crupierPoints, setCrupierPoints] = useState(0);
  const [gameMessage, setGameMessage] = useState("");


  useEffect(() => {
    if (isStart) {
      const newDeck = shuffleDeck(createDeck());
      console.log(newDeck);
      setDeck(newDeck);
      dealCards(newDeck);
      checkBlackjack(playerPoints, crupierPoints);
    }
  }, [isStart]);

  useEffect(() => {
    if (isStart) {
      // console.log("Updated deck:", deck);
      // console.log("Player deck:", playerDeck);
      // console.log("Crupier deck:", crupierDeck);
      updatePlayerPoints(playerDeck);
      updateCrupierPoints(crupierDeck, revealCrupierCard);
      // console.log(`playerPoints: ${playerPoints}`);
      // console.log(`crupierPoints: ${crupierPoints}`);
    }
  }, [deck, playerDeck, crupierDeck, revealCrupierCard]);

  useEffect(() => {
    if (isStart) {
      if (playerPoints > 21) {
        setRevealCrupierCard(true);
        checkResults(playerPoints, crupierPoints);
      }
    }
  }, [playerPoints]);

  useEffect(() => {
    if (isStart) {
      if (playerPoints < 21) {
        checkResults(playerPoints, crupierPoints);
      }
    }
  }, [crupierPoints]);



  const resetGame = () => {
    setStart(false);
    setRevealCrupierCard(false);
    setPlayerDeck([]);
    setCrupierDeck([]);
    setDeck([]);
    setPlayerPoints(0);
    setCrupierPoints(0);
    setGameMessage("");
    // Start();
  };
  function dealCards(deck) {
    let PlayerCards = [deck[0], deck[2]];
    let CrupierCards = [deck[1], deck[3]];
    setPlayerDeck(PlayerCards);
    setCrupierDeck(CrupierCards);
    let newDeck = deck.slice(4);
    setDeck(newDeck);
    updatePlayerPoints(PlayerCards);
  }

  const handleHit = () => {
    console.log(`--------PRESS HIT---------`);
    if (isStart) {
      let newPlayerCards = [...playerDeck, deck[0]];

      setPlayerDeck(newPlayerCards);
      let newDeck = deck.slice(1);
      setDeck(newDeck);
      updatePlayerPoints(newPlayerCards);
      // checkResults(playerPoints, crupierPoints);
    }
  };

  const handleStand = () => {
    console.log(`--------PRESS STAND---------`);
    setRevealCrupierCard(true);
    if (crupierPoints < 17) {
      let newCrupierCards = [...crupierDeck, deck[0]];
      setCrupierDeck(newCrupierCards);
      let newDeck = deck.slice(1);
      setDeck(newDeck);
      updateCrupierPoints(newCrupierCards, true);
      // checkResults(playerPoints, crupierPoints);
    }
  };

  const updatePlayerPoints = (cards) => {
    let points = calculatePoints(cards);
    setPlayerPoints(points);
  };
  const calculatePoints = (cards) => {
    let points = 0;
    let numAces = 0;

    cards.forEach((card) => {
      if (card.value === "ACE") {
        numAces++;
        points += 11;
      } else if (
        card.value === "KING" ||
        card.value === "QUEEN" ||
        card.value === "JACK"
      ) {
        points += 10;
      } else {
        points += parseInt(card.value);
      }
    });

    while (numAces > 0 && points > 21) {
      points -= 10;
      numAces--;
    }

    return points;
  };
  const updateCrupierPoints = (cards, revealCard) => {
    let points = 0;

    if (revealCard) {
      points = calculatePoints(cards);
    } else {
      points = calculatePoints(cards.slice(0, cards.length - 1));
    }

    setCrupierPoints(points);
  };
  const checkBlackjack = (playerPoints, crupierPoints) => {
    if (playerPoints === 21 && crupierPoints === 21) {
      setGameMessage("Gracz ma Blackjack!");
    } else if (playerPoints === 21) {
      setGameMessage("Crupier ma Blackjack!");
    } else if (crupierPoints === 21) {
      setGameMessage("Crupier ma Blackjack!");
    }
  };

  const checkResults = (playerPoints, crupierPoints) => {
    console.log("### checkResults / Player Points:", playerPoints);
    console.log("### checkResults / Crupier Points:", crupierPoints);
    let resultMessage = "";

    if (playerPoints > 21) {
      resultMessage = "Gracz przekroczył 21 punktów!";
    } else if (crupierPoints > 21) {
      resultMessage = "Crupier przekroczył 21 punktów.";
    } else if (playerPoints === 21 && crupierPoints === 21) {
      resultMessage = "DOUBLE BLACKJACK";
    } else if (playerPoints === 21) {
      resultMessage = "Gracz wygrywa! Blackjack!";
    } else if (crupierPoints === 21) {
      resultMessage = "Crupier wygrywa! Blackjack!";
    } else if (
      playerPoints > crupierPoints &&
      playerPoints < 21 &&
      crupierPoints < 21
    ) {
      resultMessage = "Gracz wygrywa!";
    } else if (playerPoints < crupierPoints) {
      resultMessage = "Crupier wygrywa!";
    } else if (playerPoints === crupierPoints) {
      resultMessage = "REMIS";
    }

    setGameMessage(resultMessage);
  };

  const Start = () => {
    setStart(true);
    setGameMessage("");
  };

  return (
    <>
      <div>
        <button onClick={Start}>START</button>
        <button onClick={resetGame}>RESTART</button>
      </div>

      {gameMessage && <div>{gameMessage}</div>}

      {isStart && (
        <>
          <Player cards={playerDeck} points={playerPoints} />
          <div>
            <button onClick={handleHit} disabled={!isStart}>
              Hit
            </button>
            <button onClick={handleStand} disabled={!isStart}>
              Stand
            </button>
          </div>
          <Crupier
            cards={crupierDeck}
            points={crupierPoints}
            revealCard={revealCrupierCard}
          />
          <Deck cards={deck} />
        </>
      )}
    </>
  );
};

export default BlackJack;

 

Podobne pytania

0 głosów
0 odpowiedzi 88 wizyt
+1 głos
2 odpowiedzi 670 wizyt
pytanie zadane 16 października 2022 w JavaScript przez wsnofi Bywalec (2,680 p.)
0 głosów
1 odpowiedź 107 wizyt
pytanie zadane 10 maja 2022 w JavaScript przez chrystian Gaduła (4,780 p.)

92,972 zapytań

141,936 odpowiedzi

321,171 komentarzy

62,301 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Wprowadzenie do ITsec, tom 2

Można już zamawiać tom 2 książki "Wprowadzenie do bezpieczeństwa IT" - będzie to około 650 stron wiedzy o ITsec (17 rozdziałów, 14 autorów, kolorowy druk).

Planowana premiera: 30.09.2024, zaś planowana wysyłka nastąpi w drugim tygodniu października 2024.

Warto preorderować, tym bardziej, iż mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy dodatkowe 15% zniżki! Dziękujemy zaprzyjaźnionej ekipie Sekuraka za kod dla naszej Społeczności!

...