Sign in to follow this  

Hangman!

This topic is 4168 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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[i] = '_';
    }
    
    welcome();
    while(!done) {
        
        system("cls");
        cout << "The word so Far:\n\n";
        
        for(int i = 0; i != theWord.size(); i++) {
            cout << soFar[i] << " ";
        }
        
        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[i] == goodGuess) {
                        soFar[i] = 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[i]) {
            return cGuess;
        }
    }
    
    return 0;
}

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
you might want to use STRING COMPARE "strcmp" instead of "=="

Share this post


Link to post
Share on other sites
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...?

Share this post


Link to post
Share on other sites
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?


// bad
cout << "foo\n\n";
// good
cout << "foo\n" << endl;

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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[i] = '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] = '_';
}
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

Share this post


Link to post
Share on other sites
Driv3Mefar explained why, but i'll try to break it down a little more.
A string is really just an array of letters, for example:

std::string str1 = "HELLO";
/* str1 can be thought of as the following array:
INDEX: 0 1 2 3 4
=====================
DATA: | H | E | L | L | O |
=====================
*/




So lets say you do this instead:

std::string str1;
/* str1 can be thought of as the following array:
INDEX:
==
DATA: ||
==
So if you then try to reference the i-th character
(in a for loop as an example), you are trying to reference
an index that isn't in the strings length which is 0

The reason why doing str1 = str1 + 1; works is because you are
increasing the length of the array and adding the character
to the end, and have: */

std::string str1; // value is "" length is 0
str1 = str1 + "_"; // increases the length to 1 and value becomes "_"
str1[2] = 'x'; // not in the length of the string, string value is still "_"



I hope this helps to clear it up some more even, and I am always happy to help!

-sevans




Share this post


Link to post
Share on other sites
Quote:
Original post by Sevans
Driv3Mefar explained why, but i'll try to break it down a little more.
A string is really just an array of letters, for example:
*** Source Snippet Removed ***

So lets say you do this instead:
*** Source Snippet Removed ***

I hope this helps to clear it up some more even, and I am always happy to help!

-sevans


Sevans, thank you for the awesome insight into strings. That is how I had guesses they worked, but wasn't sure.

Share this post


Link to post
Share on other sites

This topic is 4168 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this