{"id":3776,"date":"2023-07-18T01:25:28","date_gmt":"2023-07-18T01:25:28","guid":{"rendered":"https:\/\/nmi.cool\/advweb\/?page_id=3776"},"modified":"2026-03-01T21:49:05","modified_gmt":"2026-03-01T21:49:05","slug":"exercise-lets-play-cards","status":"publish","type":"page","link":"https:\/\/nmi.cool\/advweb\/unit-two-javascript\/week-six\/exercise-lets-play-cards\/","title":{"rendered":"Exercise: Let&#8217;s Play Cards"},"content":{"rendered":"\n<p>In this lesson we are about to take random numbers to another level by using them to construct poker hands with actual cards.<\/p>\n\n\n\n<p>Goal: Use JavaScript\u2019s Math.random() and array manipulation methods to build a simple 5-card draw experience using 52 playing card images and basic jQuery interactivity.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Download&nbsp;<a href=\"https:\/\/nmi.cool\/advweb\/wp-content\/uploads\/sites\/12\/2025\/10\/cards.zip\" data-type=\"attachment\" data-id=\"4533\">cards.zip<\/a>&nbsp;and move the unzipped folder to your work area.<\/li>\n\n\n\n<li>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.<\/li>\n\n\n\n<li>With a bit more poking around, you should also discover that there are 52 card images inside of the cards folder which are conveniently referenced by name in an array inside of cards.js.<\/li>\n\n\n\n<li>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. <\/li>\n\n\n\n<li>&nbsp;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. <pre class=\"wp-block-code\"><code>let deck = document.querySelector(\"#deck\");<\/code><\/pre> <\/li>\n\n\n\n<li>Next create the shuffle function that is going to sort the cards for us. <pre class=\"wp-block-code\"><code>function shuffle() {\n    let deck = document.querySelector(\"#deck\");\n    deck.innerHTML = \"\"; \/\/ clear the deck first<\/code><\/pre><\/li>\n\n\n\n<li>Now our job is to generate a suitable random number. Let&#8217;s do that by creating a new variable named outcome and setting it to Math.random as in<br><strong>let outcome = Math.random()<\/strong>. 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&#8217;re going to use a more sustainable approach. <pre class=\"wp-block-code\"><code>let outcome = Math.floor(Math.random() * cards.length);<br>console.log(outcome); \/\/ optional debug<\/code><\/pre><\/li>\n\n\n\n<li>Let&#8217;s start humbly and see if we can add just one card to the deck with code that starts something like: <pre class=\"wp-block-code\"><code>    deck.innerHTML = \"&lt;img src='cards\/\" + cards[outcome] + \"'&gt;\";<\/code><\/pre><\/li>\n\n\n\n<li>If things work properly, that should place one card in the deck, but we need five. Now it&#8217;s time to exercise your coding powers and add a loop. The for loop shown below would be a very functional starting point. <pre class=\"wp-block-code\"><code>    for (let i = 0; i &lt; 5; i++) {\n        let outcome = Math.floor(Math.random() * cards.length);\n        deck.innerHTML += \"&lt;img src='cards\/\" + cards[outcome] + \"'&gt;\";\n    }<\/code><\/pre><\/li>\n\n\n\n<li>Make sure you prevent repeating or infinite cards! Add the following to your function: <pre class=\"wp-block-code\"><code>    deck.innerHTML = \"\"; \/\/clear the deck before starting\n    deck.innerHTML += \"&lt;img src='cards\/\" + cards[outcome] + \"'&gt;\"; \/\/ Use += so cards accumulate instead of replace<\/code><\/pre><\/li>\n<\/ol>\n\n\n\n<p><strong>Now it&#8217;s time for some fun side quests.<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Place this at the end of your shuffle() function to make the cards draggable: <pre class=\"wp-block-code\"><code>    $(\"img\").draggable();<\/code><\/pre><\/li>\n\n\n\n<li>Add a function (still inside of shuffle()) that allows you to double click on a card to discard it: <pre class=\"wp-block-code\"><code>    $(\"img\").dblclick(function(){\n        $(this).hide();\n    });<\/code><\/pre><\/li>\n\n\n\n<li>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&#8217;ll use a new concepts: splice. Add this inside your for loop, right after drawing each card: <pre class=\"wp-block-code\"><code>cards.splice(outcome, 1);<\/code><\/pre><\/li>\n<\/ol>\n\n\n\n<p>Test it! Do you:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Get 5 cards each time?<\/li>\n\n\n\n<li>Avoid repeated cards?<\/li>\n\n\n\n<li>See cards disappear on double click?<\/li>\n\n\n\n<li>Notice the deck shrinking?<\/li>\n<\/ul>\n\n\n\n<p><strong>Time for some challenges.<\/strong><\/p>\n\n\n\n<p><strong>Add cards one at a time. <\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create a new button with an id of #addCard. This button will be tied to a new function in cards.js. You&#8217;ll need to create an if statement to make sure you have cards left. <pre class=\"wp-block-code\"><code>function addCard() {<br>    \/\/ Step 1: Make sure we still have cards left<br>    if (cards.length &gt; 0) {<br>        \/\/ Step 2: Select the deck area<br>        let deck = document.querySelector(\"#deck\");<\/code><\/pre><\/li>\n\n\n\n<li>Add the same parameters and methods from your other function: <pre class=\"wp-block-code\"><code>\/\/ Step 3: Get a random index from the remaining deck\n        let outcome = Math.floor(Math.random() * cards.length);\n\n        \/\/ Step 4: Display that card image inside the deck\n        deck.innerHTML += \"&lt;img src='cards\/\" + cards[outcome] + \"'&gt;\";\n\n        \/\/ Step 5: Remove that card from the array so it\u2019s not reused\n        cards.splice(outcome, 1);\n\n        \/\/ Step 6: Make all cards draggable again\n        $(\"img\").draggable();\n\n        \/\/ Step 7: Re-attach double-click discard functionality\n        $(\"img\").dblclick(function(){\n            $(this).hide();\n        });\n    }<\/code><\/pre><\/li>\n\n\n\n<li>Finish it with an else statement that lets the user know if the deck is empty: <pre class=\"wp-block-code\"><code>else {\n        alert(\"No more cards left in the deck!\");\n    }\n}<\/code><\/pre><\/li>\n<\/ol>\n\n\n\n<p><strong>Reset the Deck<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Add a reset button that is ready to rock with a new function. <pre class=\"wp-block-code\"><code>&lt;button onclick=\"reset()\"&gt;Reset&lt;\/button&gt;<\/code><\/pre><\/li>\n\n\n\n<li>What was the part of the other functions that reset the deck? Apply that here in the new function. <\/li>\n<\/ol>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Need a hint?<\/summary>\n<pre class=\"wp-block-code\"><code>function reset() {\n    document.querySelector(\"#deck\").innerHTML = \"\";\n}<\/code><\/pre>\n<\/details>\n\n\n\n<p><strong>Add a second hand<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Add another &lt;div&gt; to provide space for a second hand. Give it an id of #deck2.<\/li>\n\n\n\n<li>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. <\/li>\n<\/ol>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>One function to rule them all:<\/summary>\n<pre class=\"wp-block-code\"><code>function dealHands() {\n    \/\/ Step 1: Target both hand areas\n    let deck1 = document.querySelector(\"#deck\");\n    let deck2 = document.querySelector(\"#deck2\");\n\n    \/\/ Step 2: Clear out both decks before dealing\n    deck1.innerHTML = \"\";\n    deck2.innerHTML = \"\";\n\n    \/\/ Step 3: Deal 5 cards to each hand (10 total)\n    for (let i = 0; i &lt; 5; i++) {\n        \/\/ --- FIRST HAND ---\n        let outcome1 = Math.floor(Math.random() * cards.length);\n        deck1.innerHTML += \"&lt;img src='cards\/\" + cards&#091;outcome1] + \"'&gt;\";\n        cards.splice(outcome1, 1); \/\/ remove card from deck\n\n        \/\/ --- SECOND HAND ---\n        let outcome2 = Math.floor(Math.random() * cards.length);\n        deck2.innerHTML += \"&lt;img src='cards\/\" + cards&#091;outcome2] + \"'&gt;\";\n        cards.splice(outcome2, 1); \/\/ remove card from deck\n    }\n\n    \/\/ Step 4: Make all images draggable and discardable\n    $(\"img\").draggable();\n    $(\"img\").dblclick(function(){\n        $(this).hide();\n    });\n}<\/code><\/pre>\n<\/details>\n","protected":false},"excerpt":{"rendered":"<p>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\u2019s Math.random() and array manipulation methods to build a simple 5-card draw experience using 52 playing card images and basic jQuery interactivity. Now it&#8217;s time for some fun side quests. &hellip; <a href=\"https:\/\/nmi.cool\/advweb\/unit-two-javascript\/week-six\/exercise-lets-play-cards\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Exercise: Let&#8217;s Play Cards<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":3694,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-3776","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/nmi.cool\/advweb\/wp-json\/wp\/v2\/pages\/3776","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nmi.cool\/advweb\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/nmi.cool\/advweb\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/nmi.cool\/advweb\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nmi.cool\/advweb\/wp-json\/wp\/v2\/comments?post=3776"}],"version-history":[{"count":14,"href":"https:\/\/nmi.cool\/advweb\/wp-json\/wp\/v2\/pages\/3776\/revisions"}],"predecessor-version":[{"id":4788,"href":"https:\/\/nmi.cool\/advweb\/wp-json\/wp\/v2\/pages\/3776\/revisions\/4788"}],"up":[{"embeddable":true,"href":"https:\/\/nmi.cool\/advweb\/wp-json\/wp\/v2\/pages\/3694"}],"wp:attachment":[{"href":"https:\/\/nmi.cool\/advweb\/wp-json\/wp\/v2\/media?parent=3776"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}