const crypto = require('crypto'); class PlayingCard { static suits = { spades: '♠', hearts: '♥', diamonds: '♦', clubs: '♣' } static ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'] constructor(suit, rank) { this.suit = suit; this.rank = rank; } get getRank() { switch (this.rank) { case 'A': return 'Ace'; case 'J': return 'Jack'; case 'Q': return 'Queen'; case 'K': return 'King'; default: return this.rank; } } get name() { return `${this.getRank} of ${PlayingCard.suits[this.suit]}`; } get Value() { if (this.rank === 'A') { return [1, 11]; } else if (['J', 'Q', 'K'].includes(this.rank)) { return [10]; } else { return [parseInt(this.rank)]; } } } class Deck { constructor() { this.cards = []; for (const suit in PlayingCard.suits) { for (const rank of PlayingCard.ranks) { this.cards.push(new PlayingCard(suit, rank)); } } } shuffleOnce() { for (let i = this.cards.length - 1; i > 0; i--) { const randomIndex = crypto.randomInt(0, i + 1); const temp = this.cards[i]; this.cards[i] = this.cards[randomIndex]; this.cards[randomIndex] = temp; } } shuffle(shuffles = 3) { for (let i = 0; i < shuffles; i++) { this.shuffleOnce(); } } drawCard() { return this.cards.pop(); } } class BlackjackTable { constructor() { this.deck = new Deck(); this.deck.shuffle(); this.playerHand = [this.deck.drawCard(), this.deck.drawCard()]; this.dealerHand = [this.deck.drawCard(), this.deck.drawCard()]; } playerScore() { return this.calculateScore(this.playerHand); } drawCard() { return this.deck.drawCard(); } calculateScore(hand) { let score = 0; for (const card of hand) { score += card.Value[0]; } return score; } isBust(score) { return score > 21; } winner(player, dealer) { const dealerScore = this.calculateScore(dealer); const playerScore = this.calculateScore(player); const playerIsBust = this.isBust(playerScore); const dealerIsBust = this.isBust(dealerScore); const playerWins = !playerIsBust && (playerScore > dealerScore || dealerIsBust); const dealerWins = !dealerIsBust && (dealerScore > playerScore || playerIsBust); return playerWins ? 'player' : dealerWins ? 'dealer' : 'tie'; } } class BlackjackGame { constructor() { this.blackjack = new BlackjackTable(); this.readline = require('readline').createInterface({ input: process.stdin, output: process.stdout }); } printSeparator() { console.log('\n---------------------------------\n'); } printPlayerHand() { console.log(`\nPlayer hand: ${this.blackjack.playerHand.map(card => card.name).join(', ')}`); console.log(`Player score: ${this.blackjack.playerScore()}`); } printDealerHand(hidden = true) { if (hidden) { console.log(`Dealer hand: ${this.blackjack.dealerHand[0].name}, [Hidden]`); console.log(`Dealer score: ${this.blackjack.dealerHand[0].Value[0]}`); } else { console.log(`Dealer hand: ${this.blackjack.dealerHand.map(card => card.name).join(', ')}`); console.log(`Dealer score: ${this.blackjack.calculateScore(this.blackjack.dealerHand)}`); } } printWinner() { const winner = this.blackjack.winner(this.blackjack.playerHand, this.blackjack.dealerHand); if (winner !== 'tie') return console.log(`The winner is the ${winner}! Congratulations!`); console.log('It\'s a tie!'); } recieveInput(answer) { answer = answer.toLowerCase(); switch (answer) { case 'hit': this.blackjack.playerHand.push(this.blackjack.drawCard()); this.printPlayerHand(); if (this.blackjack.isBust(this.blackjack.playerScore())) { this.printSeparator(); console.log('Player busts! Dealer wins!'); return this.readline.close(); } this.askQuestion(); break; case 'stand': while (this.blackjack.calculateScore(this.blackjack.dealerHand) < 17) { this.blackjack.dealerHand.push(this.blackjack.drawCard()); } this.printSeparator(); this.printDealerHand(false); this.printSeparator(); this.printWinner(); this.readline.close(); break; default: this.printSeparator(); console.log('Invalid input. Please try again.'); this.printSeparator(); this.askQuestion(); break; } } askQuestion() { this.readline.question('Would you like to hit or stand? ', this.recieveInput.bind(this)); } doubleNewline() { process.stdout.write('\n\n'); } start() { this.printPlayerHand(); this.doubleNewline(); this.printDealerHand(); this.printSeparator(); this.askQuestion(); } } const blackjackGame = new BlackjackGame(); blackjackGame.start();