Hangman!

Started by
10 comments, last by -JetSirus- 17 years, 9 months ago
Hello, I'm trying to complete one of the excercises at the end of a chapter, and theres one thing i cannot get to work. If the user guesses the work, it should tell them they've won, but it doesnt! Please take a glance and see if you see something i dont. Source:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <ctime>
using namespace std;

void welcome();
char getGuess(string question);
char checkGuess(string theWord, char guess);

int main()
{
    srand(time(NULL));
    char guess;
    bool done = false;
    
    vector<string> words;
    words.push_back("guitar");
    words.push_back("vampire");
    words.push_back("sponge");
    words.push_back("comcast");
    words.push_back("love");
    
    // randomly picks a word
    random_shuffle(words.begin(), words.end());
    string theWord = words[0];
    
    string soFar;
    char goodGuess;
    const int MAX_GUESS = theWord.size();
    int numGuess = 0;
    int counter = 0;
    
    for(int i = 0; i != theWord.size(); i++) {
        soFar = '_';
    }
    
    welcome();
    while(!done) {
        
        system("cls");
        cout << "The word so Far:\n\n";
        
        for(int i = 0; i != theWord.size(); i++) {
            cout << soFar << " ";
        }
        
        guess = getGuess("\n\nPlease Enter in 1 Letter: ");
        goodGuess = checkGuess(theWord, guess);
        
        if(theWord.find(goodGuess) != string::npos) {
                for(int i = 0; i != theWord.size(); i++) {
                    if(theWord == goodGuess) {
                        soFar = goodGuess; 
                        --numGuess;
                    }
                }
            } 
        
        if(MAX_GUESS <= numGuess) {
            cout << "\nHAHAHA! YOU LOSE!\n\n";
            system("pause");
            done = true;
        }
         
        if(soFar == theWord) {
              cout << "\nOMG! YOU WON!\n\n";
              system("pause");
              done = true;
        }
        
        ++numGuess;
    }
    
    return 0;
}

//////////////////////////////////////////////////////////////////////////
/////                                                                /////
/////                        FUNCTION DEFINITIONS                    /////
/////                                                                /////
//////////////////////////////////////////////////////////////////////////

void welcome()
{
    cout << "Welcome to Hangman! Good Luck!\n\n";
    system("pause");
}

char getGuess(string question)
{
    char playerGuess;
    
    cout << question;
    cin >> playerGuess;
    
    return playerGuess;
}

char checkGuess(string theWord, char guess)
{
    char cGuess = guess;
    
    for(int i = 0; i != theWord.size(); i++) {
        if(cGuess == theWord) {
            return cGuess;
        }
    }
    
    return 0;
}

Advertisement
you might want to use STRING COMPARE "strcmp" instead of "=="
It works if you init your soFar string with the underscores when you declare it. Like this:
string soFar(theWord.size(), '_');
---------------------------------------------Warning: This post may contain traces of Q-Basic
Quote:Original post by Anonymous Poster
you might want to use STRING COMPARE "strcmp" instead of "=="


Actualy, when using std::string, it is better to use ==, not functions designed for C-style strings.

Edit: Also, your checkGuess function seems somewhat useless. All it does is make a local variable, with which you do nothing that would warant using a new local variable rather than the variable you pass in to the function, search through the word, and if you find that character, return it. After which, you proceed to search through the word again, looking for the same character...?
Quote:Original post by Anonymous Poster
you might want to use STRING COMPARE "strcmp" instead of "=="


Incorrect. You might want to use C++.

OP:

- soFar is a string, so why not just display it as a string instead of iterating over characters? Similarly, there is a much easier way to initialize it: use the constructor accepting an int 'n' and a char 'c', which initializes the string to 'n' length with every letter being 'c'.

- You probably don't want to reduce the guess count by one for every time the letter appears. :s

- The checkGuess() logic is rather dubious. Just replace the characters, counting up the ones that were replaced. Then, if none are replaced, increment the guess count. That also addresses the previous problem.

- As for actually getting the text to appear, did you try flushing the buffer?

// badcout << "foo\n\n";// goodcout << "foo\n" << endl;
Quote:Original post by PlutoWarrior
It works if you init your soFar string with the underscores when you declare it. Like this:
string soFar(theWord.size(), '_');


Thank you very much!

Can you explain why it works like this but it doesnt work the way i had it? I cannot understand it. [sad]
Quote:Original post by NUCLEAR RABBIT
Quote:Original post by PlutoWarrior
It works if you init your soFar string with the underscores when you declare it. Like this:
string soFar(theWord.size(), '_');


Thank you very much!

Can you explain why it works like this but it doesnt work the way i had it? I cannot understand it. [sad]


When you decliar the string without initializing it, the string has no idea how long it should be, so it does not reserve any space in memory. As far as it is concerned, it is the null string "". When you try to index into the string using the subscript operator, you are writting to memory that does not belong to it. This results in the string not changing (not a big deal) and you hosing memory that belongs to something else (this is a big deal).
EDIT: Driv3mefar explained what I failed to in the rest of this post. Your loop to iterate through all of the characters is indexing characters which have not been set, the reason why the method I show works is because I am adding characters to the end of the string. anyways later on in the rest of the post just ignore where i said i wasnt sure what is going on, this edit should have helped explain it.

And MAN you guys post fast, no one had posted and now like 4 ppl in the time it took me to write this one!
REST OF THE POST IS BELOW:

To see what is going on here, insert the following into lines 43 and 44

        system("cls");    // line 42        /* begin added code */            cout << "DEBUG: theWord is: " << theWord << endl;  // new line 43            cout << "DEBUG: soFar is: " << soFar << endl;      // new line 44        /* end added code */        cout << "The word so Far:\n\n";  // old line 43, becomes line 45


You will see that so far is printing out as if it is empty. odd, lets see what happens if we try this instead:
        system("cls");    // line 42        /* begin added code */            cout << "DEBUG: theWord is: " << theWord << endl;  // new line 43            cout << "DEBUG: soFar[0] is: " << soFar[0] << endl; // new line 44        /* end added code */        cout << "The word so Far:\n\n";  // old line 43, becomes line 45

Now we see that the first letter of so far is printed out.

I had a hunch that using the [] operator (like soFar = 'somecharacter') was what was causing the trouble. So I looked for the previous time that you set soFar[something] = somethingElse; this is at line 36:
you had
for(int i = 0; i != theWord.size(); i++) { // line 35
soFar = '_';
}
I am not 100% sure why this would cause soFar (which is of string type not character array type) to act like a character array, but because of that, the comparison at line 67:
if(soFar == theWord) {
does not work.

So if we change line 36 to:
for(int i = 0; i != theWord.size(); i++) { // line 35
soFar = soFar + '_'; // this works, assuming soFar was empty to begin with
}
Also be sure to change line 44 back to:
cout << "DEBUG: soFar is: " << soFar << endl;

It should work properly now. Once it does just remove the line 43 and 44 debug output lines we added. If for some reason this doesn't work for you following the source i copied and pasted let me know I will just paste the whole thing.

As far as why it switched to acting like a character array and using the character array operators instead of string class operators I haven't the slightest idea, hopefully somone else can explain why.

SIDE NOTE: I know that a string is really just an array of characters
I meant in terms of C++ type, for the sake of explaination ^.^d

Good luck with your code, let me know how this goes

-sevans
-Sevans
to Sevans & Driv3meFar,

Thank you for the explainations! [smile] Helped out alot and i got it working!

If you have anymore information on why it was acting like it was, please tell me. [lol]
I can't believe I overlooked that one of my "style" suggestions would actually fix the problem. x_X

This topic is closed to new replies.

Advertisement