Hangman Program Problem

Most of my hangman program works fine, except for when I get to the //Guessing Letters Section at the bottom. The only letter from the word it accepts for is the first letter, and I'm not sure why?

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cstdarg>
#include <cstdlib>
#include <ctime>
#include <algorithm>
using namespace std;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//HANGMAN PROGRAM 

int main(int argc, char* argv[])
   {
        int i, j, k, words, random_number;
        char ch;


        //ERROR CHECKS
        ifstream file;                        //input a file
        if ( argc < 2 )                       //what if a file isn't specified?
        {
            cerr << argv[0] << ": No filename specified" << endl;
            return 1;
        }
        file.open( argv[1], ios::in );
        if ( ! file )                         //what if the file doesn't exist?
        {
            cerr << argv[0] << ": Error on opening file " << argv[1] << endl;
            return 2;
        }


        //DATA FILE IN TO WORDS
        short word_count = 0;
        bool in_word = false;
        char word[11];                        //words no longer than 10 characters 
        int element = 0;
        string str[30], str1, str3;           //storing, assume file of 30 words
        while ( (ch = file.get() ) != EOF )
        {
            if( ch != '\n' && ch != ' ' )   
            {
                word[element] = ch;           //if character not a space or end of 
                element++;                    //line, then its within a word 
                if( ! in_word )
                {
                    in_word = true;
                }
            }
            else
            {
                in_word = false; 
                word[element] = '\0';         //if character a space of end of
                str[word_count] = string( word ) ;   //line, it terminates word
                word_count++;                 //and adds to word count       
                element = 0;                  //reset element to 0 for next word
            }
        }


        //RANDOM WORD GENERATOR, ASTERISKS 
        srand((unsigned) time(NULL));
        for ( words = 0; words == 0; words++ )
        {
            random_number = ( rand() % word_count + 1 );
        }
        str1 = str[random_number];            //denote random word as str1 
        cout << str1 << endl;                 //output word and length of word      
        cout << str1.length() << endl;
        str3 = str1;
        for( i = 0; i < str1.length(); i++ )
        {
		    str3[i] = '*';
		    cout << str3[i] ;
        }
        cout << endl;
    

        //CREATE ARRAY OF SAME LENGTH, ASTERISKS
        char phrase[str1.length() + 1] ;
        char *pointer ; 
        pointer = &phrase[0] ;                  //pointer goes to first character
        for(j = 0; j < str1.length(); j++ )
        {
            *pointer = str1[j] ;
            ++pointer;
        }


        //MAX GUESSES 
        int guesses;
        int max_guesses = 10; 
        cout << str1 << endl;
        
        
        //GUESSING LETTERS
        char str2;
        for (guesses = 0; guesses < max_guesses;  )
        {
            cout << "Guess a letter: ";
            cin >> str2;
            for ( k = 0; k <= str1.length(); k++)
            {
                if( ( str2 == str1[k] ) == 1 )
                {
                    str3.replace( k, 1, 1, str2 );
                    cout << str3 << endl;
                    cout << "Correct" << endl;
                    break;
                }
                else
                {
                    guesses = guesses + 1;
                    cout << "Used guesses: " << guesses << endl;
                    cout << "Guesses left: " << max_guesses - guesses << endl;
                    break;
                }
            }
            if( str1 == str3 )
            {
                cout << "WELL DONE" << endl;
            }
            if( max_guesses - guesses == 0 )
            {
                cout << "*************************\n";
                cout << "*           |           *\n";
                cout << "*           |           *\n";
                cout << "*           O           *\n";
                cout << "*          /|\\          *\n";
                cout << "*          / \\          *\n";
                cout << "*       HARD LUCK       *\n";
                cout << "*************************\n";
            }
            
        }
        return 0;
   };
Last edited on
Read this to learn about code tags -> https://www.cplusplus.com/articles/jEywvCM9/
Edit your post to include code tags.
TVM.
Thank you! Looks much better now, any ideas for my query?
First I would check if you can read the input correctly. Use some print statements to output all the names you read.
What does the file look ?
I also would get rid of all the old C char arrays and pointers and use only modern C++.
Yes I've got a file 'text.dat' which has got random words in it, separated by spaces or returns. When I run the code it outputs the random word(str1) and its length as asterisks(str3) just so I know which word I'm working with and what to guess. When I guess the first letter of the word it returns 'correct' along with the asterisks, but with the correct first letter instead of asterisks. When I guess any other letter in the word it thinks its incorrect, adds one to the number of guesses and outputs number of guesses/guesses left.
Line 107

You always break out of the loop after checking one letter, whether you guess right or not.

You want to examine all letters, and record how many correct guesses there were.

Having meaningless variable names called str,str1,str2,str3 leads to all kinds of 'blindness' about what is going on. Stop looking at the code for 10 minutes and you have to mentally re-establish in your head what each is for. Give them better names.

Also, you have a single function over 150 lines long.
Break the code up with some functions; add your own parameters and return results.
1
2
3
4
5
6
7
8
int main ( ) {
    //DATA FILE IN TO WORDS
    readDataFile();
    //RANDOM WORD GENERATOR, ASTERISKS
    pickRandomWord();
    //GUESSING LETTERS
    playGame();
}

Sorry I might seem stupid, how would you check all letters instead of one? I've changed the 'break out'.
I believe the problem to be in here:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
for (guesses = 0; guesses < max_guesses;  )
        {
            cout << "Guess a letter: ";
            cin >> str2;
            for ( k = 0; k <= str1.length(); k++ )
            {
                if( str2 == str1[k] )
                {
                    str3.replace( k, 1, 1, str2 );
                    cout << str3 << endl;
                    cout << "Correct" << endl;
                    break;
                }
                else
                {
                    guesses = guesses + miss;
                    cout << "Used guesses: " << guesses << endl;
                    cout << "Guesses left: " << max_guesses - guesses << endl;
                }


Sorry I am now in the process of changing str1, str2, str3. Currently str1 is the word, str2 is the letter guess, str3 is the asterisks
Topic archived. No new replies allowed.