-
Hang man program hanging
Can anyone tell me what my major malfunction is here? I want to add other functionality to this program so I decided I might as well use classes and that got me about as far as this
Code:
#include <iostream>
#include "string.h"
using namespace std;
class wordtbg { // word to be guessed by player
string wordtobeguessed; // string to hold word to be guessed
char letterguess; //to hold letter that player guesses is in the wordtobeguessed
public:
string wtbg (string x); //constructor to get the wordtobeguessed
char guessfunc (char x); // function to see if letter guessed is correct or not
} hangman; //object of class wordtbg
string wordtbg::wtbg (string x)
{
wordtobeguessed = x;
}
char wordtbg::guessfunc (char x)
{
char wtbg; //will be used to turn wordtobeguessed from a string to a char type
char thing[5]; //letter guessed
string compare;
do{
for (int i = 0; i < 5; i++)
{
if ( wordtobeguessed[i] == x)
{
thing[i] = x;
compare = thing;
cout << "you guessed " << thing << " which is one of the letters!";
}
else
{
cout << "that's not one of the letters!";
}
}
} while (compare != wordtobeguessed);
}
int main ()
{
hangman.wtbg ("tulip");
char letter;
cout << "please enter a letter: ";
cin >> letter;
hangman.guessfunc (letter);
return 0;
}
everything compiles but when i try to run the program it just hangs and crashes. Incredibly simple and yet... I can't figure out the problem!
-
You've got a few issues with that code that you should probably try to fix before worrying about getting the code to run.
1. #include "string.h" should be #include <string>
2. You're implementing your "constructor" incorrectly. The constructor has the same name as the class, and should have no return type. In your code, the thing you label as a constructor is just a regular function.
3. There's no need to make hangman a global variable. Make it a local variable inside main(). If you're not sure what I mean by this, ask.
4. You have a character array called thing, but you don't initialize it. At the very least you should assign all null characters to it. You should also make it 6 characters long because character arrays require one extra spot for the terminating null.
5. IMO, a better solution would be to change thing to be a string instead. Initialize the string with 5 spaces or something like that to indicate the string hasn't been guessed yet. It look slike you originally tried to use a string but that didn't work. Use string compare(5) and it might work better.
6. You ask the user for a letter, but you don't do that inside your loop. So you loop while the word to be guessed doesn't match the compare word, but the compare word never changes after the first run through. You need to ask for another letter inside your do while loop, or move the loop to main around the letter request.
I'm sure there are other things you can clean up, but that should get you started. Items 4-6 are the most important for fixing the hang.
-
I believe I did everything you said... it still crashes when run. Though it certainly looks better. thanks for the help...
Code:
#include <iostream>
#include <string>
using namespace std;
class wordtbg { // word to be guessed by player
string wordtobeguessed; // string to hold word to be guessed
char letterguess; //to hold letter that player guesses is in the wordtobeguessed
public:
string wtbg (string x); //function to get wordtobeguessed
void guessfunc (); // function to see if letter guessed is correct or not
};
string wordtbg::wtbg (string x)
{
wordtobeguessed = x;
}
void wordtbg::guessfunc ()
{
string thing = " "; //holds letters that are guessed and eventually the word
string compare[6]; // ignore
char letter; // holds the letter guessed by the player
do{
cout << "please enter a letter";
cin >> letter;
for (int i = 0; i < 5; i++)
{
if ( wordtobeguessed[i] == letter)
{
thing[i] = letter;
cout << "you guessed " << thing << " which is one of the letters!";
}
else
{
cout << "that's not one of the letters!";
}
}
} while (thing != wordtobeguessed);
}
int main ()
{
wordtbg hangman;
hangman.wtbg ("tulip");
hangman.guessfunc ();
return 0;
}
-
Code:
string wordtbg::wtbg (string x)
{
wordtobeguessed = x;
}
it is a function, don't you think it shoul return something... like
return wordtobeguessed ;
btw, why you need this function?
wordtobeguessed is public... you can access it direcly...
-
>> it still crashes when run
Add a return statement to your wtbg function or change it to void. That might be causing a crash for you.
>> I believe I did everything you said
You actually did do a good job of that. Except you haven't fixed item #2 yet, but other than the missing return statement that shouldn't cause a problem.
Other than that, when I run the code it doesn't crash. It works for me. There was only one problem. You were outputting the "that's not one of the letters!" statement too often. It should only be output once outside the for loop if the letter is not found. I'd consider adding a new bool variable to remember whether the letter is found so that the right message can be displayed outside the loop.
-
Thanks Daved, It's working now. I can see what I did with the "that's not the letter!" thing... for each [i] that's repeated in the loop it returns the else statement... I'll fix that next... then i'll be back to bother you again when i try to add a menu and random word selection.
-
sorry... i took itu wrong...
wordtobeguessed is private not public...
something was wrong with my eyes...
hehehe...
nice to hear it is working now....
:)
-
Yeah, Auralius it's private... I didn't go into writing this program with a plan so I just sort of skipped a whole bunch of readability steps (such as typing out "private:" to be clear which variables were private).
For now I am making a menu (just a "would you like to play hangman?") thing... I want to make a class for it though so that I can add different functionality to it later. The thing is, the only way I know how to make a menu is with a CASE BREAK setup. Is that sufficient or are there better ways to write menus that are perhaps more clever? No need to go in depth, i'll do all the research, I just need a direction to start in!
-
i think CASE BREAK is ok... :)
but why you declare hangman in global?
i think it is better not to use global variable (if it is possible)...
that's why it is called c++, right?
we use thee oop rule...
-
Yeah, when I changed it into its working form I declared the object "hangman" in main instead of globally. Probably good to do that from now on... don't want to do that and get all messed up later on!
to be clear
Code:
int main ()
{
wordtbg hangman;
.
.
.
.
that's how I changed it.
wait... what's the OOP rule?
added the menu, I wanted to make a menu class but I don't know if you can call a class inside a class... I am sure you can make it a friend or something but this is much more simple... now to add random word selection from a file!!!
Code:
int main ()
{
wordtbg hangman;
hangman.wtbg ("tulip");
int choice;
cout << "Please make a selection:\n";
cout << "1: Play HangMan!\n";
cout << "2: quit\n";
cin >> choice;
switch (choice)
{
case 1:
hangman.guessfunc ();
break;
case 2:
break;
}
return 0;
}
-
Ok... I know how to use and set rand() but is there a place that will show me how to select a line from an ifstream so that I can say "ifstreamfile ("blah.txt", randomlinenumer) = wordtobeguessed" so that I can take a random line and make "wordtobeguessed" equal to the string/char string on that random line?
-
There are plenty of ways, the easiest of which may be reading n lines (where n is a random number) and then assigning the last word read as the one to be guessed.
-
This is how I am trying this... it's obviously not working. I was just trying to get the first line in the file as a sort of test to see if I could properly use ifstream... turns out I can't lol!
Code:
string wordtbg::wtbg (void)
{
ifstream wordfile ("words.txt" , ios::in); // input file stuff... getting the file
if (!wordfile) // check to see if file opens or what ever
{
cout << "could not get word from file :'( ";
return wordtobeguessed;
}
istream& getline(istream& wordfile, streamsize); // get a ling in the wordfile.. not sure this is how this member/function works though
cout << wordtobeguessed; // just to verify it worked (it doesn't lol)
return wordtobeguessed;
}
I have no idea how to assign the line to "wordtobeguessed" ...
-
I think that you actually want to call the function instead of attempting to declare it:
Code:
string wordtbg::wtbg()
{
ifstream wordfile("words.txt", ios::in);
if (!wordfile)
{
cout << "could not get word from file :'( ";
wordtobeguessed = "";
}
else
{
getline(wordfile, wordtobeguessed);
cout << wordtobeguessed << endl; // just to verify it worked
}
return wordtobeguessed;
}
However, your class design looks a little awkward. I would suggest something like this:
Code:
class HangManWord
{
public:
// Initialise with the answer to be guessed.
explicit HangManWord(const std::string& answer);
// Returns true if letter is in the answer.
bool guess(char letter) const;
// Returns true if word is the answer.
bool guess(const std::string& word) const;
private:
std::string answer;
};
Then your current wtbg() member function would become a free function that say, returns a HangManWord object, or throws an exception if the file could not be opened. You could also provide a default constructor and a setter function if you think that it is necessary, and perhaps use a HangMan namespace so you have a HangMan::Word object instead.
-
Laserlight: I'm really new to programming and C++ so that'd be why my classes are funky. I really haven't even read anything about OOP design or even covered all the standard C++ things. I read through Cplusplus.com and C++ demystified but those only really teach you what certain things are and not how to use them. I just got C++ how to program and practical C++ programming, so i'll be reading through those soon. I'll try to implement your "HangManWord" class tomorrow and get back to you. For now I changed the member "wtbg" and it gets the first line of my file, which is "stuff" and I tried to create a way to count the letters in the random word so far it doesn't work... and I know it probably has something to do with a completely novice mistake
where end is equal to '\n'
Blah is an integer set to 0
and thing is a string that would be initialized with all '-' characters for as many characters are in the random word.
Code:
for (int w = 0; end != wordtobeguessed[w]; w++) //determine number of letters in wordtobeguessed
{
blah++;
}
for (int f = 0; f < blah; f++) //fill thing with "-" characters for as many letters are in wordtobeguessed
{
thing[f] = '-';
}