In this lesson we are about to take random numbers to another level by using them to construct poker hands with actual cards.
Goal: Use JavaScript’s Math.random() and array manipulation methods to build a simple 5-card draw experience using 52 playing card images and basic jQuery interactivity.
- Download cards.zip and move the unzipped folder to your work area.
- Look at cards.html. As you can see, it already contains a div named #deck, a link to cards.js, and a button that calls a function named shuffle.
- With a bit more poking around, you should also discover that there there are 52 card images inside of the cards folder which are conveniently referenced by name in an array inside of cards.js.
- Your job at this point is to build that function inside of cards.js and get it to randomly assemble the images of five separate cards inside of #deck.
- Now that the preliminaries are out of the way, the first step is to create a variable named deck and assign it to the #deck div tag.
let deck = document.querySelector("#deck");
- Next create the shuffle function that is going to sort the cards for us.
function shuffle() { let deck = document.querySelector("#deck"); deck.innerHTML = ""; // clear the deck first
- Now our job is to generate a suitable random number. Let’s do that by creating a new variable named outcome and setting it to Math.random as in
let outcome = Math.random(). As you know, this will generate a fraction between 0 and 1. We need a much bigger number. Since we know there are 52 cards in the deck, we could multiply it by 52. However, we’re going to use a more sustainable approach.let outcome = Math.random() * cards.length;
console.log(outcome); // optional debug - Let’s start humbly and see if we can add just one card to the deck with code that starts something like:
deck.innerHTML = "<img src='cards/" + cards[outcome] + "'>";
- If things work properly, that should place one card in the deck, but we need five. Now it’s time to exercise your coding powers and add a loop. The for loop shown below would be a very functional starting point.
for (let i = 0; i < 5; i++) { let outcome = Math.floor(Math.random() * cards.length); deck.innerHTML += "<img src='cards/" + cards[outcome] + "'>"; }
- Make sure you prevent repeating or infinite cards! Add the following to your function:
deck.innerHTML = ""; //clear the deck before starting deck.innerHTML += "<img src='cards/" + cards[outcome] + "'>"; // Use += so cards accumulate instead of replace
Now it’s time for some fun side quests.
- Place this at the end of your shuffle() function to make the cards draggable:
$("img").draggable();
- Add a function (still inside of shuffle()) that allows you to double click on a card to discard it:
$("img").dblclick(function(){ $(this).hide(); });
- Finally, we need to make sure that cards are not being reused. That means, we need to remove them from the possible cards (the array) when they display. As the deck shrinks, we also need to change the random number generator to respond to the adjust number of cards. We’ll use two new concepts: splice and Math.floor. First, add this inside your for loop, right after drawing each card:
cards.splice(outcome, 1);
- Then, update the random number generator to:
let outcome = Math.floor(Math.random() * cards.length);
Test it! Do you:
- Get 5 cards each time?
- Avoid repeated cards?
- See cards disappear on double click?
- Notice the deck shrinking?
Time for some challenges.
Add cards one at a time.
- Create a new button with an id of #addCard. This button will be tied to a new function in cards.js. You’ll need to create an if statement to make sure you have cards left.
function addCard() {
// Step 1: Make sure we still have cards left
if (cards.length > 0) {
// Step 2: Select the deck area
let deck = document.querySelector("#deck"); - Add the same parameters and methods from your other function:
// Step 3: Get a random index from the remaining deck let outcome = Math.floor(Math.random() * cards.length); // Step 4: Display that card image inside the deck deck.innerHTML += "<img src='cards/" + cards[outcome] + "'>"; // Step 5: Remove that card from the array so it’s not reused cards.splice(outcome, 1); // Step 6: Make all cards draggable again $("img").draggable(); // Step 7: Re-attach double-click discard functionality $("img").dblclick(function(){ $(this).hide(); }); }
- Finish it with an else statement that lets the user know if the deck is empty:
else { alert("No more cards left in the deck!"); } }
Reset the Deck
- Add a reset button that is ready to rock with a new function.
<button onclick="reset()">Reset</button>
- What was the part of the other functions that reset the deck? Apply that here in the new function.
Need a hint?
function reset() {
document.querySelector("#deck").innerHTML = "";
}
Add a second hand
- Add another <div> to provide space for a second hand. Give it an id of #deck2.
- To start, build out another function that talks to the second div. Once you get that working, come back here to learn how to control both of them with one function.
One function to rule them all:
function dealHands() {
// Step 1: Target both hand areas
let deck1 = document.querySelector("#deck");
let deck2 = document.querySelector("#deck2");
// Step 2: Clear out both decks before dealing
deck1.innerHTML = "";
deck2.innerHTML = "";
// Step 3: Deal 5 cards to each hand (10 total)
for (let i = 0; i < 5; i++) {
// --- FIRST HAND ---
let outcome1 = Math.floor(Math.random() * cards.length);
deck1.innerHTML += "<img src='cards/" + cards[outcome1] + "'>";
cards.splice(outcome1, 1); // remove card from deck
// --- SECOND HAND ---
let outcome2 = Math.floor(Math.random() * cards.length);
deck2.innerHTML += "<img src='cards/" + cards[outcome2] + "'>";
cards.splice(outcome2, 1); // remove card from deck
}
// Step 4: Make all images draggable and discardable
$("img").draggable();
$("img").dblclick(function(){
$(this).hide();
});
}