← jason

hangman

c++, console, ascii gallows. two word lists depending on how bad you want to feel about your vocabulary.

standard hangman, nothing reinvented. secret word gets picked from one of two lists (normal or "hard mode," which is really just longer words), you guess letters, six wrong guesses and the little guy on the ascii gallows is fully assembled.

the source comments do more explaining than i will here — half of them are just me narrating decisions as i made them, which in hindsight is a better readme than an actual readme.

+---+ | | O | /|\ | / \ | | =========

how it's put together

one file. a printGallows function keyed off remaining lives, two hardcoded word lists, and a menu loop that doesn't exit until you pick 4. guessed letters get tracked in a vector so it can tell you when you've already tried one — nothing fancy, just a linear scan since the list never gets long enough to matter.

source

hangman.cpp

#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <cctype>

using namespace std;

// i draw a dead guy depending on how bad you are doing. standard stuff.
void printGallows(int lives) {
    if (lives == 6) {
        cout << "  +---+\n  |   |\n      |\n      |\n      |\n      |\n=========\n";
    } else if (lives == 5) {
        cout << "  +---+\n  |   |\n  O   |\n      |\n      |\n      |\n=========\n";
    } else if (lives == 4) {
        cout << "  +---+\n  |   |\n  O   |\n  |   |\n      |\n      |\n=========\n";
    } else if (lives == 3) {
        cout << "  +---+\n  |   |\n  O   |\n /|   |\n      |\n      |\n=========\n";
    } else if (lives == 2) {
        cout << "  +---+\n  |   |\n  O   |\n /|\\  |\n      |\n      |\n=========\n";
    } else if (lives == 1) {
        cout << "  +---+\n  |   |\n  O   |\n /|\\  |\n /    |\n      |\n=========\n";
    } else {
        cout << "  +---+\n  |   |\n  O   |\n /|\\  |\n / \\  |\n      |\n=========\n";
    }
}

// basic words. nothing crazy. just random items.
const vector<string> NORMAL_WORDS = {
    "astronaut", "backpack", "chocolate", "dinosaur", "elephant", 
    "furniture", "guitar", "helicopter", "internet", "journey", 
    "keyboard", "lightning", "mountain", "notebook", "ocean", 
    "pyramid", "restaurant", "smartphone", "telescope", "umbrella"
};

// words for when you want to feel smart or whatever.
const vector<string> HARD_WORDS = {
    "labyrinth", "cacophony", "ephemeral", "juxtaposition", "obfuscate", 
    "quintessential", "synecdoche", "vicarious", "zephyr", "capricious", 
    "ubiquitous", "pernicious", "melancholy", "idiosyncrasy", "acquiesce"
};

void playGame(bool hardMode) {
    // grab whichever list. reference it to save memory or something. 
    const vector<string>& currentPool = hardMode ? HARD_WORDS : NORMAL_WORDS;
    int randomIndex = rand() % currentPool.size();
    string word = currentPool[randomIndex];

    string hiddenWord(word.length(), '_');
    vector<char> guessedLetters; // track stuff so they don't double guess.
    int lives = 6;
    char rawGuess;

    // the main loop. runs until you run out of juice or figure it out.
    while (lives > 0 && hiddenWord != word) {
        printGallows(lives);
        cout << "\nWord: " << hiddenWord << "\n";
        cout << "Lives left: " << lives << "\n";
        
        if (!guessedLetters.empty()) {
            cout << "Guessed letters: ";
            for (char c : guessedLetters) cout << c << " ";
            cout << "\n";
        }

        cout << "Enter a letter: ";
        cin >> rawGuess;

        // lowercase it because nobody wants to deal with shift key bugs.
        char guess = tolower(rawGuess);
        bool alreadyGuessed = false;
        for (char c : guessedLetters) {
            if (c == guess) {
                alreadyGuessed = true;
                break;
            }
        }

        if (alreadyGuessed) {
            cout << "You already guessed '" << guess << "'! Try a different letter.\n";
            continue;
        }

        // put it in the pile.
        guessedLetters.push_back(guess);

        // check if it's actually in the word. standard linear scan.
        bool found = false;
        for (size_t j = 0; j < word.length(); j++) {
            if (word[j] == guess) {
                hiddenWord[j] = guess;
                found = true;
            }
        }

        if (!found) {
            cout << "Incorrect guess!\n";
            lives--; // rip.
        }
    }

    printGallows(lives);
    if (hiddenWord == word) {
        cout << "\nCongratulations! You won! The word was: " << word << "\n";
    } else {
        cout << "\nGame Over! You ran out of lives. The word was: " << word << "\n";
    }
}

int main() {
    // seed the clock. otherwise it's the same word every time you boot it.
    srand(time(nullptr));
    
    int choice = 0;
    bool hardMode = false; // normal mode by default. keeps it chill.

    // menu loop. keeps spinning until choice hits 4.
    while (choice != 4) {
        cout << "\n===================================\n";
        cout << "  _   _                                   \n";
        cout << " | | | | __ _ _ __   __ _ _ __ ___   __ _ _ __ \n";
        cout << " | |_| |/ _` | '_ \\ / _` | '_ ` _ \\ / _` | '_ \\\n";
        cout << " |  _  | (_| | | | | (_| | | | | | | (_| | | | |\n";
        cout << " |_| |_|\\__,_|_| |_|\\__, |_| |_| |_|\\__,_|_| |_|\n";
        cout << "                    |___/                      \n";
        cout << "===================================\n";

        cout << " 1: Play Game\n";
        cout << " 2: Settings\n";
        cout << " 3: Help / Rules\n";
        cout << " 4: Exit Game\n";
        cout << "===================================\n";
        cout << "Enter choice: ";
        cin >> choice;

        if (choice == 1) {
            playGame(hardMode);
        } 
        else if (choice == 2) {
            int setChoice = 0;
            cout << "\n--- SETTINGS ---\n";
            cout << "Current Difficulty: " << (hardMode ? "HARD" : "NORMAL") << "\n";
            cout << "1. Set to Normal Mode\n";
            cout << "2. Set to Hard Mode\n";
            cout << "Enter choice: ";
            cin >> setChoice;
            if (setChoice == 1) hardMode = false;
            if (setChoice == 2) hardMode = true;
            cout << "Difficulty updated!\n";
        } 
        else if (choice == 3) {
            cout << "\n--- HOW TO PLAY ---\n";
            cout << "1. The computer picks a secret vocabulary word.\n";
            cout << "2. Guess one letter at a time to reveal parts of the word.\n";
            cout << "3. Every incorrect guess builds part of the execution gallows.\n";
            cout << "4. Win by revealing the full word before running out of 6 lives!\n";
        }
        else if (choice == 4) {
            cout << "\nThanks for playing! Goodbye.\n";
        }
        else {
            cout << "\nInvalid choice. Please pick options 1 through 4.\n";
        }
    }

    return 0; // and we're out.
}