I trying to make Blackjack game in React. A bot has got 2 cards at start. If user stands, and bots card value is less than 17, it should draw addictional card, but then program cause infinite loop. This is my code:
const [playerCards, setPlayerCards] = useState<Card[]>([]);
const shuffledDeck = shuffleDeck(deck);
const [dealerCards, setDealerCards] = useState<Card[]>([]);
const shuffleDeck = (deck: Card[]): Card[] => {
for (let i = deck.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i 1));
[deck[i], deck[j]] = [deck[j], deck[i]];
}
return deck;
};
const handleStand = () => {
if (gameState === 'playing') {
console.log(shuffledDeck[playerCards.length dealerCards.length]);
while(getHandValue(dealerCards) < 17) {
setDealerCards([
...dealerCards,
shuffledDeck[playerCards.length dealerCards.length],
]);
}
}
let dealerHandValue = getHandValue(dealerCards);
const playerHandValue = getHandValue(playerCards);
if (dealerHandValue > 21 || dealerHandValue < playerHandValue) {
setGameState('won');
setPlayerBalance(playerBalance currentBet);
} else if (dealerHandValue > playerHandValue) {
setGameState('lost');
setPlayerBalance(playerBalance - currentBet);
} else {
setGameState('tied');
}
};
const getHandValue = (cards: Card[]): number => {
let value = 0;
let numAces = 0;
for (const card of cards) {
if (card.rank === Rank.Ace) {
numAces ;
} else if (card.rank === 'J' || card.rank === 'K' || card.rank === 'Q') {
value = 10;
} else {
value = Number(card.rank);
}
}
while (numAces > 0) {
if (value 11 > 21) {
value = 1;
} else {
value = 11;
}
numAces--;
}
return value;
};
The goal is to make bot draw a cards until value of his cards will be at least 17.
CodePudding user response:
As discussed in the comments, using setDealerCards
inside the while
loop can be problematic. Setting the state causes a re-render to the component and may trigger the function again depending on it's use.
Another problem may be that since React schedules it's updates you may not get the most updated state every time you set the state again in the while
loop.
So this might help
const handleStand = () => {
let newDealerCards = [...dealerCards];
if (gameState === 'playing') {
while(getHandValue(newDealerCards) < 17) {
newDealerCards =
[...newDealerCards, shuffledDeck[playerCards.length newDealerCards.length]];
}
setDealerCards(newDealerCards);
}
let dealerHandValue = getHandValue(newDealerCards);
const playerHandValue = getHandValue(playerCards);
if (dealerHandValue > 21 || dealerHandValue < playerHandValue) {
setGameState('won');
setPlayerBalance(playerBalance currentBet);
} else if (dealerHandValue > playerHandValue) {
setGameState('lost');
setPlayerBalance(playerBalance - currentBet);
} else {
setGameState('tied');
}
};
We make the new newDealerCards
variable to spread dealerCards
state, we then do the while
loop with your condition and update newDealerCards
accordingly. When we're done, only then we set the state again with the updated variable we made and thus we avoid calling setDealerCards
multiple times inside the while
loop.