Welcome to yet another exciting tutorial by Coding Artist. Building projects is one of the best ways to learn JavaScript. So in today’s tutorial let us expand our javascript knowledge with a fun and easy-to-build project called ‘Sliding Puzzle Game’. To build this project we need HTML, CSS, and Javascript.
Video Tutorial:
Before we move on to the actual tutorial, you can check out the video tutorial of this post here. If you like video tutorials like this subscribe to my YouTube channel, where I post new projects based on HTML, CSS, and Javascript regularly.
Project Folder Structure:
Let’s build the project folder structure before we begin writing the code. We create a project folder called ‘Sliding Puzzle Game’. Inside this folder, we have three files. These files are index.html, style.css, and script.js. Apart from these, we have images for our puzzle and the original image.
HTML:
We begin with the HTML Code. First, create a file called – ‘index.html’. Copy the code below and paste it into your HTML file.
<!DOCTYPE html> <html lang="en"> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Sliding Puzzle Game</title> <!-- Google Fonts --> <link href="https://fonts.googleapis.com/css2?family=Poppins&display=swap" rel="stylesheet" /> <!-- Stylesheet --> <link rel="stylesheet" href="style.css" /> </head> <body> <div class="cover-screen"> <p id="result"></p> <button id="start-button">Start Game</button> </div> <div id="moves"></div> <div class="slider-game"> <div class="container"></div> <div class="original-image"> <img src="original_image.png" alt="" /> </div> </div> <!-- Script --> <script src="script.js"></script> </body> </html>
CSS:
Next, we style our game using CSS. For this copy, the code provided to you below and paste it into your stylesheet.
* { padding: 0; margin: 0; box-sizing: border-box; font-family: "Poppins", sans-serif; } img { max-width: 100%; } .slider-game { width: 80%; display: flex; justify-content: space-between; margin: 0 auto; margin-top: 5%; } .container { display: grid; width: 25em; height: 25em; grid-template-columns: repeat(3, 1fr); grid-auto-rows: 8em; } .original-image { width: 25em; height: 25em; } .image-container { border: 1px solid #ffffff; } .cover-screen { position: absolute; top: 0; left: 0; background-color: #edb506; width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center; } #start-button { font-size: 1.2em; padding: 0.8em 2em; border: none; border-radius: 3em; cursor: pointer; } #moves { position: relative; margin: 1em; text-align: right; } .hide { display: none; } @media only screen and (max-width: 768px) { .slider-game { flex-direction: column; } .container { width: 20em; height: 20em; grid-auto-rows: 6em; } .original-image { width: 20em; height: 20em; } }
Javascript:
Next, we style our game using CSS. For this copy, the code provided to you below and paste it into your stylesheet.
Finally, we add functionality to the game using Javascript. Once again copy the code below and paste it into your script file.
The game involves a grid of 3×3 squares, with each square containing an image. The goal is to slide the image parts around to get them in the correct order, with one blank square to help with the sliding.
The steps involved in making this code are:
- First, start with variable initializations and references.
- Then call the ‘randomImages’ function to fill an array with random values for the images.
- Then call the ‘gridGenerator’ function to generate the game grid based on the randomized image array.
- When the user clicks on an image the ‘selectImage’ function is called. It checks whether the clicked image is adjacent to the blank image and swaps their positions if they are. It also increments the moves count and checks whether the user has won the game.
- The start button event listener initializes the game by generating a new grid and resetting the moves count to zero.
- Finally, create a function so that when the window loads we could display the cover screen.
//Initial References const moves = document.getElementById("moves"); const container = document.querySelector(".container"); const startButton = document.getElementById("start-button"); const coverScreen = document.querySelector(".cover-screen"); const result = document.getElementById("result"); let currentElement = ""; let movesCount, imagesArr = []; const isTouchDevice = () => { try { //We try to create TouchEvent (it would fail for desktops ad throw error) document.createEvent("TouchEvent"); return true; } catch (e) { return false; } }; //Random number for image const randomNumber = () => Math.floor(Math.random() * 8) + 1; //Get row and column value from data-position const getCoords = (element) => { const [row, col] = element.getAttribute("data-position").split("_"); return [parseInt(row), parseInt(col)]; }; //row1, col1 are image co-ordinates while row2 amd col2 are blank image co-ordinates const checkAdjacent = (row1, row2, col1, col2) => { if (row1 == row2) { //left/right if (col2 == col1 - 1 || col2 == col1 + 1) { return true; } } else if (col1 == col2) { //up/down if (row2 == row1 - 1 || row2 == row1 + 1) { return true; } } return false; }; //Fill array with random value for images const randomImages = () => { while (imagesArr.length < 8) { let randomVal = randomNumber(); if (!imagesArr.includes(randomVal)) { imagesArr.push(randomVal); } } imagesArr.push(9); }; //Generate Grid const gridGenerator = () => { let count = 0; for (let i = 0; i < 3; i++) { for (let j = 0; j < 3; j++) { let div = document.createElement("div"); div.setAttribute("data-position", `${i}_${j}`); div.addEventListener("click", selectImage); div.classList.add("image-container"); div.innerHTML = `<img src="image_part_00${ imagesArr[count] }.png" class="image ${ imagesArr[count] == 9 ? "target" : "" }" data-index="${imagesArr[count]}"/>`; count += 1; container.appendChild(div); } } }; //Click the image const selectImage = (e) => { e.preventDefault(); //Set currentElement currentElement = e.target; //target(blank image) let targetElement = document.querySelector(".target"); let currentParent = currentElement.parentElement; let targetParent = targetElement.parentElement; //get row and col values for both elements const [row1, col1] = getCoords(currentParent); const [row2, col2] = getCoords(targetParent); if (checkAdjacent(row1, row2, col1, col2)) { //Swap currentElement.remove(); targetElement.remove(); //Get image index(to be used later for manipulating array) let currentIndex = parseInt(currentElement.getAttribute("data-index")); let targetIndex = parseInt(targetElement.getAttribute("data-index")); //Swap Index currentElement.setAttribute("data-index", targetIndex); targetElement.setAttribute("data-index", currentIndex); //Swap Images currentParent.appendChild(targetElement); targetParent.appendChild(currentElement); //Array swaps let currentArrIndex = imagesArr.indexOf(currentIndex); let targetArrIndex = imagesArr.indexOf(targetIndex); [imagesArr[currentArrIndex], imagesArr[targetArrIndex]] = [ imagesArr[targetArrIndex], imagesArr[currentArrIndex], ]; //Win condition if (imagesArr.join("") == "123456789") { setTimeout(() => { //When games ends display the cover screen again coverScreen.classList.remove("hide"); container.classList.add("hide"); result.innerText = `Total Moves: ${movesCount}`; startButton.innerText = "RestartGame"; }, 1000); } //Increment a display move movesCount += 1; moves.innerText = `Moves: ${movesCount}`; } }; //Start button click should display the container startButton.addEventListener("click", () => { container.classList.remove("hide"); coverScreen.classList.add("hide"); container.innerHTML = ""; imagesArr = []; randomImages(); gridGenerator(); movesCount = 0; moves.innerText = `Moves: ${movesCount}`; }); //Display start screen first window.onload = () => { coverScreen.classList.remove("hide"); container.classList.add("hide"); };
Go ahead and customize the project the way you like. If you have any queries, suggestions, or feedback comment below. Download the source code by clicking on the ‘Download Code’ button below.
what is the password of code file