Let’s see if I can help you with the logic.
- - -
step 1:
Create at least 3 functions:
A)
void print(/* arguments */);
will display the useful information (the left available characters, the chances left and the std::string with the underscores).
It is supposed to be just a sequence of std::cout.
B) A function to display the win condition (more or less a bunch of cout);
C) A function to display the defeat condition (more or less a bunch of cout).
Now the code is cleaner.
- - -
step 2:
Ask the user for a phrase and save it into
std::string guessword
.
step 3:
Copy all characters that are NOT spaces into another std::string, turning them into uppercase on the fly.
Let's call this variable ‘upp_g_word’.
step 4:
Define another std::string, as long as ‘upp_g_word’, but contains only underscores.
Let's call this variable ‘matches’.
- - -
step 5:
Define a variable to keep the tally of the goes (your
int lives=3;
is fine).
Define a bool variable to exit the following loop by a winning or losing condition.
Define a variable to keep the available characters (your
string z="a b c d...";
is fine, just don’t call it ‘z’, please!).
You don’t need more std::strings than these!!
You need no C-style char array at all!!
- - -
OUTER LOOP
conditions: are there lives left? AND is ‘upp_g_word’ [EQUAL TO|DIFFERENT FROM] ‘matches’ ?
(You need to decide if you want to check for equality or differences).
Inside the loop:
print() <-- see above
- ask for A SINGLE CHARACTER
(later you can improve your code to accept an entire std::string and extract just the first character - but this should be done in a separate function)
Let’s call this variable ‘ans’.
- check if the character has already been chosen and, in case, decrease lives and
continue
.
- remove that character from the list of available ones.
- IN A LOOP
compare the uppercase version of ‘ans’ to each character inside ‘upp_g_word’.
if they match, change the corresponding one into ‘matches’ to ‘ans’.
- END LOOP
If ‘upp_g_word’ and ‘matches’ now match, set the “exit by winning condition” variable to true - you can also exit here, if you want.
If there was at least one match, print "Correct!" and skip the following line.
If there was no matches, print "Incorrect!" and decrease lives.
END OUTER LOOP
step 6:
Ending according to the value of the “exit by winning condition” variable.
= = =
About your current code:
Step 1: listen to your compiler
main.cpp: In function 'int main()':
main.cpp:73:18: warning: comparison of integer expressions of different signedness: 'int' and 'std::__cxx11::basic_string<char>::size_type' {aka 'long long unsigned int'} [-Wsign-compare]
73 | if(q>0||q<z.length())
| ~^~~~~~~~~~~
main.cpp:17:9: warning: unused variable 'j' [-Wunused-variable]
17 | int j,q;
| ^
main.cpp:22:16: warning: 'i' may be used uninitialized in this function [-Wmaybe-uninitialized]
22 | per[i]= word[i];
| ^ |
If you think those are secondary problem because they are classified as ‘warnings’, you are very much mistaken.
Look at the last one, for example:
'i' may be used uninitialized in this function [-Wmaybe-uninitialized] |
The code is:
per[i]= word[i];
Being ‘i’ uninitialized, what do you get?
Step 2: in general, avoid declaring your variables where you don’t have a good value to initialize them.
That often leads to hard to find bugs.
Declaring them in a bunch at the beginning of functions is usually a bad habit.
Step 3: if you aren’t an expert, avoid introducing the entire standard namespace in your code.
“using namespace std;” is a bad, bad habit.
Step 4: Don’t use more variables than you need!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
r=guessword.length();
per[i]= word[i];
for(int i=0;i<r;i++)
{
guessword[i]=toupper(per[i]);
}
word=guessword;
for(int i=0;i<r;i++)
{
if(word[i]==' ')
{
continue;
}
word.replace(i,1,"_");
}
|
So:
per[i]= word[i];
A memory area distant ‘i’ (uninitialized) from ‘per[0]’ (previously uninitialized) has been assigned the value of ‘word[i]’.
Conclusion: ‘per[]’ still contains garbage.
1 2 3 4
|
for(int i=0;i<r;i++)
{
guessword[i]=toupper(per[i]);
}
|
Every elements of ‘guessword’ have been assigned unpredictable values.
Nice.
word=guessword;
‘word’ now contains garbage.
Funny.
Conclusion: you could have made such disaster with a lot of variables less.
The fascinating part is this occasionally happens to work because ‘i’ is not unlikely to be 0!
Luckily at lines 18-19:
(There are other two copies of ‘guessword’)
At line 103:
|
word.replace(findit,1,x.substr(findit,1));
|
(If I don’t misunderstand the code, ‘word’ is restored, char by char, from ‘x’)
And at lines 119-125:
1 2 3 4 5 6
|
if(word==y)
{
system("CLS");
cout<<"YOU WIN! The phrase was "<<y<<endl;
return 0;
}
|
(Yuk! The restored ‘word’ is compared to (a copy of) the original value of ‘guessword’ and it works. Wow!)