I am trying to implement a shuffled deck of cards in Javascript, but I am running into behavior I am having a hard time understanding.
Here is my code. For conciseness, this deck contains only cards with faces 1-5 and only two suits:
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
function getDeck() {
let values = Array(5).fill().map((element, index) => index + 1);
let suits = ['H', 'D'];
let deck = new Array();
values.forEach(function(value) {
suits.forEach(function(suit) {
let card = {
'value': value,
'suit': suit
}
deck.push(card);
})
})
return deck
}
var deck = getDeck();
console.log(deck);
shuffleArray(deck);
console.log(deck);
I took the shuffle in place code from this answer
I would expect for the first log statement to show an unshuffled deck and the second log statement to show a shuffled deck. Instead, they both show identically shuffled decks! It's as if the randomization is reaching backwards in time!
To make matters worse, when I was first trying to code a minimal example, I didn't bother with values and suits and tried only to shuffle a small array, but in that case, it worked exactly as expected, only deepening my confusion...
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
function getDeck() {
let deck = [1, 2, 3, 4, 5];
return deck;
}
var deck = getDeck();
console.log(deck);
shuffleArray(deck);
console.log(deck);
In that case, the output is
What's going on? Why does the simple case work but the more complex case not seem to? What about timing or scoping am I misunderstanding?
You're modifying directly on the main array (the original deck) and console.log is not synchronous, so that is why both are the same. I'd suggest you clone another array and modify that new array instead
const newArray = [...array] //clone the original array to the new array
function shuffleArray(array) {
const newArray = [...array]
for (var i = newArray.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = newArray[i];
newArray[i] = newArray[j];
newArray[j] = temp;
}
return newArray
}
function getDeck() {
let values = Array(5).fill().map((element, index) => index + 1);
let suits = ['H', 'D'];
let deck = new Array();
values.forEach(function(value) {
suits.forEach(function(suit) {
let card = {
'value': value,
'suit': suit
}
deck.push(card);
})
})
return deck
}
var deck = getDeck();
console.log(deck);
const newDeck = shuffleArray(deck);
console.log(newDeck);
.as-console-wrapper { max-height: 100% !important; top: 0; }