I am trying to create a card dealer that deals 5 cards when a button is clicked on the web page.
Basically, I want to create a card object with 2 attributes, 'suit' and 'value', once that is done I want to create an array of 52 card objects with random suits and values but ideally they should all be unique. Out of those 52 card objects, I would like 5 to be selected and displayed when the button is clicked. I am not getting any output from my function that is invoked from my button and I don't really understand why.
I am really new to Javascript and the professor teaching the intro class I am taking right now isn't very helpful, unfortunately.
Here is my current code:
<head>
<script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
</head>
<body>
<h1>Robo Dealer</h1>
<button onclick="dealHand();">Deal Hand</button>
<hr />
<div id="card_hand"></div>
<script>
// Declaring arrays for suits and values
const suits = ["Hearts", "Spades", "Clubs", "Diamonds"];
const values = [
"Ace",
2,
3,
4,
5,
6,
7,
8,
9,
10,
"Jack",
"Queen",
"King",
];
// Creating the card object
function cards(value, suit) {
this.value = value;
this.suit = suit;
}
// Creating array of 52 card objects
var deck = new Array();
function getDeck() {
for (i = 0; i < 52; i ) {
let cardObject = new cards(
values[Math.random()],
suits[Math.random()]
);
deck.push(cardObject);
}
return deck;
}
// Dealing hand of 5 card objects / outputting it to HTML
const dealHand = () => {
for (i = 0; i < 6; i ) {
$("#card_hand").html(getDeck());
}
return false; // prevent page reload
};
</script>
</body>
CodePudding user response:
Here is a tidied up version of your script, involving a Durstenfeld shuffle and a simple array containing the 52 cards deck. The first 5 cards of the shuffled deck are being dealt:
function shfl(a){ // Durstenfeld shuffle
for(let j,i=a.length;i>1;){
j=Math.floor(Math.random()*i--);
if (i!=j) [a[i],a[j]]=[a[j],a[i]]
}
return a
}
const suits = ["Hearts", "Spades", "Clubs", "Diamonds"],
values = ["Ace",2,3,4,5,6,7,8,9,10,"Jack","Queen","King"],
deck=[];
suits.forEach(s=>values.forEach(v=>
deck.push(s "-" v)));
console.log(shfl(deck).slice(0,5));
CodePudding user response:
OK, lets take a look at how you might approach this using objects. At the moment you're just iterating 52 times and selecting suits/values at random. What you probably should do is create the deck first by iterating over the suits and values, shuffle them, and then return the top five cards (like a casino would do).
There's a couple of bits of code here that you might not be familiar with but I'll include some notes, and some links to documentation at the end. I did get a little carried away with this but I hope that some of it is useful.
// Cache the element that will hold the hand,
// and the button, and add a listener to the button
const cardHand = document.querySelector('#card_hand');
const button = document.querySelector('button');
button.addEventListener('click', play);
// Set up the suits and values
const suits = ['♥', '♠', '♣', '♦'];
const values=["Ace",2,3,4,5,6,7,8,9,10,"Jack","Queen","King"];
// https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
function shuffle(array) {
let currentIndex = array.length, randomIndex;
while (currentIndex != 0) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
[array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
}
return array;
}
// Create a new deck of cards. Iterate over the suits first
// and have an inner loop that iterates over the values. That
// way you'll return a complete deck of 52 card objects. Each object
// is `{ value, suit }`. You may want to shuffle the deck at some point
// and you can use the Fisher/Yates algorithm for that (see above)
function createDeck() {
const deck = [];
for (i = 0; i < suits.length; i ) {
for (j = 0; j < values.length; j ) {
const card = { value: values[j], suit: suits[i] };
deck.push(card);
}
}
return shuffle(deck);
}
// Create some cards HTML - `map` over the `hand` array
// and then, using a template string, create some HTML for
// each card. `map` returns an array so we need to join it up
// into a single string after the iteration is complete
function createHTML(hand) {
return hand.map(card => {
return (
`<div >
${card.value} ${card.suit}
</div>`
);
}).join('');
}
// Create the deck
const deck = createDeck();
function play() {
// If there are enough cards in the deck
// take off the first 5 and display them
if (deck.length >= 5) {
const hand = deck.splice(0, 5);
cardHand.innerHTML = createHTML(hand);
} else {
cardHand.textContent = 'No cards remaining';
}
}
#card_hand { display: grid; grid-template-columns: repeat(auto-fit, minmax(80px, 1fr)); gap: 0.5em; }
.card { height: 100px; width: 70px; border: 1px solid #555; display: flex; justify-content: center; align-items: center; }
.♥, .♦ { color: red; }
<button type="button">Deal Hand</button>
<hr />
<div id="card_hand"></div>
Additional documentation