• 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ę

Object Storage Arubacloud
0 głosów
77 wizyt
pytanie zadane 18 stycznia w JavaScript przez neo1020 Dyskutant (8,430 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,430 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,260 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,430 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 81 wizyt
+1 głos
2 odpowiedzi 528 wizyt
pytanie zadane 16 października 2022 w JavaScript przez wsnofi Bywalec (2,680 p.)
0 głosów
1 odpowiedź 91 wizyt
pytanie zadane 10 maja 2022 w JavaScript przez chrystian Gaduła (4,780 p.)

92,576 zapytań

141,426 odpowiedzi

319,652 komentarzy

61,961 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.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...