3
\$\begingroup\$

Most hangman implementations I have seen keep a list of characters the player has already guessed and compares them to the players current guess each time to see if they have already made the same guess. My implementation checks if the word was changed after replacing any matches. Is my implementation easier to understand as well as more efficient than this one Hangman game logicistics and cleanliness?

Side Question: Should I use static variables in loops?

Hangman

#include <iostream>
#include <fstream>
#include <cassert>
#include <vector>
#include <random>
#include <string>

std::string replace_if_match(std::string& write, const std::string& read, const std::string& match)
{
    assert( write.length() >= read.length() );

    for( int search_pos{0}; (search_pos = read.find( match, search_pos )) != -1; ++search_pos){

        write.replace( search_pos, match.length(), match );
    }
    return write;
}

int main()
{   
    std::ifstream file("word_list");
    assert( file.is_open() );

    std::vector<std::string> word_list;

    while( !file.eof() ){

        static std::string word;
        file >> word;
        word_list.push_back( word );
    }
    file.close();

    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_int_distribution<int> dist(0, word_list.size() - 1);

    std::string unknown_word;

    std::string previous_word;

    std::string guessed_word;

    std::string guess;

    int num_of_guesses;

    int in_game{true};

    while( in_game )
    {
        unknown_word = word_list[dist(mt)];

        guessed_word = std::string().append( unknown_word.length(), '_' );

        num_of_guesses = 5;

        while( num_of_guesses > 0 && unknown_word != guessed_word )
        {
            std::cout << guessed_word << '\n'; 

            std::cout << "Number of Guesses Left: " << num_of_guesses << '\n';

            std::cout << "Enter a string as guess.\n";
            std::cin >> guess;

            previous_word = guessed_word;

            if( previous_word == replace_if_match( guessed_word, unknown_word, guess ) ){

                num_of_guesses--;
            }
        } 
        if( guessed_word == unknown_word ){

            std::cout << "We did not have a noose for you any way.\n";
        }
        else{ 

            std::cout << "You loser, the word was " << unknown_word << "!\n"; 
        }
        std::cout << "Would you like to try another? <Yes: 1, No: 0>\n";
        std::cin >> in_game;
    }
}
\$\endgroup\$
2
\$\begingroup\$

I find this function signature quite confusing:

std::string replace_if_match(std::string& write, 
                             const std::string& read, const std::string& match)

The names write, read, and match aren't very descriptive and everything is being passed in by reference, so what is it going to be returning?

Changing the parameter names to something like guessed_word, word_to_guess and guess might be more descriptive. The return still feels wrong though, why not just have it return true/false to indicate if replaces have been made?

The implementation you've made doesn't really conform to the standard rules of Hangman. One of the advantages of keeping track of characters guessed is that it ensures you only guess one character at a time. With your current approach, it's possible to guess partial words (so you can guess 'hang' and it would find the start of 'hangman'). Character matching also encourages you to think about casing, 'H' != 'h' with your current approach. These choices may be intentional, but it feels unexpected.

\$\endgroup\$
  • \$\begingroup\$ I wanted to create a robust function that could be used in another case. Is there a standard library function that I could use instead? Why not let the user guess entire phrases? Is the way I am checking less efficient? I think you are right about casing. Hangman is not case sensitive. I can fix that. \$\endgroup\$ – dylan May 23 '16 at 19:31
  • \$\begingroup\$ I can also easily change it to only accept single character string guesses. \$\endgroup\$ – dylan May 23 '16 at 19:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.