4
\$\begingroup\$

I am learning javascript with the course Javascript Getting started by Mark Zaymota.

Currently the code is in a script.js file, and I was wondering how could we refactor it to extract classes from it.

The code in a file, until cards' generation and shuffle is:

index.html:

<!DOCTYPE html>
<html>
 <head>
 <link rel="stylesheet" href="style.css">
 </head>
 <body>
 <h1>Blackjack game</h1>
 <h6>By Yone Moreno</h6>
 <br>
 <p id='text-area'>Welcome to BlackJack!!!!!</p>
 <button id='new-game-button'>Start a New Game!!!</button>
 <button id='hit-button'>Hit!</button>
 <button id='stay-button'>Stay...</button>
 <script src="script.js"></script>
 </body>
</html>

script.js

// Blackjack
let textArea = document.getElementById('text-area');
let newGameButton = document.getElementById('new-game-button');
let hitButton = document.getElementById('hit-button');
let stayButton = document.getElementById('stay-button');
let gameStarted = false,
 gameOver = false,
 playerWon = false,
 dealerCards = [],
 playerCards = [],
 dealerScore = 0,
 playerScore = 0,
 deck = [];
hitButton.style.display = 'none';
stayButton.style.display = 'none';
showStatus();
newGameButton.addEventListener('click', function() {
 gameStarted = true;
 gameOver = false;
 playerWon = false;
 deck = createDeck();
 shuffleDeck(deck);
 dealerCards = [getNextCard(), getNextCard()];
 playerCards = [getNextCard(), getNextCard()];
 newGameButton.style.display = 'none';
 hitButton.style.display = 'inline';
 stayButton.style.display = 'inline';
 showStatus();
})
let suits = ['Hearts', 'Clubs', 'Diamonds', 'Spades'];
let values = ['As', 'King', 'Queen', 'Jack',
 'Ten', 'Nine', 'Eight', 'Seven', 'Six',
 'Five', 'Four', 'Three', 'Two'
]
function createDeck() {
 let deck = [];
 for (suitIndex = 0; suitIndex < suits.length; suitIndex++) {
 for (let valueIndex = 0; valueIndex < values.length; valueIndex++) {
 let card = {
 suit: suits[suitIndex],
 value: values[valueIndex]
 };
 deck.push(card);
 }
 }
 return deck;
}
function getNextCard() {
 return deck.shift();
}
function getCardString(card) {
 return card.value + ' of ' + card.suit;
}
function showStatus() {
 if (!gameStarted) {
 textArea.innerText = 'Welcome to BlackJack!!!!!!!!!!';
 return;
 }
 for (let i = 0; i < deck.length; i++) {
 textArea.innerText += '\n' + getCardString(deck[i]);
 }
}
function shuffleDeck(deck) {
 for (let i = 0; i < deck.length; i++) {
 let swapIndex = Math.trunc(Math.random() * deck.length);
 let randomCard = deck[swapIndex];
 let currentCard = deck[i];
 deck[swapIndex] = currentCard;
 deck[i] = randomCard;
 }
}

How could we refactor it?

I thought we should create some classes:

Deck, with createDeck() and shuffleDeck()

Card with getNextCard() and getCardString()

GameManager with buttons, text area and vriables, style logic, call to functions and event listeners.

Until now I have extracted Deck class:

Deck.js

class Deck{
 createDeck() {
 let deck = [];
 for (let suitIndex = 0; suitIndex < suits.length; suitIndex++) {
 for (let valueIndex = 0; valueIndex < values.length; valueIndex++) {
 let card = {
 suit: suits[suitIndex],
 value: values[valueIndex]
 };
 deck.push(card);
 }
 }
 this.deck = deck;
 return deck;
 }
 shuffleDeck() {
 for (let i = 0; i < deck.length; i++) {
 let swapIndex = Math.trunc(Math.random() * deck.length);
 let randomCard = deck[swapIndex];
 let currentCard = deck[i];
 deck[swapIndex] = currentCard;
 deck[i] = randomCard;
 }
 }
}

new script.js

// Blackjack
let textArea = document.getElementById('text-area');
let newGameButton = document.getElementById('new-game-button');
let hitButton = document.getElementById('hit-button');
let stayButton = document.getElementById('stay-button');
let gameStarted = false,
 gameOver = false,
 playerWon = false,
 dealerCards = [],
 playerCards = [],
 dealerScore = 0,
 playerScore = 0,
 deck = [];
hitButton.style.display = 'none';
stayButton.style.display = 'none';
showStatus();
let myClassDeck = new Deck();
newGameButton.addEventListener('click', function () {
 gameStarted = true;
 gameOver = false;
 playerWon = false;
 myClassDeck.createDeck();
 myClassDeck.shuffleDeck(myClassDeck);
 dealerCards = [getNextCard(), getNextCard()];
 playerCards = [getNextCard(), getNextCard()];
 newGameButton.style.display = 'none';
 hitButton.style.display = 'inline';
 stayButton.style.display = 'inline';
 showStatus();
})
let suits = ['Hearts', 'Clubs', 'Diamonds', 'Spades'];
let values = ['As', 'King', 'Queen', 'Jack',
 'Ten', 'Nine', 'Eight', 'Seven', 'Six',
 'Five', 'Four', 'Three', 'Two'
]
function getNextCard() {
 let nextCard = myClassDeck.deck.shift();
 console.log('card given is:', nextCard);
 return nextCard;
}
function getCardString(card) {
 return card.value + ' of ' + card.suit;
}
function showStatus() {
 if (!gameStarted) {
 textArea.innerText = 'Welcome to BlackJack!!!!!!!!!!';
 return;
 }
 for (let i = 0; i < myClassDeck.deck.length; i++) {
 textArea.innerText += '\n' + getCardString(myClassDeck.deck[i]);
 }
}

How could we improve it?

I think we should use constructor, and create get and set to deck into Deck.js

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Mar 24, 2018 at 14:03
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

If you start going the OOP way (which works great for this type of game), your next step should be to make the main game a class as well. That prevents having all your variables and functions in the global scope.

You can use arrow functions to prevent nested functions in a class. It's clearer to just call a method of the class. Now you can call newGame from other places as well.

class Game {
 constructor(){
 this.suits = ['Hearts', 'Clubs', 'Diamonds', 'Spades']
 this.textArea = document.getElementById('text-area')
 this.newGameButton = document.getElementById('new-game-button')
 this.myDeck = new Deck()
 this.newGameButton.addEventListener('click',()=>this.newGame())
 this.showStatus()
 }
 showStatus(){
 }
 newGame(){
 this.myDeck.createDeck()
 this.myDeck.shuffleDeck()
 }
}
new Game()
answered Mar 28, 2018 at 18:24
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.