Image Puzzle Game with JavaScript

From this tutorial you will know how to make Image Puzzle Game using JavaScript. If you are a beginner and want to improve your JavaScript knowledge then Picture Puzzle Game is a must try for you.

I have used HTML, CSS and JavaScript to create this Sliding Image Puzzle game. JavaScript used here is a bit difficult but I have explained step by step.

Image Puzzle Game in JavaScript

An image puzzle game with JavaScript is an interactive web-based application that challenges users to rearrange scrambled pieces of an image to reconstruct the original picture. 

This type of game is both entertaining and engaging, making it a popular choice for web developers looking to create interactive content.

See the Pen Untitled by Growthpanda (@Growthpanda) on CodePen.

To create this Image Puzzle Game first I created a button. Clicking on that button will show two sections. The complete image can be seen in one section. The top section shows many pieces of the original image. Arrange the pieces of images to complete this game.

Slide Puzzle Game in HTML CSS JavaScript

Building an image puzzle game with JavaScript provides a hands-on opportunity for web developers to practice their skills in HTML, CSS, and JavaScript, and it offers an enjoyable experience for users who like to solve puzzles and engage with interactive content on the web.

Step 1: Structure of Image Puzzle Game

Start by creating the HTML structure for your Image Puzzle game. Include a container for the puzzle board and a placeholder for the image. Additionally, you’ll need buttons to shuffle the puzzle pieces and restart the game. 

    <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="https://groundtutorial.com/wp-content/uploads/2024/01/original_image.png" alt="" />
      </div>
    </div>

Step 2: Design the Image Puzzle Game

Add some basic styling to enhance the visual appeal of your puzzle game. You can adjust the styles based on your preferences and the overall theme of your website.

The basic design of the game and the design of the webpage are done by the following codes.

* {
  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%;
}

All other elements of the game are designed by following codes.

.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;
}

The following CSS is used to make this JavaScript Image Puzzle Game responsive.

@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;
  }
}

Step 3: JavaScript for Sliding Image Puzzle

Now, let’s implement the JavaScript logic for the image puzzle game. This includes loading the image, creating puzzle pieces, shuffling them, and handling user interactions.

1: Initial References
// 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 = [];
  • moves, container, startButton, coverScreen, and result are variables that store references to various HTML elements by querying the document using document.getElementById and document.querySelector.

  • currentElement is a variable to keep track of the currently clicked puzzle piece.

  • movesCount is a variable to store the number of moves made by the player.

  • imagesArr is an array that will hold the order of the puzzle pieces.

2: Check for Touch Device
const isTouchDevice = () => {
  try {
    // We try to create TouchEvent (it would fail for desktops and throw an error)
    document.createEvent("TouchEvent");
    return true;
  } catch (e) {
    return false;
  }
};

This function isTouchDevice checks if the current device is a touch-enabled device by attempting to create a TouchEvent. If successful, it returns true; otherwise, it returns false.

3: Random Number Generation
const randomNumber = () => Math.floor(Math.random() * 8) + 1;

randomNumber is a function that generates a random number between 1 and 8 (inclusive) using Math.random() and Math.floor. This function will be used later to randomize the order of images in the puzzle.

4: Get Coordinates
const getCoords = (element) => {
  const [row, col] = element.getAttribute("data-position").split("_");
  return [parseInt(row), parseInt(col)];
};

getCoords is a function that takes a puzzle piece element and extracts its row and column coordinates from the data-position attribute. The coordinates are returned as an array of integers.

5: Check Adjacent
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;
};

checkAdjacent is a function that checks if two puzzle pieces are adjacent to each other on the grid. It takes the row and column coordinates of two pieces and returns true if they are adjacent, and false otherwise.

6: Fill Array with Random Values for Images
const randomImages = () => {
  while (imagesArr.length < 8) {
    let randomVal = randomNumber();
    if (!imagesArr.includes(randomVal)) {
      imagesArr.push(randomVal);
    }
  }
  imagesArr.push(9);
};

randomImages is a function that populates the imagesArr array with eight unique random values between 1 and 8, followed by a fixed value of 9. This array represents the order of the images in the puzzle.

7: 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="https://groundtutorial.com/wp-content/uploads/2024/01/image_part_00${
        imagesArr[count]
      }.png" class="image ${
        imagesArr[count] == 9 ? "target" : ""
      }" data-index="${imagesArr[count]}"/>`;
      count += 1;
      container.appendChild(div);
    }
  }
};

gridGenerator is a function that dynamically generates the HTML structure for the puzzle grid. It creates a 3×3 grid of div elements, each containing an img element representing a puzzle piece. Event listeners are added to each div for the click event, and the selectImage function is called when a piece is clicked.

8: 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 the game ends, display the cover screen again
        coverScreen.classList.remove("hide");
        container.classList.add("hide");
        result.innerText = `Total Moves: ${movesCount}`;
        startButton.innerText = "Restart Game";
      }, 1000);
    }
    // Increment and display move count
    movesCount += 1;
    moves.innerText = `Moves: ${movesCount}`;
  }
};

selectImage is a function that handles the click event on a puzzle piece. It checks if the clicked piece is adjacent to the blank space (target), and if so, it swaps their positions. The function then checks for a win condition and increments the move count.

9: Start Button Click
startButton.addEventListener("click", () => {
  container.classList.remove("hide");
  coverScreen.classList.add("hide");
  container.innerHTML = "";
  imagesArr = [];
  randomImages();
  gridGenerator();
  movesCount = 0;
  moves.innerText = `Moves: ${movesCount}`;
});

This code adds a click event listener to the “Start” button. When clicked, it hides the cover screen, displays the puzzle container, resets the HTML inside the container, generates new random images, sets up the puzzle grid, and resets the move count.

10: Display Start Screen First
window.onload = () => {
  coverScreen.classList.remove("hide");
  container.classList.add("hide");
};

This code sets up an event listener for the window.onload event. When the window is fully loaded, it displays the cover screen and hides the puzzle container.

Congratulations! You’ve now created a basic image puzzle game using HTML, CSS, and JavaScript. This project serves as a great starting point for those looking to delve into interactive web development and create engaging content for their users.

Please comment how you like this Image Puzzle Game. If you have any problem to understand the code of this project (Puzzle Game in Javascript HTML CSS) then you can comment me.

Leave a Comment