In this blog post, I am going to share with you the high level steps needed to build the Hangman game using the Batch scripting language.
To learn more about how the Hangman is programmed using the Batch scripting language, please refer to Chapter 5 in the Batchography book.
What’s the Hangman game
Quoting Wikipedia:
The word to guess is represented by a row of dashes, representing each letter of the word. In most variants, proper nouns, such as names, places, and brands, are not allowed. If the guessing player suggests a letter which occurs in the word, the other player writes it in all its correct positions. If the suggested letter or number does not occur in the word, the other player draws one element of a hanged man stick figure as a tally mark.
Game design
The Hangman game logic can be broken into the following steps:
- Using a dictionary file and randomly picking up a word to be guessed
- Drawing the initial game board
- Entering the guess letters loop and do one of the following on each turn:
- Reveal correct letter
- Draw the Hangman stick figure in steps
- Decide whether the game is over: Win or lose?
- Game over: when all the tries are exhausted and the correct word has not been guessed yet
- Player wins: when all the letters are revealed before the number of tries have been exhausted
- Prompt the user and ask if he/she wants to play again
Step 1 – Picking a word from the dictionary
For this step, we need a dictionary file. Any text file containing a list of words would do.
The following function (get-random-line) takes two arguments:
- The dictionary text file name
- The output variable that will contain the randomly picked word from the dictionary file
:: -------------------------------------------------------------------------- :: :: Get random line :: :get-random-line <1=filename> <2=result-var> setlocal enabledelayedexpansion set MAXLINES=-1 for /f "useback tokens=1 delims=:" %%a in (`findstr /N /B /C:"#" "%~1"`) DO set MAXLINES=%%a if %MAXLINES% EQU -1 ( echo Fatal error: the words list file %1 does not end with the "#" marker! call :TermScript 2>nul ) :: Get the random line number. Draw the random line a few times to increase randomness. set /a i=0 :get-random-line-rnd SET /A RANDLINE="(%RANDOM% %% (MAXLINES-1))" set /a i+=1 if %i% NEQ 3 goto get-random-line-rnd if %RANDLINE% EQU 0 (SET SKIPSTX=) ELSE (SET SKIPSTX=skip=%RANDLINE%) :: Skip some lines and return a single line (word) for /f "usebackq %SKIPSTX% delims=" %%w in ("%~1") DO ( endlocal set %~2=%%w exit /b 0 )
When this function is called like this:
:: :: Test the get random line :: :test-get-random-line call :get-random-line words-sat300.txt w echo word=%w% exit /b 0
It will simply return a random line from the “words-sat300.txt” file.
Step 2 – The game board
The idea behind the game board is to:
- Display the stick figure: depending on how many tries have been exhausted so far, the stick figure may be:
- Fully drawn
- Not drawn yet
- Or partially drawn
- Display the guess letters: also depending on what has been guessed so far, there could be:
- No guessed letters
- Some guessed letters
- Or all letters are guessed
The stick figure is drawn using the draw-hangman function which takes the number of exhausted tries so far as its sole parameter:
:: :: Draw the hangman in progression :: :draw-hangman <1=steps> if "%~1" EQU "0" ( echo. echo. echo. echo. echo. ) if "%~1" EQU "1" ( echo (o.o^) echo. echo. echo. echo. ) if "%~1" EQU "2" ( echo (o.o^) echo. ^| echo. ___^| echo. echo. ) if "%~1" EQU "3" ( echo (o.o^) echo. ^| echo. ___^|___ echo. echo. ) if "%~1" EQU "4" ( echo (o.o^) echo. ^| echo. ___^|___ echo. ^| echo. / ) if "%~1" EQU "5" ( echo (o.o^) echo. ^| echo. ___^|___ echo. ^| echo. / \ ) exit /b 0
To display the guessed words so far, we use the reveal-letters function. Essentially, this function displays underscore (“_”) characters that correspond to each letter of the picked word that has not been revealed yet by the player, or it will display the actual guessed letters.
If the word length was 5 (for example the word “hello”), and only the letter “e” has been guessed so far, then we should display something like the following:
Guess: _e___ Enter a letter:
The reveal-letters function takes 4 parameters:
- The actual word
- An equal length (to the actual word) string that contains either “0” if the character at the same position in the actual word has not been revealed yet, or “1” if the character has been revealed.
- The letter to reveal
- A result / output variable to hold the result of the revelation
That’s how the reveal-letters function looks like:
:: :: Reveal letters in a word :: :reveal-letters :: Args: :: <1=Word-Val> The value of the word :: <2=WordBits-Var-InOut> WordBit variable name :: <3=Letter-Val> The letter to reveal :: <4=NewWord-Var-Out> Variable to hold the revealed word :: Returns: :: Number of newly revealed letters setlocal enabledelayedexpansion :: Get the input string length set Word=%~1 call :strlen "%Word%" set /A WordLen=%errorlevel%-1 :: Get the current revelation bits set Bits=!%~2! :: Reset internal variables set NewBits= set NewWord= set /A NbReveal=0 :: Scan and reveal for /L %%i in (0, 1, %WordLen%) DO ( :: Take the revealed letter set Word_I=!Word:~%%i,1! :: Take the current revelation bit set Bit_I=!Bits:~%%i,1! :: Not previously revealed? if !Bit_I! EQU 0 ( :: Check whether to reveal if /I "%~3"=="!Word_I!" ( set Bit_I=1 set /A NbReveal += 1 ) ELSE ( set Word_I=_ ) ) :: Form new revelation bits and word set NewBits=!NewBits!!Bit_I! set NewWord=!NewWord!!Word_I! ) ( endlocal set %~4=%NewWord% set %~2=%NewBits% exit /b %NbReveal% )
Steps 3 and 4 – The game loop
The game loop is actually called from the Game function which executed steps 3 and 4 described above:
- Initialize the game given the randomly picked word from the first step
- Prompt the user for a character to guess
- Draw the updated game board based on what the guessed character was and how many tries are remaining
- Repeat from step #2 until a win or a lose situation occurs
:: :: Game loop :: :Game <1=WordToGuess> setlocal enabledelayedexpansion :: Reset the retries counter set /a MAX_TRIES=5 set /a NbTries=0 :: Initialize the word set Word=%~1 :: Initialize the word bits call :init-word-bits "%Word%" WordBits :: Reveal nothing call :reveal-letters "%Word%" WordBits _ RevealedWord :Game-Letter-Loop cls call :draw-hangman %NbTries% :: Did we exhaust all the tries? if !NbTries! EQU !MAX_TRIES! ( echo. echo Game over^^! The word was: '%Word%'^^! echo. exit /b 0 ) ECHO Guess: %RevealedWord% :: Did we reveal all the letters? if /I "!Word!"=="!RevealedWord!" goto Game-Finished :: Take a single letter SET /P Letter="Enter a letter: " SET Letter=!Letter:~0,1! set OldBits=!WordBits! call :reveal-letters "%Word%" WordBits !Letter! RevealedWord :: If nothing was revealed then decrease the number of tries if !OldBits!==!WordBits! SET /A NbTries+=1 :: Repeat goto :Game-Letter-Loop :Game-Finished echo. echo Good job^^! echo. endlocal EXIT /b 1
Step 5 – Putting it altogether
In this last step, everything is put together:
- The game is started and a random word is picked
- The Game function is called and in turn it will invoke the Game-Loop function which will in turn reveal letters or draw more of the hangman stick figure
- After the Game function returns, the game may restart after prompting the player to play a new game or not
:PlayGame :PlayGame-Again call :get-random-line words-sat300.txt word call :Game %Word% choice /c:yn /m "Do you want to play more?" if "%ERRORLEVEL%" EQU "1" goto PlayGame-Again goto :eof
You may download the full Hangman’s source code from the Batchography’s book online source repository:
You might also like:
- Batchography: Embedding an executable file in a Batch script
- Batchography: How to check if your Batch file script is running as an Administrator
- WifiPasswordReveal: A script to reveal all the saved WiFi passwords in Windows 7 and above
- My books
- Free pictures to PDF converter: Pic2Pdf v1.0
- Introducing the “Batchography: The Art of Batch Files Programming” book