HomeJavascriptWordle Game Javascript

Wordle Game Javascript

Hey everyone. Welcome to today’s tutorial. In today’s tutorial, we will learn how to create a wordle app. To create this app, we need HTML, CSS, and JavaScript. This is an intermediate-level JavaScript tutorial. If you are interested to learn more about such tutorials, you can check out this playlist here.
 
Let’s first see how this game works. The goal of the game is to guess a word in 6 tries. The Green colour indicates the correct letter in a right place. The Yellow coloured blocks indicate the correct letter in the wrong place. However, grey blocks show the wrong letters.

Video Tutorial:

If you are interested to learn by watching a video tutorial rather than reading this block post, you can check out the video below. Also, subscribe to my YouTube channel where I post new tutorials tricks and tips every alternate day.

Project Folder Structure:

Let’s first create the project folder structure. We create a project folder called wordle. Inside this folder, we have three files these files index.html, style.css, and script.js. The first file is the HTML document. While the second one is the stylesheet. We finally have the script file.

HTML:

The HTML file consists of elements that build the layout of our app. Copy the code below and paste it into your HTML document.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Wordle</title>
    <!-- Google Font -->
    <link
      href="https://fonts.googleapis.com/css2?family=Poppins:wght@600&display=swap"
      rel="stylesheet"
    />
    <!-- Stylesheet -->
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <div class="wrapper">
      <div class="container"></div>
      <div class="rules">
        <img src="rules.svg" />
      </div>
      <div class="win-screen hide"></div>
    </div>
    <button class="submit hide">Submit</button>
    <!-- Script -->
    <script src="script.js"></script>
  </body>
</html>

CSS:

Next, we style the game using CSS. For this copy, the code provided to you below and paste it into your style sheet.

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  font-family: "Poppins", sans-serif;
}
body {
  height: 100vh;
  background: linear-gradient(135deg, #c59cff, #7e5bfb);
}
.wrapper {
  position: absolute;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
  display: flex;
  gap: 1em;
  background-color: #ffffff;
  padding: 1em;
  border-radius: 0.5em;
  box-shadow: 0 2.5em 3.75em rgba(30, 19, 70, 0.3);
}
.container,
.rules {
  width: 18.75em;
  height: 22.5em;
  position: relative;
}
.input-group {
  display: grid;
  width: 100%;
  grid-template-columns: auto auto auto auto auto;
  column-gap: 0.2em;
  margin: 0.2em 0;
}
.input-box {
  font-size: 2em;
  width: 1.7em;
  height: 1.7em;
  text-align: center;
  display: block;
  border: 1px solid #000000;
  line-height: 1;
  font-weight: 600;
  text-transform: uppercase;
}
.input-box:disabled {
  color: #000000;
}
.correct {
  background-color: #6aaa64;
}
.exists {
  background-color: #c9b458;
}
.incorrect {
  background-color: #787c7e;
}
.correct,
.exists,
.incorrect {
  color: #ffffff;
}
.win-screen {
  font-weight: 400;
  position: absolute;
  background-color: #ffffff;
  height: 100%;
  width: 100%;
  top: 0;
  left: 0;
  border-radius: 0.5em;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 1em;
}
.win-screen button {
  font-size: 1.2em;
  background-color: #7e5bfb;
  border: none;
  outline: none;
  font-weight: 400;
  padding: 0.8em 2em;
  border-radius: 2em;
}
.hide {
  display: none;
}
@media screen and (max-width: 700px) {
  .wrapper {
    flex-direction: column;
    transform: translateX(-50%);
    left: 50%;
    top: 0.5em;
  }
}

Javascript:

We finally had functionality to the game with JavaScript we do this in the following steps:
Create initial references
Create an initial setup
A function to generate a random word
A function to update input to disabled status and set focus
The logic for writing in inputs
Comparison logic

let words = [
  "Zebra",
  "Sling",
  "Crate",
  "Brick",
  "press",
  "truth",
  "sweet",
  "salty",
  "alert",
  "check",
  "roast",
  "toast",
  "shred",
  "cheek",
  "shock",
  "czech",
  "woman",
  "wreck",
  "court",
  "coast",
  "flake",
  "think",
  "smoke",
  "unrig",
  "slant",
  "ultra",
  "vague",
  "pouch",
  "radix",
  "yeast",
  "zoned",
  "cause",
  "quick",
  "bloat",
  "level",
  "civil",
  "civic",
  "madam",
  "house",
  "delay",
];
let container = document.querySelector(".container");
let winScreen = document.querySelector(".win-screen");
let submitButton = document.querySelector(".submit");
let inputCount, tryCount, inputRow;
let backSpaceCount = 0;
let randomWord, finalWord;

//Detect touch device
const isTouchDevice = () => {
  try {
    //We try to create TouchEvent (it would fail for desktops and throw error)
    document.createEvent("TouchEvent");
    return true;
  } catch (e) {
    return false;
  }
};

//Initial Setup
const startGame = async () => {
  winScreen.classList.add("hide");
  container.innerHTML = "";
  inputCount = 0;
  successCount = 0;
  tryCount = 0;
  finalWord = "";

  //Creating the grid
  for (let i = 0; i < 6; i++) {
    let inputGroup = document.createElement("div");
    inputGroup.classList.add("input-group");
    for (let j = 0; j < 5; j++) {
      //Disabled by default. We will enable one by one
      inputGroup.innerHTML += `<input type="text" class="input-box" onkeyup="checker(event)" maxlength="1" disabled>`;
    }
    await container.appendChild(inputGroup);
  }
  inputRow = document.querySelectorAll(".input-group");
  inputBox = document.querySelectorAll(".input-box");
  updateDivConfig(inputRow[tryCount].firstChild, false);
  randomWord = getRandom();
  console.log(randomWord);
};

//Get random word
const getRandom = () =>
  words[Math.floor(Math.random() * words.length)].toUpperCase();

//Update input to disabled status and set focus
const updateDivConfig = (element, disabledStatus) => {
  element.disabled = disabledStatus;
  if (!disabledStatus) {
    element.focus();
  }
};

//Logic for writing in the inputs
const checker = async (e) => {
  let value = e.target.value.toUpperCase();
  //disable current input box
  updateDivConfig(e.target, true);
  if (value.length == 1) {
    //if the word is lesss than 5 length and the button isn't backspace
    if (inputCount <= 4 && e.key != "Backspace") {
      //Attach the letter to the final word
      finalWord += value;
      if (inputCount < 4) {
        //enable next
        updateDivConfig(e.target.nextSibling, false);
      }
    }
    inputCount += 1;
  } else if (value.length == 0 && e.key == "Backspace") {
    //Empty input box anduser press Backspace
    finalWord = finalWord.substring(0, finalWord.length - 1);
    if (inputCount == 0) {
      //For first inputbox
      updateDivConfig(e.target, false);
      return false;
    }
    updateDivConfig(e.target, true);
    e.target.previousSibling.value = "";
    //enable previous and decrement count
    updateDivConfig(e.target.previousSibling, false);
    inputCount = -1;
  }
};

//When user presses enter/backspace and all the inputs are filled
window.addEventListener("keyup", (e) => {
  if (inputCount > 4) {
    if (isTouchDevice()) {
      submitButton.classList.remove("hide");
    }
    if (e.key == "Enter") {
      validateWord();
    } else if (e.key == "Backspace") {
      inputRow[tryCount].lastChild.value = "";
      finalWord = finalWord.substring(0, finalWord.length - 1);
      updateDivConfig(inputRow[tryCount].lastChild, false);
      inputCount -= 1;
    }
  }
});

//Comparison Logic
const validateWord = async () => {
  if (isTouchDevice()) {
    submitButton.classList.add("hide");
  }
  let failed = false;
  //Get all input boxes of current row
  let currentInputs = inputRow[tryCount].querySelectorAll(".input-box");
  //Check if it is a valid english word
  await fetch(
    `https://api.dictionaryapi.dev/api/v2/entries/en/${finalWord}`
  ).then((response) => {
    if (response.status == "404") {
      console.clear();
      alert("Please Enter Valid Word");
      failed = true;
    }
  });

  //If not then stop here
  if (failed) {
    return false;
  }
  //Initially set these
  let successCount = 0;
  let successLetters = "";
  //Checks for both words
  for (let i in randomWord) {
    //if same then green
    if (finalWord[i] == randomWord[i]) {
      currentInputs[i].classList.add("correct");
      successCount += 1;
      successLetters += randomWord[i];
    } else if (
      randomWord.includes(finalWord[i]) &&
      !successLetters.includes(finalWord[i])
    ) {
      //If the letter exist in the chosen word and is not present in the success array then yellow
      currentInputs[i].classList.add("exists");
    } else {
      currentInputs[i].classList.add("incorrect");
    }
  }
  //Increment try count
  tryCount += 1;
  //If all letters are correct
  if (successCount == 5) {
    //Display the win banner after 1 second
    setTimeout(() => {
      winScreen.classList.remove("hide");
      winScreen.innerHTML = `
        <span>Total guesses: ${tryCount}</span>
        <button onclick="startGame()">New Game</button>
        `;
    }, 1000);
  } else {
    //unsuccessful so next attempt
    inputCount = 0;
    finalWord = "";
    if (tryCount == 6) {
      //all attempts wrong
      tryCount = 0;
      winScreen.classList.remove("hide");
      winScreen.innerHTML = ` <span>You lose</span>
        <button onclick="startGame()">New Game</button>`;
      return false;
    }
    //for next attempt move to first child of next row
    updateDivConfig(inputRow[tryCount].firstChild, false);
  }
  inputCount = 0;
};

window.onload = startGame();

That’s all for this tutorial. If you face any issues while creating this project you can download the source code by clicking on the download button below also so if you have any queries suggestions or feedback you can comment below.
Happy coding!

Previous articleMCQ – 18/11/22
Next articleMCQ – 20/11/22
RELATED ARTICLES

1 COMMENT

  1. Hello, I absolutely love your works!
    Might be wrong but it seems that correct but misplaced chars aren’t counted. Leading in a wrong result if the randomWord is “Cheeks” and the finalWord is “Eerie”. All 3 “e” will be yellow.
    I played around with that Wordle game mechanism but on Swift 🙂

LEAVE A REPLY

Please enter your comment!
Please enter your name here

6 + 3 =

Most Popular