Hangman game - while loop with condition "contained in an array" - c++

I'm creating a hangman game. I'm having a problem asking the user to reenter a new guess(char) if they have entered that same one already(these are contained in the letters[] array). I have started with a while loop that asks the user to reenter if "guess" matches one of the chars that stored in the array. Thanks.
void play(string word)
{
string copy = word;
for(int i = 0; i < word.length(); i++)
{
copy[i] = ' ';
}
bool match = false;
bool valid = false;
int chance = 5;
char letters[26];
int counter = 0;
char guess;
while (chance > 0 && match == false)
{
int blanks = 0;
for (int i = 0; i < word.length(); i++)
{
if(copy[i] == ' ')
blanks++;
}
cout << '|';
for(int i = 0; i < word.length(); i++)
{
cout << copy[i] << '|';
}
cout << "\t(There are '" << blanks << "' blanks)" << endl;
cout << "Incorrect letters guessed: ";
for (int i = 0; i<counter; i++)
{
cout << "'" << letters[i] << "' ";
}
cout << "\n\nEnter guess: ";
cin >> guess;
for(int i = 0; i < counter; i++)
{
if(guess == letters[i])
valid = true;
}
while (valid == true)
{
for(int i = 0; i < counter; i++)
{
if(guess == letters[i])
valid = true;
else
valid = false;
}
if (valid)
{
cout << "\n\nAlready tried that one. Enter guess: ";
cin >> guess;
}
}
long find = word.find(guess);
if (find != string::npos)
{
copy[find] = word[find];
for (int i = 0; i < word.length(); i++)
{
if (word[i] == word[find])
{
copy[i] = word[find];
}
}
}
else
{
chance--;
letters[counter] = guess;
counter++;
printMan(chance);
}
if (copy == word)
{
match = true;
}
}
if (match == true)
cout << "\nYou saved a life! You managed to win! Congrats, cheater." << endl;
else
cout << "\nThe man has been hung! You LOSE! The word was '" << word << "', you idiot." << endl;
}

for(int i = 0; i < counter; i++)
{
if(guess == letters[i])
valid = true;
else
valid = false;
}
The problem with this for loop is that after you find a valid guess... you don't stop looping.
You go on and check if letter equals the next value in the loop too - and the next and the next. and valid keeps getting overwritten over and over until you get to the end of the loop - at which time valid equals the value of the check against the last letter in letters.
so your "check guess" code only gets called if guess matches the last letter in letters.
You need to look up how to exit out of a loop at the moment that you find a matching guess.

Related

for loop with nested if statement stops iterating after first iteration becomes true. C++

I have a function that receives a character "x" from a user. If the "x" exists in a hard-coded array, "x" is pushed into another array filled with lowdashes in the same position as in the first array. Fo example:
firstArray = ["h", "e", "l", "l","o"]
//user provided character that exist in first array. "e"
lowDashesArray= ["_", "e", "l", "l", "o"]
Then, I want to check if both arrays are equal, my problem is that when the user guesses the firts element in the array (in the above example "h"), the for loop stops iteraring without checking if the other elements are equal. As a result, the block of code that expects both arrays to be equal is executed.
The function looks like so:
bool checkIfLetterExistOnWord(string word, char letter, char* lettersArray, char* lowDashesArray, bool hasWon, bool hasLost, int lives){
bool isCorrectLetter = false;
for(int i = 0; i<word.length(); i++ ){
if(letter == lettersArray[i]){
int position = i;
lowDashesArray[position] = letter;
cout << lowDashesArray;
cout << endl;
isCorrectLetter = true;
}
}
if(isCorrectLetter){
for(int j = 0; j < word.length(); j++){
if(lettersArray[j] == lowDashesArray[j]){
hasWon = true;
//here is the problem. But only when user guesses the first element of the array
}
else{
break;
}
}
if(hasWon){
cout << "You have won";
cout << endl;
cout << hasWon;
cout << endl;
cout << lowDashesArray;
cout << endl;
cout << word;
cout << endl;
return hasWon;
}
else{
cout << "good job. Guess the next letter";
cout << endl;
return hasWon;
}
}
else{
cout << "wrong";
cout << endl;
lives--;
if(lives == 0){
hasLost = true;
cout << "You lost";
return hasLost;
}
else {
cout << "You still have this lives :";
cout << endl;
cout << lives;
cout << endl;
return hasLost;
}
}
}
Both your loop logic is incorrect.
bool isCorrectLetter = false;
for(int i = 0; i<word.length(); i++ ){
if(letter == lettersArray[i]){
int position = i;
lowDashesArray[position] = letter;
cout << lowDashesArray;
cout << endl;
isCorrectLetter = true;
}
}
Here you print the array once for every occurance of the guess character. FUrthermore you do not check, if the letter "was already uncovered". You need to do the printing after the loop and depending on whether you want guessing uncovered chars to be an error, you may need to ajust the check.
for(int j = 0; j < word.length(); j++){
if(lettersArray[j] == lowDashesArray[j]){
hasWon = true;
//here is the problem. But only when user guesses the first element of the array
}
else{
break;
}
}
You're trying to check here, if every char meets a certain criterion (being a non placeholder char). In this case you cannot break early. In general the loop for this kind of check needs to look like this:
bool checkSuccess = true;
for (size_t i = 0; checkSuccess && i != length; ++i)
{
if (!Check(elements[i]))
{
checkSuccess = false;
}
}
Or in your case (using break instead):
hasWon = true;
for(int j = 0; j < word.length(); j++)
{
if(lettersArray[j] != lowDashesArray[j])
{
hasWon = false;
break;
}
}
Imho it's preferrable to separate the replacement logic from io logic. You could e.g. rewrite the logic similar to this:
constexpr char MaskChar = '_';
/**
* Replaces placeholders in \p maskedText, if they the corresponding char in \p clearText
* matches \p guess.
*
* \param[in,out] maskedText the text with some chars replaced with '_'
*
* \return true, if at least one char was replaced, false otherwise
*/
bool GuessChar(std::string const& clearText, std::string& maskedText, char const guess)
{
assert(clearText.length() == maskedText.length());
bool guessCorrect = false;
for (size_t i = 0; i != clearText.length(); ++i)
{
if (maskedText[i] == MaskChar && clearText[i] == guess)
{
guessCorrect = true;
maskedText[i] = guess;
}
}
return guessCorrect;
}
int main()
{
std::string const clearText = "hello";
std::string maskedText(clearText.length(), MaskChar);
size_t lives = 3;
while (lives > 0 && maskedText.find(MaskChar) != std::string::npos)
{
std::cout << "Word: " << maskedText
<< "\nMake your guess!\n";
char c;
std::cin >> c;
if (GuessChar(clearText, maskedText, c))
{
std::cout << "Guess correct!\n";
}
else
{
--lives;
std::cout << "Guess incorrect\n"
<< lives << " lives left\n";
}
}
if (lives > 0)
{
std::cout << "You win!\n";
}
else
{
std::cout << "You loose!\n";
}
}

I have a hangman game I'm making, and I need help figuring out why it's not fully working

I'm making a hangman game in C++ and I am close to finishing, however I have one major issue. I have to get the game to only allow the user 4 guesses, but my program doesn't register the correct number of guesses.
I've tried to change variables as well as the conditions within the if and else statements regarding guessing.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
cout << "Welcome to hangman!" << endl;
char choice = 'y';
while (choice == 'y') {
string word;
cout << "Enter a word to guess: ";
getline(cin, word);
if (word.empty()) {
cout << "The word should not be blank.\n";
continue;
}
bool contain_space = false;
for (char c : word) {
if (isspace(c)) {
contain_space = true;
break;
}
}
if (contain_space) {
cout << "The word cannot contain spaces.\n";
continue;
}
vector <bool> index;
for (int i = 0; i < word.size(); i++) {
index.push_back(false);
}
**int guess_correct = 0;**
int guess_wrong = 4;
char letter;
while (guess_wrong >= 0 && guess_correct < word.size()) {
bool valid_guess = true;
cout << "Guess a letter." << endl;
cin >> letter;
for (int i = 0;i < word.size(); i++) {
if (word[i] == letter) {
valid_guess = true;
index[i] = true;
guess_correct++;
break;
}
else {
guess_wrong = guess_wrong - 1;
}
}
for (int i = 0; i < word.size(); i++) {
if (index[i] == true) {
cout << word[i] << "\t";
}
else {
cout << "___\t";
}
}
cout << endl;
}
cout << "Would you like to play again? (y/n)" << endl;
cin >> choice;
cin.ignore();
}
return 0;
}
The black ticks show the beginning of the code section I'm stuck on. Each time I run it, it will let me go through the game with correct guesses, but incorrect guesses don't allow for 4.
You are decrementing guess_wrong for each letter in the word that doesn't match, not once for the "whole guess".
you probably want to move the guess_wrong = guess_wrong - 1; // aka guess_wrong-- out of the for loop and only do it if (!valid_guess).

Replace characters in old array

I'm solving a problem and stuck on last part now what i am doing. Taking 5 characters from user and save it on character array and than saying enter 3 characters to check does array has your enter characters in it.
For example: User enter 5 characters dagpl.Than second array subArray which search characters from main array now user enter 3 charactersdgl.Result saying 3 characters found. Are you want to replace these 3 characters with new characters? So enter 3 new replace characters now user enter xyz.
Final array would be replace like this xaypz.
My Code doesn't working fine for replacing characters i don't know what i'm doing wrong.
#include<iostream>
#include<cstdlib>
using namespace std;
int main(int argc, char**argv) {
bool check = false;
char arr[6] = { '\0' };
char subarr[4] = { '\0' };
int count = 0;
cout << "Enter Characters : ";
for (int i = 0; i < 5; i++) {
cin >> arr[i];
}
cout << "Enter 3 Characters and see how many times does array has your Search Characters : ";
for (int i = 0; i < 3; i++) {
cin >> subarr[i];
}
//Sub Array
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
if (subarr[i] == arr[j]) {
if (!check) {
cout << "Found characters are: ";
}
count++;
cout << subarr[i] << ",";
check = true;
}
}
}
if (check) {
cout << '\b';
cout << " ";
cout << endl;
}
if (!check) {
cout << "Sorry Nothing Found" << endl;
}
cout << "total Found : " << count << endl;
//SECTION 3
if (check) {
int n = count + 1;
char* replace = new char[n]();
cout << "You can only replace " << count << " new characters because of find operation! so enter it will be replace old array with it: ";
for (int i = 0; i < n - 1; i++) {
cin >> replace[i];
}
//Replace characters
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < 5; j++) {
if (subarr[i] == arr[j]) {
arr[j] = replace[j];
}
}
}
delete[]replace;
replace = NULL;
cout << "New Array would be: ";
for (int i = 0; i < 5; i++) {
cout << arr[i];
}
cout << endl;
}
system("pause");
return EXIT_SUCCESS;
}
You're not marking the matched characters from arr
Replace the matched characters from arr[j] with a distinct character so that you can determine where to replace later. you can use null terminator
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
if (subarr[i] == arr[j]) {
if (!check) {
cout << "Found characters are: ";
}
count++;
cout << subarr[i] << ",";
check = true;
arr[j]='\0'; //replacing the matched character with null terminator
}
}
}
Now traverse through your arr and replace null terminators with characters from replace array
int i=0;
for (int j = 0; j < 5; j++) {
if (arr[j]=='\0') { //replace when it equals to null terminator
arr[j] = replace[i++];
}
}
You want to ask the user to replace a specific number of chars, counting how many chars appear in subarr.
arr is input, subarr is from:
int replacecount[3] = { 0 };
for (int x=0; x<6; x++)
for (int i=0; i<3; i++)
if (input[x] == from[i]) {
++replacecount[i];
break;
}
int count = 0;
for (int i=0; i<3; i++)
if (replacecount[i] > 0)
++count;
std::cout << " you can replace " << count << " characters..." << std::endl;
char to[3];
for (int i=0; i<3; i++)
if (replacecount[i] > 0) {
std::cout << "enter replace character for '" << from[i] << "'" << std::endl;
std::cin >> to[i];
}
for (int x=0; x<6; x++)
for (int i=0; i<3; i++)
if (input[x] == from[i]) {
input[x] = to[i];
break;
}
std::cout << "replaced string is: " << input << std::endl;

C++ adding extra, unwanted characters to a string

I am having a bug that I cannot find a fix for through google searching. I am attempting to make a text based version of the game Mastermind. I am using a string the is set from an array of chars as the criteria for a while loop. When the string is equal to "****" the game is supposed to tell the player that they won and exit, but for some reason a ^A is being added on to the end of the string that is being checked, even though it is not in the char array.
Here is the function that sets the char array and returns a string from that array:
string check(int guess[4], int num[4]) {
char hints[4];
cout << " ";
for (int i = 0; i < 4; i++) {
if (guess[i] == num[i]) {
hints[i] = '*';
cout << "*";
}
else {
for (int x = 0; x < 4; x++) {
if (guess[i] == num[x]) {
cout << "+";
}
}
}
if (guess[i] != num[i]) {
hints[i] = ' ';
}
}
string hint(hints);
cout << endl;
cout << hint << endl;
return hint;
}
And here is the function checking the value of the string:
while (hints.compare("****") != 0) {
if (guessCount == 5) {
break;
}
cout << "Guess?: ";
cin >> guess;
intToArray(guess, guessArr);
hints = check(guessArr, nums);
cout << hints << endl;
guessCount++;
}
if (hints.compare("****") == 0) {
cout << "You win! The number was: ";
for (int i = 0; i < 4; i++) {
cout << nums[i];
}
}
You haven't null-terminated the hints array, so you are getting extra garbage that is lying around on the stack in your string.
You could let the hint string know how long it is when you are constructing it.
string hint(hints, 4);
cout << endl;
cout << hint << endl;

I keep getting subscript out of range don't know how to fix it [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
#include <iostream>
#include <fstream>
#include <string>
#include <ctime>
#include <cstdlib>
using namespace std;
const int MAX_NUMS = 200; // Constant for the maximum number of words.
const int MAX_GUESSES = 8;
const string LETTERS = "abcdefghijklmnopqrstuvwxyz";
char inputLetter();
int findChar(char letter, string&word);
string getGuessedWord(string&secretWord, string&lettersGuessed);
string getLettersGuessed(char letter, string&lettersGuessed, int n);
void display(string&lettersGuessed, string&wordGuessed, int num, int pos);
bool isDone(string wordGuessed);
int main()
{
string oneWord; // holds one word from input file
string secretWord; // holds secret word to be guessed
string words[MAX_NUMS]; // holds list of words from input file
int randomValue; // holds index of secret word
int count = 0; // holds number of words in the file
// Declare an ifstream object named myFile and open an input file
ifstream myFile;
myFile.open("P4Words.txt");
// Exit program if cannot open file for input
if (!myFile)
{
cout << "Error: Unable to open file for input" << endl;
return 0;
}
// Input words from a file into words array
// Add your code here ...
myFile >> oneWord;
while (!myFile.eof())
{
words[count] = oneWord;
count++;
myFile >> oneWord;
}
myFile.close();
cout << count << " words loaded." << endl;
srand(static_cast<unsigned int>(time(0)));
// Select a secret word
// Add your code here ...
secretWord = words[rand() % (count + 1) ];
// Possible useful variables the loop
string lettersGuessed = ""; // holds letters guessed so far
string wordGuessed; // holds current word guessed like �_ pp_ e�
int incorrectGuesses = 0; // holds number of incorrect guesses so far
char letter; // holds a guessed letter
bool done = false; // have not guessed the word yet
int num = 8; int pos;
cout << "Welcome to the game, Hangman V1 by Your Name!" << endl;
cout << "I am thinking of a word that is " << secretWord.length()
<< " letters long." << endl;
// Set up a loop to input guesses and process
// Add your code here ...
do
{
letter = inputLetter();
pos = findChar(letter, secretWord);
wordGuessed = letter;
lettersGuessed = getLettersGuessed(letter, lettersGuessed, 8 - num);
wordGuessed = getGuessedWord(secretWord, lettersGuessed);
display(lettersGuessed, wordGuessed, num, pos);
done = isDone(wordGuessed);
num--;
} while ((num > 1) && (done == false));
// Check for won or lost
// Add your code here ...
if (done == false)
{
cout << "sorry you lose..." << endl;
}
if (done == true)
{
cout << "congratulations! " << endl;
}
system("pause"); // stop program from closing, Windows OS only
return 0;
}
// Add function definitions here ...
char inputLetter()
{
int i;
char letter;
do
{
cout << "please guess a letter: " << endl;
cin >> letter;
for (i = 0; i < 25; i++)
{
if (letter == LETTERS[i])
{
return letter;
}
}
if (letter != LETTERS[i])
{
cout << "Oops! That is an invalid character." << endl;
}
} while (letter != LETTERS[i]);
}
int findChar(char letter, string &word)
{
int i = 0; int pos = 0; bool found = false;
do
{
if (word[pos] == letter)
{
return pos;
found = true;
}
pos++;
} while (pos<word.length() - 1);
if (found == false)
{
return -1;
}
}
string getGuessedWord(string&secretWord, string&letterGuessed)
{
string temp;
temp = secretWord;
for (size_t k = 0; k <= temp.length() - 1; k++)
{
temp[k] = '_';
}
for (size_t i = 0; i <= temp.length() - 1; i++)
{
for (size_t j = 0; j <= temp.length() - 1; j++)
{
if (letterGuessed[i] == secretWord[j])
{
temp[j] = letterGuessed[i];
}
}
}
return temp;
}
string getLettersGuessed(char letter, string&lettersGuessed, int n)
{
string temp;
temp = letter;
lettersGuessed.insert(n, temp);
return lettersGuessed;
}
void display(string&lettersGuessed, string&wordGuessed, int num, int pos)
{
if (pos != -1)
{
cout << "You have " << num << " guesses left." << endl;
cout << "Letters guessed so far: " << lettersGuessed << endl;
cout << "Good guess!: " << wordGuessed << endl;
cout << "-----------------------------------------------------" << endl;
}
if (pos == -1)
{
cout << "You have " << num << " guesses left." << endl;
cout << "Letters guessed so far: " << lettersGuessed << endl;
cout << "Oops! that letter is not my word: " << wordGuessed << endl;
cout << "-----------------------------------------------------" << endl;
}
}
bool isDone(string wordGuessed)
{
bool done = false; int k = 0;
for (size_t i = 0; i <= wordGuessed.length() - 1; i++)
{
if (wordGuessed[i] == '_')
{
k++;
}
}
if (k == 0)
{
done = true;
}
return done;
}
it says subscript is out of range I need help to fix it
let me know how to fix it please its a project that is due very soon
that's all I got so far
Change:
for (size_t i = 0; i <= temp.length() - 1; i++)
to:
for (size_t i = 0; i <= letterGuessed.length() - 1; i++)