How to Create a Hangman Game in Batch Script
Building a specialized word-guessing game like Hangman requires sophisticated string manipulation, dynamic character hiding, and sequential input validation. Unlike a simple guessing game handling standard numbers, Hangman demands the Batch script evaluate individual letters within a hidden string, revealing only the correctly guessed indexes while masking the rest with underscores (_ _ _ A _).
In this guide, we will demonstrate how to construct an interactive Hangman GUI using nested loops and delayed expansion.
The Strategy: Masking the Word
- Define a target word (e.g.,
SCRIPT). - Calculate the exact length of the target word.
- Generate a parallel "masked" string composed entirely of underscores (
_). - Capture a letter guess from the user.
- Loop through every single character index of the target word.
- If the guessed letter matches the target letter at index
i, update the masked string at that specific index. - Display the updated masked string, decrement lives if incorrect, and repeat.
Implementation Script
@echo off
setlocal EnableDelayedExpansion
title Batch Hangman
color 0F
:Init
cls
:: 1. Define Game Stats
set "targetWord=AUTOMATION"
set "guessedLetters="
set "lives=6"
set "wordLength=0"
set "maskedWord="
:: 2. Calculate length and build masked string
:CalcLength
if not "!targetWord:~%wordLength%,1!"=="" (
set /a "wordLength+=1"
set "maskedWord=!maskedWord!_"
goto CalcLength
)
:: Calculate last index for the loop
set /a "lastIndex=wordLength - 1"
:GameLoop
cls
echo ==========================================
echo H A N G M A N
echo ==========================================
echo.
echo Lives Remaining: !lives!
echo Guessed Letters: !guessedLetters!
echo.
:: Display masked word with spaces between characters
set "displayWord="
for /l %%I in (0,1,!lastIndex!) do (
set "displayWord=!displayWord! !maskedWord:~%%I,1!"
)
echo Secret Word :!displayWord!
echo.
:: 3. Evaluate Win/Loss Conditions
if "!maskedWord!"=="!targetWord!" goto Victory
if !lives! equ 0 goto GameOver
:: 4. Get User Input
set "guess="
set /p "guess=Guess a letter: "
:: Validate input is not empty
if "!guess!"=="" goto GameLoop
:: Truncate to first character only
set "guess=!guess:~0,1!"
:: Validate input is a letter (A-Z)
set "isLetter=0"
set "alphabet=ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for /l %%C in (0,1,25) do (
if /i "!guess!"=="!alphabet:~%%C,1!" set "isLetter=1"
)
if "!isLetter!"=="0" (
echo [^^!] Please enter a letter A-Z only.
timeout /t 2 /nobreak >nul
goto GameLoop
)
:: Normalize guess to uppercase for consistent comparison
for /l %%C in (0,1,25) do (
if /i "!guess!"=="!alphabet:~%%C,1!" set "guess=!alphabet:~%%C,1!"
)
:: Check if already guessed
set "alreadyGuessed=0"
for %%X in (!guessedLetters!) do (
if /i "%%X"=="!guess!" set "alreadyGuessed=1"
)
if "!alreadyGuessed!"=="1" (
echo You already guessed that letter^^!
timeout /t 2 /nobreak >nul
goto GameLoop
)
:: Append to guessed list
set "guessedLetters=!guessedLetters! !guess!"
set "matched=0"
:: 5. Reconstruct the Masked Word
:: Build a new string (newMask) character by character
set "newMask="
for /l %%I in (0,1,!lastIndex!) do (
set "targetChar=!targetWord:~%%I,1!"
set "maskChar=!maskedWord:~%%I,1!"
:: If guess matches target character, reveal it
if /i "!targetChar!"=="!guess!" (
set "newMask=!newMask!!targetChar!"
set "matched=1"
) else (
:: Otherwise, keep whatever was already in the mask
set "newMask=!newMask!!maskChar!"
)
)
:: Apply the new string to the game state
set "maskedWord=!newMask!"
:: 6. Handle Incorrect Guesses
if "!matched!"=="0" (
set /a "lives-=1"
)
goto GameLoop
:: 7. End States
:Victory
echo ==========================================
echo CONGRATULATIONS^^! YOU SAVED THE HANGMAN^^!
echo ==========================================
echo.
echo The word was: !targetWord!
goto Replay
:GameOver
echo ==========================================
echo GAME OVER
echo ==========================================
echo.
echo The word was: !targetWord!
goto Replay
:Replay
echo.
set "playAgain="
set /p "playAgain=Play Again? (Y/N): "
if /i "!playAgain!"=="Y" goto Init
echo Thanks for playing^^!
pause
exit /b
How It Works
- Iterative Rebuilding: Because Batch cannot natively perform
maskedWord[3]="A", we use a loopfor /l %%I in (0,1,!lastIndex!)that walks through every character position. We evaluate the old character at each index. If the guess matches, we append the revealed letter to a temporarynewMaskstring. If not, we append whatever was already there (an underscore or a previously revealed letter). Finally, we completely overwritemaskedWordwithnewMask. - Tracking Guessed Letters: The
!guessedLetters!string stores previous guesses separated by spaces, preventing players from being unjustly penalized for repeating a character. Thefor %%X in (!guessedLetters!)loop tokenizes on spaces to check each previously guessed letter individually. - Truncation:
set "guess=!guess:~0,1!"forcefully trims multi-character inputs. If a user tries to type "ABC", this command clips the string to just the first letter "A", preventing unexpected strings from breaking the comparison loop.
Why Build Hangman in Batch?
- String Parsing Masterclass: Slicing strings apart character-by-character, evaluating logic simultaneously across two discrete strings (
targetWordandmaskedWord), and assembling a cohesive result seamlessly is a robust way to learn about memory buffers and index-based manipulation. - State Machines: A complex
:GameLoopthat gracefully checks Win/Loss boundaries, input safety boundaries, and screen-redraw operations entirely through iterative label jumping. - Algorithmic Optimization: An unoptimized character replacement loop in Batch lags heavily. Learning the fastest way to evaluate loop indices minimizes screen tearing and input latency globally across all scripts.
Conclusion
Hangman demonstrates sophisticated native string traversal mechanisms. By dynamically rebuilding arrays iteratively, a simple Command Prompt environment elegantly supports hidden variables, nested matching arrays, and complex state preservation without relying on any external modules or dependencies.