1

Currently I am working on a hangman game, I had previously coded it to only work for a 5 letter word, but now would like to make it handle any length of word, how could I change this code to make it work how I want it to?

#include "stdafx.h"
#include <iostream>
#include <string>
#include <stdlib.h>
#include <cstdlib>
using namespace std;

int main()
{
string word;
int tries;
string guess;
string wordguess;
string output;

cout << "Enter a word for player two to guess: ";
cin >> word;
system("CLS");
cout.flush();
cout << "Guess the word!" << endl;

for (int i = 0; i < word.length(); i++)
{
cout << "_ ";
}

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

for (int tries = 5; tries > 0; tries--)
{
if (guess[0] == word[0]) {
    output[0] = word[0];
    cout << "You guessed the first letter! Good job!" << endl;
}
if (guess[0] == word[1]) {
    output[2] = word[1];
    cout << "You guessed the second letter! Good job!" << endl;
}
if (guess[0] == word[2]) {
    output[4] = word[2];
    cout << "You guessed the third letter! Good job!" << endl;
}
if (guess[0] == word[3]) {
    output[6] = word[3];

    cout << "You guessed the fourth letter! Good job!" << endl;
}
if (guess[0] == word[4]) {
    output[8] = word[4];
    cout << "You guessed the fifth letter! Good job!" << endl;
}

cout << output << endl;
cout << "You have " << tries << " tries left. Take a guess at the word: " << endl;
cin >> wordguess;
if (wordguess == word)
{
    cout << "Congratulations, you guessed the word correctly!" << endl;
    break;
}
}
    system("pause");
    return 0;
}

As you can tell I was checking each position from 0 to 4 (first through fifth letter). I know there are plenty of ways that I could have coded this better but as you can guess, I am new to coding and this is the way I thought of it. Please note this is still a work in progress so it is not fully complete. Any help would be great!

ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152
zhodges10
  • 5
  • 3
  • I think you are looking for a `std::set` of letters that is the word. – Captain Giraffe Oct 21 '17 at 01:58
  • Sounds like it would work, so if the word was "play" it would consider it a set of p, l, a, and y? – zhodges10 Oct 21 '17 at 02:00
  • `output[x]` is undefined behavior since `output` is empty (it will not automatically grow the string). You can use a loop over the characters in `word`, but you will need some general way of getting the English word for "first", "second", etc. – aschepler Oct 21 '17 at 02:00
  • Instead of the if statements, you would `find` the guesses. Yes. – Captain Giraffe Oct 21 '17 at 02:00
  • A `std::set` wouldn't give you any information about which position(s) a correct guess is in. – aschepler Oct 21 '17 at 02:01
  • @aschepler Why would the initial string be discarded? – Captain Giraffe Oct 21 '17 at 02:02
  • I guess I should have added this, prior to change some of the code, output was set to "_ _ _ _ _" and each underscore would change to its corresponding letter. – zhodges10 Oct 21 '17 at 02:03
  • Possible duplicate of [For every character in string](https://stackoverflow.com/questions/9438209/for-every-character-in-string) – ivan_pozdeev Oct 21 '17 at 03:13
  • On a side note, [you aren't supposed to include C headers like `stdlib.h` in C++ but rather their C++ equivalents like `cstdlib`](https://stackoverflow.com/questions/2900785/whats-the-difference-between-cstdlib-and-stdlib-h). – ivan_pozdeev Oct 21 '17 at 18:26

3 Answers3

2

When designing an algorithm, think of how you would do this by hand, without a computer. Then let the code do the same.

If you were checking your friend's guess against a word written on sand, you would probably go about it like this:

  • go through the written pattern character by character, pronouncing your word in memory
  • for each letter, check if it is equal to the guess
  • if it is

    • replace the placeholder with it
    • memorize that your friend guessed right.
    • Also note if there are any placeholders left
      • if there aren't, your friend wins
  • finally, if your friend didn't guess right, score them a penalty point and check if they lose

Now, all that leaves is to put this down in C++. The language provides all sorts of entities - let's check which ones fit ours needs the best:

  • the word and the current pattern - strings of a fixed size
  • bits to memorize:

    • whether the current guess is right - bool
    • placeholders left - int
    • penalty points (or, equivalently, attempts left) - int
  • parts of the algorithm:

ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152
0
// Example program
#include <iostream>
#include <string>
using namespace std;

class my_game
{
private:
    string congrats_array[15] = {"first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "nineth", "tenth", "eleventh", "twelfth", "thirteenth", "fourteenth", "fifteenth"};
    string word_to_guess;
    int tries_left;
    int word_length;
    int letters_guessed_count;
    string guessed_letters;

    void check_letter(char letter); 
    void print_current_word_state();

public:
    my_game();
    void begin_the_game();
    void play_the_game();   
};

my_game::my_game()
{

}

void my_game::begin_the_game()
{
    cout << "Enter a word for player to guess: " << endl;
    cin >> word_to_guess;
    system("CLS");
    cout.flush();

    cout << "Enter the tries amount!\n" << endl;
    cin >> tries_left;

    word_length = word_to_guess.size();

    guessed_letters = "_";
    letters_guessed_count = 0;

    for(int i = 0; i < word_length - 1; i++){
        guessed_letters += "_";   
    }
}

void my_game::play_the_game()
{
    cout << "Guess the word!" << endl;
    char letter;

    for(int i = 0; i < tries_left; i++)
    {
        cout << guessed_letters << endl;
        cout << "Enter a letter: " << endl;
        cin >> letter;
        check_letter(letter);

        if(letters_guessed_count == word_length){
            cout << "Congrats! You won!" << endl;
            return;
        }
    }

    cout << "You lose" << endl;
}

void my_game::check_letter(char letter)
{
    for(int i = 0; i < word_length; i++)
    {
        if(word_to_guess[i] == letter && guessed_letters[i] != letter)
        {
            guessed_letters[i] = letter;
            letters_guessed_count++;
            cout << "You guessed the" << congrats_array[i] <<"letter! Good job!" << endl;
        }
    }
}


int main()
{
  my_game game;
  game.begin_the_game();
  game.play_the_game();
}
Alex
  • 94
  • 9
  • Could you elaborate why there are 15 places in the array? Would that mean the word could only be up to 15 letters, correct? – zhodges10 Oct 21 '17 at 03:36
  • Exactly. You can add it up to 50, because the longest word is 45 letters length, and after 20 you can just concat words: 20 + 1 etc, so u actually need about 25 words in that array. I am just too lazy xD. And I thought that author may code it by himself. And also that 15 letter word is enough long to play for the first time. – Alex Oct 21 '17 at 04:10
  • It is the limit of only "You guessed the n-th letter! Good job!" phrase, which is printed. If you skip it, or add words in the array as I said above, you can skip this limit. – Alex Oct 21 '17 at 04:13
0

So, in short what you need to do this with words of any arbitrary length is to use string's .substr() function and the stringstream library's .str() and << and >> operators. This version of your code uses a function that inserts a correctly guessed character at the appropriate indexed location. This will gradually replace the "_________" with letters at the correct places. This is much easier to do in Java, but stringstream is a good library I would highly recommend getting familiar with it. I'll leave the problem of how to handle multiple instances of a guessed character up to you (ie 'i' in "bibliography")

#include <string>
using std::string;

#include <sstream>
using std::stringstream;

#include <iostream>
using std::cout;
using std::cin;
using std::endl;

string newString(string, int, string);

int main()
{
    string word;
    string guess;
    int tries;
    string output;

    string input;

    cout << "Enter word for player 2 to guess: "; 
    cin >> word;

    stringstream ss;

    //---------- fills the stream with "_"s matching the length of word

    for(int i = 0; i < word.length(); i++)
        ss << "_";

    //----------- assigns the initial value of "___..." to output

    ss >> output;

    //----------- sets up the loop 

    tries = 5; 
    bool found = false;

    for(int i = 0; i < 5; i++)
    {
        cout << "\nTry " << i << " of 5: Enter a letter or guess the word: "; 
        cin >> input;

        if(input == word)
        {
            cout << "Congratulations, you guessed the word correctly!" << endl;
            break;
        }

        //------------------ else, proceed with replacing letters 

        if(word.find(input) != std::string::npos)
        {
            size_t position = word.find(input);                                         // finds index of first instance of the guessed letter
            cout << "You guessed the " << position+1 << " letter! Good job!" << endl;   // since strings start at index 0, position+1

            //------- replaces appropriate "_" with the guessed letter

            output = newString(input, position, output);
            cout << "\n" << output;

             // Around here you'll want to set up a way to deal with multiple instances 
             // of the same letter

        }
        else
            cout << "Incorrect guess" << endl; 
    }

    return 0;
}

//---------------------------------------------------

string newString(string guess, int index, string word)
{
    string NewString;
    stringstream temp;

    //---------- hack up the string into sections before and after the index

    string before = word.substr(0, index);
    string after = word.substr(index+1, word.length() - index+1);

    //---------------- populates the new stringstream and assigns it to the result

    temp << before << guess << after;

    NewString = temp.str();

    return NewString;
}
Adam Coville
  • 141
  • 7