how to make hangman game step by step in javascript

Welcome to my blog, In this article, we will make a Hangman Game step by step for beginners and I build another format of this Game click to view. Hangman game is a word guessing game JavaScript picks a random word and guess the word in given chances that you have.

Current Video Link:

if you want to watch more videos subscribe my YouTube channel click here

Now we build a Word Guessing Hangman Game in three steps: HTML, CSS, and JavaScript.

Hangman Game HTML

First, we will create an index.html and create a basic static structure of the Game. The static structure means basic part of HTML like guess button, play button, Strike, Average score, how many guesses left and how may guess letters like this see HTML portion below:

<div class="info">Try to guess the hidden word below before it's too late! You can guess either one letter at a time or the whole word, but if you get the word wrong you lose 2 guesses!</div>
<input type="text" placeholder="Guess">
<button style="display:none;">Play Again</button>
<div class="word"></div>
<div class="hangman"></div>
<span style="position:absolute;bottom:10px;left:10px;">
   <div class="guessesLeft">Guesses left: <span class="bold">10</span></div>
   <div class="guessed">Guessed letters: <span class="bold"></span></div>
</span>
<span style="position:absolute;bottom:10px;right:10px;text-align:right;">
   <div>Streak: <span class="streak bold">0</span></div>
   <div>Average score: <span class="score bold">-</span></div>
</span>

HTML portion is completed Now working on style.css firstly we will design page background portion see styling properties below:

Hangman Game CSS

* {
  margin: 0;
}

body {
  transition: .2s background;
  font-family: 'Segoe UI', 'Roboto', arial, sans-serif;
  background: rgb(255,0,53);
  background: linear-gradient(135deg, rgba(33,34,176,1) 0%, rgba(255,0,53,1) 100%);
  color: white;
  height: 100vh;
}

.bold {
  font-weight: bold;
}

.info {
  font-style: italic;
  text-align: center;
  color: rgba(255, 255, 255, 0.8);
}

::-webkit-input-placeholder { /* Edge */
  color: rgba(255, 255, 255, 0.4);
}
:-ms-input-placeholder { /* Internet Explorer 10-11 */
  color: rgba(255, 255, 255, 0.4);
}
::placeholder {
  color: rgba(255, 255, 255, 0.4);
}

input, button {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  padding: 10px;
  border: none;
  border-bottom: 1px solid white;
  font-size: 1em;
  margin-top: 10px;
  background: none;
  color: white;
}
button {
  background: none;
  border-radius: 4px;
  padding: 10px 16px;
  color: white;
  cursor: pointer;
  border: 3px solid rgba(255, 255, 255, 0.6);
  transition: .2s background;
  text-transform: uppercase;
  font-weight: bold;
}
button:hover {
  background: rgba(255, 255, 255, 0.1);
}
button:active {
  background: rgba(255, 255, 255, 0.3);
}

.word {
  position: absolute;
  top: 80%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  max-width: 100vw;
}
.word span {
  border-bottom: 2px solid white;
  padding: 10px; /* not ideal for long words */
  margin: 10px;
  width: 30px;
  text-align: center;
  font-size: 2em;
  text-transform: uppercase;
}

.hangman svg {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 30vw;
  height: 40vh;
  transform: translate(-50%, -50%);
}
.hangman line, .hangman circle {
  stroke: white;
  stroke-width: 4;
  fill: none;
}

.hangman .draw {
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  animation: dash 2s linear forwards;
}

@keyframes dash {
  to {
    stroke-dashoffset: 0;
  }
}

Hangman Game styling portion has done after that connect script.js for functionality portion. Now working on script file no need jQuery part. we are completely working in pure JavaScript.

I am Take the words list which chooses a word for a Game but you can add more words and use an own words list.

Hangman Game (JS/Javascript)

var words = [
  'america',
  'animal',
  'apple',
  'bag',
  'barack obama',
  'basket',
  'bat',
  'boat',
  'box',
  'camera',
  'candle',
  'car',
  'cat',
  'china',
  'christmas',
  'clouds',
  'cobweb',
  'codepen',
  'coding',
  'computer',
  'cowboy',
  'cup',
  'denmark',
  'disney',
  'dog',
  'donald duck',
  'door',
  'drawing',
  'drums',
  'ears',
  'easter egg',
  'egg',
  'elon musk',
  'england',
  'europe',
  'eyes',
  'face',
  'facebook',
  'football',
  'fortnite',
  'france',
  'galaxy',
  'game',
  'germany',
  'google',
  'great britain',
  'guitar',
  'hacker',
  'hangman',
  'head',
  'headphones',
  'holiday',
  'horse',
  'house',
  'india',
  'italy',
  'jelly',
  'jigsaw',
  'kitchen',
  'lamp',
  'lemon',
  'letter',
  'light',
  'lightbulb',
  'mail',
  'mario',
  'melody',
  'mickey mouse',
  'microwave',
  'minecraft',
  'minigame',
  'mouse',
  'mouth',
  'movie',
  'music',
  'norway',
  'nose',
  'orange',
  'oxygen',
  'painting',
  'pants',
  'paper',
  'peace',
  'pen',
  'pencil',
  'pet',
  'pewdiepie',
  'piano',
  'plane',
  'poland',
  'present',
  'program',
  'programmer',
  'quiz',
  'radio',
  'remote control',
  'rocket',
  'russia',
  'school',
  'scotland',
  'screen',
  'seat',
  'shoes',
  'sky',
  'smartphone',
  'snake',
  'spaceship',
  'speakers',
  'star wars',
  'suitcase',
  'summer',
  'sun',
  'superhero',
  'sweater',
  'sweden',
  'television',
  'tools',
  'united states of america',
  'universe',
  'usain bolt',
  'vampire',
  'video',
  'village',
  'wales',
  'water bottle',
  'wind',
  'windmill',
  'window',
  'winter',
  'wizard',
  'word',
  'xylophone',
  'youtube',
  'zombie'
];
var hangman = [
  {from: [70, 38], to: [72, 46]},
  {from: [70, 38], to: [68, 46]},
  {from: [70, 45], to: [72, 55]},
  {from: [70, 45], to: [68, 55]},
  {from: [70, 35], to: [70, 45]},
  {circle: [70, 30], radius: 2},
  {from: [70, 5], to: [70, 25]},
  {from: [30, 5], to: [70, 5]},
  {from: [30, 95], to: [30, 5]},
  {from: [1, 95], to: [99, 95]}
];

// get stats
var stats = {streak: 0, scores: []};
if (typeof(Storage) !== "undefined") {
  if (localStorage.hangman !== undefined) {
    stats = JSON.parse(localStorage.hangman);
    setScore();
  }
}

Now we have discussed that I have used each variable and function in the game firstly we have declared some variables like word,currentWord,guessesLeft , guessed, etc. when refreshing a page then generateWord() call the working of this function is first to define some empty array and you have 10 chances to win the game inside a function get some basic HTML elements and set some static data after that iterate the random generate word and make the blanks. The length of blanks is equal to the random word length that we will guess.

So now we discuss the next addEventListener when you enter any word or character in the blank fields if the input value is not empty then check the length of the word you have entered in the field if your enter word length is not equal to the random guess word then the error comes (Your guess is not the same length as the word!) but both words length is same but guess the word in right then function go to else condition and drawHangman() function call to draw the hangman diagram and throw the fade color on the screen. when you guessed the correct word then the game is finished and you win the game.

next if condition check the already guessed condition when you enter any character and hit enter.

If the character is right then the character is automatically fill in the blank but it’s wrong and you hit enter again with the same character then the game throws an error (You have already guessed that letter!) but in this condition, no effect on guesses left numbers.

after that next condition check if you loss all guesses then you loss the game.

var word, currentWord, guessesLeft, guessed;
generateWord();
function generateWord() {
  currentWord = [], guessesLeft = 10, guessed = [];
  document.querySelector('.guessesLeft').querySelector('span').innerHTML = guessesLeft;
  document.querySelector('.guessed').querySelector('span').innerHTML = '';
  document.querySelector('input').style.display = null;
  document.querySelector('button').style.display = 'none';
  document.querySelector('.hangman').innerHTML = '';
  word = words[Math.floor(Math.random() * words.length)];
  console.log(word);
  let html = '';
  for (let i = 0; i < word.length; i++) {
    if (word[i] == ' ') {
      currentWord[i] = word[i];
      html += '<span class="hidden" style="border:none;"></span>';
    } else html += '<span class="hidden"></span>';
  }
  document.querySelector('.word').innerHTML = html;
}

// check input
document.querySelector('input').addEventListener('change', function() {
  if (this.value !== "" && this.value !== " ") {
    if (this.value.length > 1) {
      if (this.value.length !== word.length) alert('Your guess is not the same length as the word!');
      else if (this.value == word) {
        for (let i = 0; i < word.length; i++) {
          document.querySelector('.word').querySelectorAll('span')[i].innerHTML = word[i];
        }
        finish();
      }
      else {
        drawHangman();
        drawHangman();
        fadeColor('#ff2929');
      }
    } else if (this.value.match(/^[A-Za-z]+$/)) {
      let alreadyGuessed = false;
      for (let i = 0; i < guessed.length; i++) {
        if (guessed[i] === this.value.toLowerCase()) {
          alreadyGuessed = true;
          break;
        }
      }
      if (!alreadyGuessed) {
        guessed.push(this.value.toLowerCase());
        let wordHasLetter = false;
        for (let i = 0; i < word.length; i++) {
          if (word[i] === this.value.toLowerCase()) {
            wordHasLetter = true;
            document.querySelector('.word').querySelectorAll('span')[i].innerHTML = word[i];
            currentWord[i] = word[i];
          }
        }
        if (!wordHasLetter) {
          fadeColor('#ff2929');
          drawHangman();
          let guessedElem = document.querySelector('.guessed').querySelector('span');
          if (guessedElem.innerHTML == '') guessedElem.innerHTML = this.value.toUpperCase();
          else guessedElem.innerHTML += ', ' + this.value.toUpperCase();
        } else fadeColor('#35c435');
      } else alert('You have already guessed that letter!');
      if (currentWord.join('') === word) finish();
    } else alert('Please guess letters only');
    this.value = '';
    if (guessesLeft <= 0) {
      guessesLeft = 0;
      for (let i = 0; i < word.length; i++) {
        if (document.querySelector('.word').querySelectorAll('span')[i].innerHTML == '') {
          document.querySelector('.word').querySelectorAll('span')[i].style.color = 'red';
          document.querySelector('.word').querySelectorAll('span')[i].innerHTML = word[i];
        }
      }
      // fadeColor('#ff2929');
      alert('You lost!');
      document.querySelector('input').style.display = 'none';
      document.querySelector('button').style.display = null;
      stats.streak = 0;
      stats.scores.push(0);
      setScore();
    }
    document.querySelector('.guessesLeft').querySelector('span').innerHTML = guessesLeft;
  }
});

The fadeColor function is used for the color effect when you enter the character and hit enter then the color is fashing on the page.

the next one is the finish function when calling a finish function then the other function comes back on the initial state and play again button appears on the screen and setScore() set the final score and the drawHangman function when you enter in any wrong condition then drawHangman() fn decrease the guesses and draw a hangman.

function fadeColor(color) {
  document.body.style.background = color;
  setTimeout(function() {
    document.body.style.background = null;
  }, 200);
}

function finish() {
  var wrongGuesses = (10 - guessesLeft);
  // var rightGuesses = guessed.length - wrongGuesses;
  var rightGuesses = word.length;
  let score = Math.floor((rightGuesses / (wrongGuesses + rightGuesses)) * 100) || 100;
  alert('Congratulations! Score: ' + score + '%');
  stats.streak++;
  stats.scores.push(score);
  setScore();
  
  fadeColor('lightblue');
  document.querySelector('input').style.display = 'none';
  document.querySelector('button').style.display = null;
}

// play again
document.querySelector('button').addEventListener('click', generateWord);

function setScore() {
  let score = '-';
  for (let i = 0; i < stats.scores.length; i++) {
    if (score == '-') score = 0;
    score += stats.scores[i];
  }
  if (score !== '-') score = Math.floor(score / stats.scores.length) + '%';
  document.querySelector('.streak').innerHTML = stats.streak;
  document.querySelector('.score').innerHTML = score;
  localStorage.hangman = JSON.stringify(stats);
}

function drawHangman() {
  guessesLeft--;
  let part = hangman[guessesLeft];
  
  let hangmanLines = document.querySelector('.hangman').querySelectorAll('svg');
  for (let i = 0; i < hangmanLines.length; i++) {
    hangmanLines[i].children[0].classList.remove('draw');
  }
  
  let svg;  
  if (part.circle == undefined) {
    svg = '<svg><line class="draw" x1="' + part.from[0] + '%" y1="' + part.from[1] + '%" x2="' + part.to[0] + '%" y2="' + part.to[1] + '%"/></svg>';
  } else {
    svg = '<svg><circle class="draw" cx="' + part.circle[0] + '%" cy="' + part.circle[1] + '%" r="' + part.radius + '%"/></svg>';
  }
  
  document.querySelector('.hangman').innerHTML += svg;
}

The HTML, CSS, AND JAVASCRIPT part of the game is completed if you like the article share it with your friends. if you have any question or query related to the article and have any suggestions please leave in the comment box.

Thanks for reading the Article.

Leave a Reply

Your email address will not be published. Required fields are marked *