Like Tic Tac Toe, Hangman is one of the simplest games to play. It comes as no surprise that it is one of the simplest games to code. Coding a game of Hangman helps to understand programming concepts and methods like string functions, pattern matching and file manipulation. So, how do we code it?

The Logic Behind Hangman

Flowchart depicting the sequence of events in a game of Hangman.

A game of Hangman starts by drawing the pole and “noose”. Then, we choose a word and store it somewhere. We print out a series of blanks equal to the number of letters in the word and prompt a user to guess a letter. If the letter is in the word, we replace the blank(s) with the letter corresponding to the letter’s position(s) in the word. If not, we draw the next body part on the noose. This continues until the user has guessed a total of 6 wrong letters or the word has been completely guessed.

The body parts drawn (in order) are head, torso, first arm, second arm, first leg and second leg (6 parts).

Step-by-Step Procedure to Make a Game of Hangman

First, we create global variables to store the word as a string, an array of blanks with the same length as the word, a boolean to check whether the game is over or not and the number of wrong guesses the user has left.

First, we create and call a function to print the instructions.

We then create and call a function that opens a .txt file containing a list of words, reads from the file and stores the values in an array, and randomly picks a word from the array to assign to the global variable word.

After that, we create and call functions that print the blanks and related information and draw the pole and noose.

Next, we create and call a function where the actual game is played. In this play() function, inside a while loop that checks whether or not the game is over, we take an input from the user. If the inputted letter is present in the word, we replace the blank(s) in the hiddenword array with the letter as it appears in the word. We then re-call the functions to draw the pole and noose and print the hidden word. Next, we call a function that checks whether or not the game is over, i.e., whether the word has been correctly guessed or the user has exhausted his/her wrong guesses. If so, it changes the value of the boolean variable to true and the while loop breaks.

Finally, we call a function that ends the game by printing whether the user won or lost, and if not, prints the word.

Scala Implementation of the Above Procedure

import scala.io.Source
import scala.util.Random

object Hangman {
  var word: String = ""
  var hiddenWord :Array[String] = Array()
  var gameOver = false
  var chances = 6

  def main(args: Array[String]): Unit = {
    print_instructions()
    chooseWord()
    for (_ <- 0 until word.length){hiddenWord = hiddenWord :+ "_"}
    drawfig()
    print_word()
    play()
    endGame()
  }

  def play(): Unit ={
    while (!gameOver){
      var input = scala.io.StdIn.readLine("GUESS A LETTER: ")
      var guesses = findinword(input)
      for (i<- guesses){hiddenWord(i) =  word.charAt(i).toString}
      print_word()
      drawfig()
      isGameOver()
    }
  }

  def chooseWord(): Unit ={
    var wordlist:Array[String] = Array()
    val rawwordlist = Source.fromFile("/Users/sureshp/Downloads/hangman_words.txt")
    for(wrd<-rawwordlist.getLines()){wordlist = wordlist :+ wrd}
    rawwordlist.close()
    word = wordlist(Random.nextInt(wordlist.length)).toUpperCase
  }

  def print_word(): Unit ={
    for (char <- hiddenWord){
      print(char+" ")
    }
    println()
    println(s"You have $chances wrong guesses left.")
    println()
  }

  def findinword(input: String): Array[Int] ={
    var indices: Array[Int] = Array()
    for (i <- 0 until word.length){
      if (word(i).toString == input){indices = indices :+ i}
    }
    if (indices.isEmpty){chances = chances - 1; println(s"Sorry, $input is not in the word!") }
    return indices
  }

  def isGameOver(): Unit ={
    var freechars = 0
    if (chances == 0){gameOver = true}
    for (char <- hiddenWord){
      if (char == "_"){freechars += 1}
    }
    if (freechars == 0){gameOver = true}
  }

  def endGame(): Unit ={
    println("GAME OVER")
    if (chances == 0){println(s"Better luck next time! The word was '$word'")}
    else{println("Congratulations, you have guessed the right word!")}
  }

  def print_instructions(): Unit ={
    println("WELCOME TO HANGMAN!")
    println("  INSTRUCTIONS:")
    println("-> The goal of the game is to guess the word by guessing alphabets one at a time.")
    println("-> Make sure you type in your guesses one at a time.")
    println("-> eg. GUESS A LETTER: E")
    println("-> DONOT guess the same letter again if you had previously gotten it wrong. You will lose a chance both times.")
    println("-> If you guess for a second time a letter you had previously gotten right, don't worry, you will not lose a chance.")
    println("-> Always keep Caps Lock ON.")
    println("-> That's pretty much it. Enjoy!")
    println()
  }

  def drawfig(): Unit ={
    if (chances == 6){
      println("|---------|")
      println("|         ")
      println("|         ")
      println("|        ")
      println("|           ")
      println("|")
      println("------------")
    }
    else if (chances == 5){
      println("|---------|")
      println("|         O")
      println("|         ")
      println("|        ")
      println("|           ")
      println("|")
      println("------------")
    }
    else if (chances == 4){
      println("|---------|")
      println("|         O")
      println("|        / ")
      println("|        ")
      println("|           ")
      println("|")
      println("------------")
    }
    else if (chances == 3){
      println("|---------|")
      println("|         O")
      println("|        /| ")
      println("|        ")
      println("|           ")
      println("|")
      println("------------")
    }
    else if (chances==2){
      println("|---------|")
      println("|         O")
      println("|        /|\\ ")
      println("|        ")
      println("|           ")
      println("|")
      println("------------")
    }
    else if (chances==1){
      println("|---------|")
      println("|         O")
      println("|        /|\\ ")  //the double backslash prints a single backlash and is 
      println("|        / ")     //necessary because a single bakslash is considered an  
      println("|           ")    //escape sequence
      println("|")
      println("------------")
    }
    else if (chances == 0){
      println("|---------|")
      println("|         O")
      println("|        /|\\ ")
      println("|        / \\")
      println("|           ")
      println("|")
      println("------------")
    }
  }
}

The github link for the above program is:

https://github.com/adityapentyala/Scala/blob/master/Hangman.scala

The link from where I downloaded the .txt file:

https://framagit.org/siliconbot/siliconbot/-/blob/master/hangman_words.txt

Visits: 58

One Reply to “Hangman in Scala”

  1. Nice write-up! Liked the approach – algorithm & then the code. What if we add time limit and a score to this game?

Leave a Reply

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