Hangman Game using HTML, CSS and JavaScript (Source Code) - Coding Torque

Hangman Game using HTML, CSS and JavaScript

Hello coders! Are you ready to test your coding skills and put your knowledge of HTML, CSS, and JavaScript to the ultimate test? If so, you've come to the right place! In this blog, we will be walking you through the steps to create your very own Hangman game from scratch. Not only is this game a fun and engaging way to pass the time, but it's also a great way to enhance your portfolio and showcase your abilities as an intermediate-level JavaScript developer. So grab your coding hat and let's get started!


Join us on Telegram Join Now

Before we start, here are some more JavaScript projects for you to practice:

1. Snake Game using JavaScript

2. 2D Bouncing Ball Game using JavaScript

3. Rock Paper Scissor Game using JavaScript

4. Tic Tac Toe Game using JavaScript

5. QR Code Generator using JavaScript


I would recommend you don't just copy and paste the code, just look at the code and type by understanding it.


Demo



HTML Code

Starter Template

<!doctype html>
<html lang="en">

<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSS -->
    <link rel="stylesheet" href="style.css">

    <title>Hangman Game using JavaScript - @code.scientist x @codingtorque</title>
</head>

<body>
    <!-- Further Code Here -->

    <script src="script.js"></script>
</body>

</html>


Paste the below code in your <body> tag

<main>
    <div class="outside-wrapper">
        <h1 id="statusMessage">Vanilla JavaScript Hangman Game </h1>

    </div>

    <div class="outside-wrapper">

        <div class="inside-wrapper">

            <!-- <?xml version="1.0" encoding="utf-8"?> -->
            <!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
            <svg version="1.1" id="hangknuckles" xmlns="http://www.w3.org/2000/svg"
                xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 169.28 205"
                enable-background="new 0 0 169.28 205" xml:space="preserve">
                <g id="hanger">
                    <line fill="none" stroke="#000000" stroke-width="4" stroke-miterlimit="10" x1="170.259"
                        y1="203.446" x2="0.781" y2="203.001" />
                    <line fill="none" stroke="#000000" stroke-width="4" stroke-miterlimit="10" x1="38.779" y1="2"
                        x2="39.279" y2="202" />
                    <line fill="none" stroke="#000000" stroke-width="4" stroke-miterlimit="10" x1="139.78" y1="4"
                        x2="34.78" y2="2" />
                    <line fill="none" stroke="#000000" stroke-width="2" stroke-miterlimit="10" x1="138.78" y1="4"
                        x2="135.78" y2="49" />
                    <line fill="none" stroke="#000000" stroke-width="4" stroke-miterlimit="10" x1="77.323" y1="2.51"
                        x2="39.791" y2="28.042" />
                </g>
                <line id="show0" class="bodyPart hidden" fill="none" stroke="#000000" stroke-width="4"
                    stroke-miterlimit="10" x1="136.78" y1="119" x2="148.78" y2="152" />
                <line id="show1" class="bodyPart hidden" fill="none" stroke="#000000" stroke-width="4"
                    stroke-miterlimit="10" x1="137.78" y1="119" x2="114.78" y2="157" />
                <line id="show2" class="bodyPart hidden" fill="none" stroke="#000000" stroke-width="4"
                    stroke-miterlimit="10" x1="136.78" y1="108" x2="99.28" y2="100.5" />
                <line id="show3" class="bodyPart hidden" fill="none" stroke="#000000" stroke-width="4"
                    stroke-miterlimit="10" x1="136.78" y1="107" x2="166.28" y2="94.5" />
                <line id="show4" class="bodyPart hidden" stroke="#000000" stroke-width="4" stroke-miterlimit="10"
                    x1="137.78" y1="82" x2="136.78" y2="120.5" />
                <image overflow="visible" id="show5" class="bodyPart hidden" width="96" height="96"
                    xlink:href="https://res.cloudinary.com/dshmwg7vw/image/upload/v1550434128/icons8-ugandan-knuckles-96.png"
                    transform="matrix(0.5426 0 0 0.516 110.2271 42.9535)">
                </image>

            </svg>

        </div>
        <div class="inside-wrapper">
            <div>
                <img id="life5" class="lives"
                    src="https://res.cloudinary.com/dshmwg7vw/image/upload/v1550434128/icons8-ugandan-knuckles-96.png"
                    alt="">
                <img id="life4" class="lives"
                    src="https://res.cloudinary.com/dshmwg7vw/image/upload/v1550434128/icons8-ugandan-knuckles-96.png"
                    alt="">
                <img id="life3" class="lives"
                    src="https://res.cloudinary.com/dshmwg7vw/image/upload/v1550434128/icons8-ugandan-knuckles-96.png"
                    alt="">
                <img id="life2" class="lives"
                    src="https://res.cloudinary.com/dshmwg7vw/image/upload/v1550434128/icons8-ugandan-knuckles-96.png"
                    alt="">
                <img id="life1" class="lives"
                    src="https://res.cloudinary.com/dshmwg7vw/image/upload/v1550434128/icons8-ugandan-knuckles-96.png"
                    alt="">
                <img id="life0" class="lives"
                    src="https://res.cloudinary.com/dshmwg7vw/image/upload/v1550434128/icons8-ugandan-knuckles-96.png"
                    alt="">
            </div>
            <div>
                <p id="wrongLetters" class="hidden">Wrong letters:<br> <span></span></p>
            </div>
        </div>
    </div>
    <div class="outside-wrapper">

        <div class="wrapper">
            <p id="categoryName">Category:smtg</p>
            <div id="guessWrapper">
            </div>
        </div>

        <div class="button-wrapper">
            <input type="text" id="userLetter" maxlength="1" size="4" autocomplete="off">
            <button type="button" id="guessButton">Guess</button>
        </div>

        <div class="wrapper warning">
            <span id="warningText" class="hidden"> </span>
        </div>

    </div>

    <div class="outside-wrapper">
        <button type="button" id="newGame">New Game</button>
    </div>
</main>


Output Till Now


CSS Code

Create a file style.css and paste the code below. 

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

body {
  background: url("https://res.cloudinary.com/dshmwg7vw/image/upload/v1550486966/OCCNFD0.jpg");
  background-size: contain;
  background-repeat: repeat;
  font-family: "Permanent Marker", cursive;
  position: relative;
}

main {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.wrapper,
.button-wrapper {
  text-align: center;
  margin: 10px;
}

.outside-wrapper {
  margin-bottom: 20px;
  text-align: center;
}

.outside-wrapper:nth-child(2) {
  width: 100%;
  margin-top: 20px;
  display: flex;
  justify-content: center;
  max-height: 300px;
}

.outside-wrapper:nth-child(3) {
  margin-bottom: auto;
  height: 178px;
  width: 100%;
}

.hidden {
  display: none;
}

#statusMessage {
  margin-top: 20px;
  margin-bottom: 20px;
  padding: 10px;
  box-sizing: border-box;
  text-align: center;
  height: 94px;
}

svg {
  transform: rotate(-1deg);
}

.lives {
  width: 40px;
  height: auto;
}

.hiddenLife {
  display: inline-block;
  animation: lifeAway 0.6s forwards;
}

@keyframes lifeAway {
  0% {
    opacity: 1;
  }

  10% {
    transform: scale(1.5) rotate(0deg);
  }

  50% {
    transform: scale(0.5) rotate(720deg);
  }

  100% {
    transform: scale(0) rotate(720deg);
    opacity: 0;
    display: none;
  }
}

#categoryName {
  font-size: 20px;
  margin: 0 5px 5px 5px;
}

#warningText {
  color: rgb(239, 83, 80);
}

.warning {
  height: 20px;
}

#guessWrapper p {
  font-size: 40px;
  display: inline-block;
  letter-spacing: 15px;
  margin-bottom: 20px;
  margin-top: 0;
  color: green;
}

.inside-wrapper {
  text-align: center;
}

.inside-wrapper:first-child {
  width: 250px;
}

.inside-wrapper:last-child {
  width: 400px;
  padding-right: 20px;
  box-sizing: border-box;
  text-align: right;
  display: flex;
  flex-direction: column;
}

.inside-wrapper div:last-child {
  margin-top: auto;
}

#wrongLetters {
  text-align: right;
}

#wrongLetters span {
  text-align: right;
  color: rgb(239, 83, 80);
  letter-spacing: 5px;
}

@media (max-width: 470px) {
  #categoryName {
    font-size: 18px;
    margin-bottom: 10px;
  }

  .lives {
    width: 25px;
    height: auto;
  }

  #guessWrapper p {
    font-size: 20px;
  }
}

input {
  border-radius: 7px;
  border-style: none;
  border: 1px solid gray;
  text-align: center;
  transition: 0.2s linear;
}

input:focus {
  outline: none;
  border: 1px solid green;
}

button {
  transition: 0.2s linear;
  outline: none;
  border-style: none;
  background-color: darkgray;
  color: black;
  border-radius: 7px;
}

button:hover,
button:focus {
  background-color: green;
  outline: none;
  color: white;
}

input,
button {
  padding: 5px 10px;
  box-sizing: border-box;
  letter-spacing: 3px;
}  

Output Till Now

Hangman Game using HTML, CSS and JavaScript

JavaScript Code

Create a file script.js and paste the code below.

window.onload = function () {
  let wordsArray = [
    ["C", "A", "T", "S"],
    ["M", "O", "U", "S", "E"],
    ["J", "A", "V", "A", "S", "C", "R", "I", "P", "T"],
    ["P", "O", "T", "A", "T", "O"],
    ["U", "N", "D", "E", "F", "I", "N", "E", "D"],
    ["S", "P", "A", "G", "H", "E", "T"],
    ["W", "A", "Y"]
  ];
  let categoryArray = [
    ["The internet and Youtube would not be the same without them"],
    ["Touchpad ain't got nothing on me"],
    ["Love it or hate it, frontend devs need it"],
    ["This hangman game is..."],
    ["I'm declared, but don't have a value"],
    ["Somebody toucha my..."],
    ["You do not know de..."]
  ];

  let newGame = document.getElementById("newGame");
  newGame.onclick = startNewGame;

  class Hangman {
    constructor() {
      //game state and initial values
      this.random = Math.floor(Math.random() * wordsArray.length);
      this.wordToGuess = wordsArray[this.random];
      this.category = categoryArray[this.random];
      this.placeholderArray = Array(this.wordToGuess.length).fill("_");
      this.guessed = [];
      this.lives = 6;
    }
    setupNewWord() {
      //setsup new game input/buttons and creates initial placeholder containing only "_" and puts it on the board. placeholder has as many characters as the word
      let guessWrapper = document.getElementById("guessWrapper");
      let placeholderP = document.createElement("p");
      let category = document.getElementById("categoryName");
      category.innerHTML = this.category;

      placeholderP.setAttribute("id", "placeholderP");
      placeholderP.innerHTML = this.placeholderArray.join("");
      guessWrapper.appendChild(placeholderP);

      let userLetter = document.getElementById("userLetter");
      userLetter.onkeypress = this.handleKeyPress.bind(this);

      let guessButton = document.getElementById("guessButton");
      guessButton.onclick = this.handleClick.bind(this);
    }
    handleClick() {
      //main game logic, triggers input check, win or loose, updates lives, shows/hides various elements on click
      let userLetterInput = document.getElementById("userLetter");
      let userLetter = userLetterInput.value.toUpperCase();
      let placeholderP = document.getElementById("placeholderP");
      let warningText = document.getElementById("warningText");
      let alreadyGuessed = document.querySelector("#alreadyGuessed span");
      let wrongLetters = document.querySelector("#wrongLetters span");
      let leftLives = document.querySelector("#leftLives span");

      if (!/[a-zA-Z]/.test(userLetter)) {
        //check that the user types in letters
        unhideElements("hidden", warningText);
        warningText.innerHTML = "Please enter a letter from A-Z"; //and shows warning if not
      } else {
        hideElements("hidden", warningText);

        if (
          this.wordToGuess.indexOf(userLetter) > -1 &&
          this.guessed.indexOf(userLetter) == -1
        ) {
          //check if letter is a match, and first guess
          checkGuess(this.wordToGuess, userLetter);
          hideElements("hidden", warningText);
        } else if (
          this.wordToGuess.indexOf(userLetter) == -1 &&
          this.guessed.indexOf(userLetter) == -1
        ) {
          //check if not match, and first wrong
          hideElements("hidden", warningText);
          unhideElements("hidden", wrongLetters.parentNode);
          wrongLetters.innerHTML += userLetter;
          this.lives--;
          hangerDraw(this.lives);
          hideLives(this.lives);
        } else {
          //if not first use of this letter
          unhideElements("hidden", warningText);
          warningText.innerHTML = "";
          warningText.innerHTML += "Already typed " + userLetter;
        }
        this.guessed.indexOf(userLetter) == -1
          ? this.guessed.push(userLetter)
          : null; //for all guesses, if its the first time using the letter, save it

        if (Array.from(placeholderP.innerHTML).indexOf("_") == -1) {
          //trigger game win or loose
          gameOver(true); //when no more '_' exist in placeholder, you win
        } else if (this.lives == 0) {
          //when lives are gone, you loose
          gameOver();
        }
      }
      userLetterInput.value = "";
    }
    handleKeyPress(e) {
      //if enter is pressed trigger click on button
      var guessButton = document.getElementById("guessButton");
      if (e.keyCode === 13) {
        guessButton.click();
      }
    }
  }

  function checkGuess(wordToGuess, userLetter) {
    //handles check logic, and replaces letters in placeholder when a match is found
    let placeholderP = document.getElementById("placeholderP");
    let placeholderArray = Array.from(placeholderP.innerHTML);
    placeholderArray = placeholderArray.map((el, i) => {
      //check if letter exists in the guess word, and if yes,replace it in the placeholder and display it
      if (wordToGuess[i] == userLetter) {
        return (el = userLetter);
      } else {
        return el;
      }
    });

    placeholderP.innerHTML = placeholderArray.join("");
  }

  function gameOver(win) {
    // shows win/game over message
    let winMessage = document.getElementById("statusMessage");
    let btnWrapper = document.querySelector(".button-wrapper");
    hideElements("hidden", btnWrapper);
    if (win) {
      winMessage.innerHTML = "You Win";
      winMessage.style.color = "green";
    } else {
      winMessage.innerHTML = "Game Over";
      winMessage.style.color = "rgb(239, 83, 80)";
    }
  }

  function hangerDraw(num) {
    //helper function triggers show hanger drawing
    let show = document.getElementById(`show${num}`);
    unhideElements("hidden", show);
  }

  function hideLives(num) {
    //helper function triggers hides lives
    let life = document.getElementById(`life${num}`);
    hideElements("hiddenLife", life);
  }

  function hideElements(myclass, ...els) {
    //helper func that hides
    for (let el of els) {
      el.classList.add(myclass);
    }
  }

  function unhideElements(myclass, ...els) {
    //helper func that unhides
    for (let el of els) {
      el.classList.remove(myclass);
    }
  }

  function startNewGame() {
    let btnWrapper = document.querySelector(".button-wrapper");
    let winMessage = document.getElementById("statusMessage");
    let wrongLetters = document.querySelector("#wrongLetters span");
    let warningText = document.querySelector("#warningText");
    let hiddenHangman = Array.from(document.querySelectorAll("svg .bodyPart"));
    let hiddenLives = Array.from(document.querySelectorAll(".lives"));

    for (let bodyPart of hiddenHangman) {
      hideElements("hidden", bodyPart);
    }

    for (let life of hiddenLives) {
      unhideElements("hiddenLife", life);
    }

    wrongLetters.innerHTML = "";
    unhideElements("hidden", btnWrapper);
    hideElements("hidden", wrongLetters.parentNode, warningText);
    winMessage.innerHTML = "Vanilla JavaScript Hangman Game";
    winMessage.style.color = "black";
    let oldP = document.getElementById("placeholderP");
    if (oldP.parentNode) {
      oldP.parentNode.removeChild(oldP);
    }

    let startGame = new Hangman();
    startGame.setupNewWord();
  }

  let startGame = new Hangman(); //initiates first game on windo load
  startGame.setupNewWord();
};


Join us on Telegram Join Now

Written by: Coding Torque | Piyush Patil

Code Credits: @alina-balteanu

If you have any doubts or any project ideas feel free to Contact Us 

Hope you find this post helpful💖
 
 Follow us on Instagram for more projects like this👨‍💻 

Post a Comment

Previous Post Next Post