Reputation: 165
I am trying to build a game based on random card selection. The player draws a card, once the card has been drawn the card will not be drawn again.
I've tried to make it work but I'm getting an error on my website saying "Uncaught TypeError: currentCard.filter is not a function"
Here is my code:
cards = [
'clubs-ace',
'clubs-2',
'clubs-3',
'clubs-4',
'clubs-5',
'clubs-6',
'clubs-7',
'clubs-8',
'clubs-9',
'clubs-10',
'clubs-jack',
'clubs-queen',
'clubs-king',
'diamonds-ace',
'diamonds-2',
'diamonds-3',
'diamonds-4',
'diamonds-5',
'diamonds-6',
'diamonds-7',
'diamonds-8',
'diamonds-9',
'diamonds-10',
'diamonds-jack',
'diamonds-queen',
'diamonds-king',
'hearts-ace',
'hearts-2',
'hearts-3',
'hearts-4',
'hearts-5',
'hearts-6',
'hearts-7',
'hearts-8',
'hearts-9',
'hearts-10',
'hearts-jack',
'hearts-queen',
'hearts-king',
'spades-ace',
'spades-2',
'spades-3',
'spades-4',
'spades-5',
'spades-6',
'spades-7',
'spades-8',
'spades-9',
'spades-10',
'spades-jack',
'spades-queen',
'spades-king'
];
var currentCard = "";
var kingsCup = 0;
function drawCard() {
var randomNumber = Math.floor(Math.random() * (currentCard.length));
currentCard = currentCard.filter((e, i) => i !== randomNumber);
console.log(currentCard.length);
switch(currentCard[randomNumber]) {
case 1:
document.getElementById("cards").src="assets/js/games/cards/clubs-ace.png";
break;
case 2:
document.getElementById("cards").src="assets/js/games/cards/clubs-2.png";
break;
case 3:
document.getElementById("cards").src="assets/js/games/cards/clubs-3.png";
break;
case 4:
document.getElementById("cards").src="assets/js/games/cards/clubs-4.png";
break;
case 5:
document.getElementById("cards").src="assets/js/games/cards/clubs-5.png";
break;
case 6:
document.getElementById("cards").src="assets/js/games/cards/clubs-6.png";
break;
case 7:
document.getElementById("cards").src="assets/js/games/cards/clubs-7.png";
break;
case 8:
document.getElementById("cards").src="assets/js/games/cards/clubs-8.png";
break;
case 9:
document.getElementById("cards").src="assets/js/games/cards/clubs-9.png";
break;
}
}
I'm a beginner at JS and the code could probably be written in a neater and more efficient way, so please excuse the long, messy code.
What am I doing wrong?
Upvotes: 1
Views: 2280
Reputation: 4267
You might want to do something like this... Keep two lists handy that handles the cards. The first list stores the entire cards and the second one stores the currentCards
list. So every time you draw a card from the main list cards
, it is added to the currentCards
and removed from the main cards
, so you will never repeat the same card. The randomNumber
will be updated as the list of cards
list gets smaller as well.
var drawnCardsDisplay = document.getElementById('drawnCards');
var cards = [
'clubs-ace',
'clubs-2',
'clubs-3',
'clubs-4',
'clubs-5',
'clubs-6',
'clubs-7',
'clubs-8',
'clubs-9',
'clubs-10',
'clubs-jack',
'clubs-queen',
'clubs-king',
'diamonds-ace',
'diamonds-2',
'diamonds-3',
'diamonds-4',
'diamonds-5',
'diamonds-6',
'diamonds-7',
'diamonds-8',
'diamonds-9',
'diamonds-10',
'diamonds-jack',
'diamonds-queen',
'diamonds-king',
'hearts-ace',
'hearts-2',
'hearts-3',
'hearts-4',
'hearts-5',
'hearts-6',
'hearts-7',
'hearts-8',
'hearts-9',
'hearts-10',
'hearts-jack',
'hearts-queen',
'hearts-king',
'spades-ace',
'spades-2',
'spades-3',
'spades-4',
'spades-5',
'spades-6',
'spades-7',
'spades-8',
'spades-9',
'spades-10',
'spades-jack',
'spades-queen',
'spades-king'
];
var currentCards = [];
function drawCard() {
// ue cards here instead of currentCards
var randomNumber = Math.floor(Math.random() * (cards.length - 1));
currentCards.push(
// Run an immediately self executing function expression
(function(){
// store the elected card temorarily
var tempSelectedCard = cards[randomNumber];
// Remove that card from the main cards
cards = getUnDrawnCards(randomNumber);
// return the selected card and store it inside the currentCards array
return tempSelectedCard;
})()
);
// After Drawing the card, display it.
showDrawnCards(currentCards);
}
function getUnDrawnCards(cardPositionToBeRemoved) // returns card[]
{
if(cardPositionToBeRemoved)
{
// create a temporary array storage
var tempNewCards = [];
// Loop through the cards
cards.forEach(function(card, index)
{
// if the card to be removed does matches the current card position
if(index !== cardPositionToBeRemoved)
{
// Add it to the tempArrayList
tempNewCards.push(cards[index]);
}
// At tis poist the matched index will not be part of the cards anymore
});
// Return tempNewCards
return tempNewCards;
}
return [];
}
function showDrawnCards(drawnCardsArray)
{
if(drawnCardsArray.length > 0)
{
drawnCardsDisplay.innerHTML = '';
drawnCardsArray.map(function(card)
{
var drawn_card = document.createElement('span');
drawn_card.innerHTML = card;
drawnCardsDisplay.appendChild(drawn_card);
});
}
}
span{
display: inline-block;
width: 120px;
line-height: 40px;
text-align: center;
border: thin solid #dbdbdb;
margin: 5px;
}
button{
margin-top: 15px;
}
<div id="drawnCards"></div>
<button onClick="drawCard()">Click to Draw</button>
Upvotes: 0
Reputation: 19
i believe this should work.
const selectableCards = [
'clubs-ace',
'clubs-2',
'clubs-3',
'clubs-4',
'clubs-5',
'clubs-6',
'clubs-7',
'clubs-8',
'clubs-9',
'clubs-10',
'clubs-jack',
'clubs-queen',
'clubs-king',
'diamonds-ace',
'diamonds-2',
'diamonds-3',
'diamonds-4',
'diamonds-5',
'diamonds-6',
'diamonds-7',
'diamonds-8',
'diamonds-9',
'diamonds-10',
'diamonds-jack',
'diamonds-queen',
'diamonds-king',
'hearts-ace',
'hearts-2',
'hearts-3',
'hearts-4',
'hearts-5',
'hearts-6',
'hearts-7',
'hearts-8',
'hearts-9',
'hearts-10',
'hearts-jack',
'hearts-queen',
'hearts-king',
'spades-ace',
'spades-2',
'spades-3',
'spades-4',
'spades-5',
'spades-6',
'spades-7',
'spades-8',
'spades-9',
'spades-10',
'spades-jack',
'spades-queen',
'spades-king'
]
const currentCard = {}
const cardsAlreadySelected = []
const kingsCup = 0
const drawCard = () => {
const randomNumber = Math.floor(Math.random() * (selectableCards.length))
const currentCard = selectableCards.splice(randomNumber, 1)
console.log(currentCard.length)
document.getElementById("cards").src = `assets/js/games/cards/${currentCard}.png`
}
Upvotes: 0
Reputation: 35812
Specifically responding to:
I'm a beginner at JS and the code could probably be written in a neater and more efficient way, so please excuse the long, messy code.
As a general rule, you want to try and separate your data and logic, but your code mixes both.
Consider instead something like:
const cardsById = {
1: 'clubs-ace'
2: 'clubs-2'
// ...
};
document.getElementById("cards").src =
'assets/js/games/cards/' + cardsById[randomNumber]+ '.png';
That way you have your data (cardsById
) with just the unique data parts (the image names and IDs), and the logic is separate.
As for not picking the same card twice, one option would be to remove each card as you pick it using slice
as @Crayon Violent suggested in the comments (although I'd recommend splice
, with a "p", instead for that).
Another would be to add each card's ID to a second alreadyPicked
array, and then check that array when you generate a random ID; if it's one you already picked, re-pick. Which style is better depends on your specific code.
Upvotes: 2