Shuffling HTML Elements
Motivation
For my second portfolio project for Code Institute, I implemented a Rock! Paper! Scissors! Lizard! Spock! game. To make the rounds a bit more challenging, the user had a limited time to make a choice once the computer's choice had been revealed. I wanted the game tiles, which contained images for the user's choices, to be shuffled after each round in the game to add just a little extra hand-eye coordination to the game.
The task involves shuffling the array of game tile objects. The problem, however, is that JavaScript does not have a built-in shuffle()
method for array elements as other programming languages do. In this article, I show you how to shuffle the elements of an array in JavaScript and apply it to a game.
The HTML
Here is how I have set up the HTML for the game. The <img>
elements are nested within a <game-tile-panel>
which is custom HTML element. (If you want to learn how to make your own custom HTML elements, check out this article I wrote which shows you how.)
<game-tile-panel class="flex-container tile-area"> <img id="rock-tile" class="game-tile" data-value="rock" src="assets/images/rock.png" alt="rock"> <img id="paper-tile" class="game-tile" data-value="paper" src="assets/images/paper.png" alt="paper"> <img id="scissors-tile" class="game-tile" data-value="scissors" src="assets/images/scissors.png" alt="scissors"> <img id="lizard-tile" class="game-tile" data-value="lizard" src="assets/images/lizard.png" alt="lizard"> <img id="spock-tile" class="game-tile" data-value="spock" src="assets/images/spock.png" alt="spock"> </game-tile-panel>
Shuffling an Array's Elements
Here is the code for a method to shuffle an array's elements. It is taken from the following Stack Overflow article: How to randomize a JavaScript array?.
function shuffle(array) { let currentIndex = array.length, randomIndex; // While there remain elements to shuffle. while (currentIndex != 0) { // Pick a remaining element. randomIndex = Math.floor(Math.random() * currentIndex); currentIndex--; // And swap it with the current element. [array[currentIndex], array[randomIndex]] = [ array[randomIndex], array[currentIndex]]; } return array; }
We first create two variables. One is called currentIndex and set its value to the length of the array. In the same line, we also declare randomIndex. Its value is uninitialized.
We setup a while loop that counts down from the current index.
In the next line, we create a randomIndex variable and store a random index. Notice that we use
Math.floor(Math.random()*currentIndex)
. Math.floor() rounds the argument down to the next integer. Math.random() will generate a random number between 0 and 1. Multiplying this decimal by thecurrentIndex
will ensure that the output will be between 0 and currentIndex.The method that swaps is a shorthand:
array[currentIndex], array[randomIndex] = [ array[randomIndex], array[currentIndex]];
This will swap the values of array[currentIndex] and array[randomIndex]. A traditional way to do it would be like this:
let temp = array[currentIndex]; array[currentIndex] = array[tempIndex]; array[tempIndex] = temp;
- In the last line, the array is returned.
Shuffling the HTML Elements on the Screen
function shuffleTiles() { let tilePanelArray = document.getElementsByTagName("game-tile-panel"); let tilePanel = tilePanelArray[0]; let newTileArray = []; let tiles = tilePanel.children; for (let i = 0; i < tiles.length; i++) { newTileArray.push(tiles[i]); } newTileArray = shuffle(newTileArray); tilePanel.innerHTML = ""; for (let tile of newTileArray) { tilePanel.appendChild(tile); } }
We first get all of the elements in the
<game-tile-panel>
. Notice that the method is getElementsByTagName() which returns an array. Since there is only one<game-tile-panel>
, we know that the first element of this array must be the<game-tile-panel>
. We therefore fetch it withlet tilePanel = tilePanelArray[0];
and store it in the variable tilePanel.We then declare an empty array called newTileArray.
The tiles themselves are stored in a variable
tiles
and we retrieve them by calling tilePanel.children.In the next line we copy the concents of tiles into newTileArray. We have to do this because the
tiles
array is immutable.We call the shuffle function, passing the contents of newTileArray as an argument. shuffle() then returns a new array with the same contents, but in a random order. This new array is assigned to newTileArray.
The tilePanel is emptied of all its contents by setting its innerHTML to an empty string.
For each tile in the newTileArray, the tile is appended to the tilePanel.
That is all there is to it!