Selecting random words for Hangman?

I have textfile in which random words are written line by line (no whitespace) I don't know the size of the file or how many words are in it. my task is to add a command line argument so a user can specify the name of a text file to use:

/test hangman.txt

if the user doesn't add a command line argument, the program goes to a default mode and allows the user to input his own word.

I'm currently done with the main hangman program:

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
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <stdlib.h>
using namespace std;

int main(int argc, char **argv)
{

	string word, word2, masked, guess, guessmem;
	int i, miss = 6, miss2;
	cout <<"Please enter a word" << endl;
	cin >> word;
	masked = word;

	//Assigns dashes to each letter
	for (i = 0; i < masked.length(); i++)
	{
		masked[i] = '-';
		cout << masked[i];
	}
	cout << endl << "misses left: " << miss << endl;
	
	//First loop, tracks misses
	for (miss = 6; miss > 0; miss--)
	{
		cout <<"Enter a letter: ";
		cin >> guess;
		cout << endl;
		miss2 = miss;	
		//loop to check if we've already entered this letter before
		for (i = 0; i < 26; i++)
		{
			if ((guessmem[i] == guess[0]) == 1)
			{
				cout << guess << " has already been entered";
				miss++;
			}
			else;
			guessmem[i] = guess[0];
			cout << endl;
			break;
		}	


		//loop to "fill in" dashes in masked word
		for (i = 0; i < masked.length(); i++)
		{
			if ((guess[0] == word[i]) == 1)
				{
				masked[i] = guess[0];
				if (miss2 == miss)
				miss++;
				else;
				}
			else;
		}
		
		guessmem += guess;

		//Checks if the entire word has been entered - breaks out of loop if so
		if ((word == masked) == 1)
			break;
		else;
		cout << masked << endl;		
		cout <<"Misses left: " << (miss-1) << endl;
	}

	if (miss > 0)
	cout <<"Congratulations! " << word << " is the word! "<< endl;
	else 
	cout <<"You lose. " << word << " is the word." << endl;
}


but I'm having trouble with two things - randomly selecting a number that's appropriate to the size of the text file, and inputting a random word from that said file.

I'm thinking of something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if (argc == 2)
{
	string word, word2;
	int i;
	ifstream ifs;

	ifs.open(argv[i], ios::in);
	if (ifs.fail())
	{
		cerr << argv[0] << ": " << argv[i] << " No such file or directory" << endl;
	}
	else while(!ifs.eof())
	{	
		file >> max;
		srand (time(NULL));
		r = rand() % 
		for (i = 0; i<r ; i++) getline(ifs, word)
	}


But I'm getting errors left and right - would any better ways be available?
Allowed to use vectors?
1
2
3
4
5
6
7
8
9
10
11
12
13
// Non-Vector Version:
int wordcount = 0;
while ( !ifs.eof() )
{
  ifs >> word;
  // Add word to whatever
  ++wordcount;
}

// OR do you mean to get the length of the file?
ifs.seekg(0, ios::end);
const int lengthOfFile = ifs.tellg();
ifs.seekg(0, ios::beg);
We haven't learned about them yet, so not really.

Edited it to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (argc == 2) //if user specifies command line parameter
{
	ifstream ifs;
	ifs.open(argv[1], ios::in);
	if (ifs.fail())
	{
		cerr << argv[0] << ": " << argv[i] << " No such file or directory" << endl;
	}
	else while(ifs >> word2)
	{	
		if (rand()< RAND_MAX/2)
		word = word2;
	}
}
cout << word << endl;


However, I'm thinking there's something wrong with the random number generator - I'm always getting the last word from the text file I'm using
Try this?
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
if (argc == 2) //if user specifies command line parameter
{
  ifstream ifs;
  ifs.open(argv[1], ios::in);
  if (ifs.fail())
  {
    cerr << argv[0] << ": " << argv[i] << " No such file or directory" << endl;
  }
  else
  {
    // Get file length
    ifs.seekg(0, ios::end);
    const int lengthOfFile = ifs.tellg();
    ifs.seekg(0, ios::beg);


    int counter = 0;
    int wordoftheDay = rand() % lengthOfFile;
    while( !ifs.eof() )
    {
      ifs >> word2;
      ++counter;
      if ( counter == wordoftheDay)
        word = word2;
    }
  }
}

cout << word << endl;
Last edited on
int the second listing your missing the seed for the random. but its hard to tell since you modified your code and not posting the whole thing. also srand seed should only be initialized once.
Thanks for your reply, wolfgang
This is my code so far:

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
129
130
131
132
133
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <stdlib.h>
using namespace std;

//* Part 1 and 2 work perfectly fine (to view those, remove the first 2 "if" clauses and main: goto functions. I am having issues with part 3 *//

int main(int argc, char **argv)
{
	string word, word2, masked, guess, guessmem;
	int i, miss = 6, miss2;
	srand (time(NULL));

if (argc == 1) //if user does not specify command line parameter
{
	ifstream ifs;
	ifs.open("hangmanwords.txt", ios::in);
	if (ifs.fail())
	{
		cerr << argv[0] << ": " << argv[i] << " No such file or directory" << endl;
	}
	else
	{
		// Get length of file
		ifs.seekg(0, ios::end);
		const int length = ifs.tellg();
		ifs.seekg(0, ios::beg);

		int counter = 0;
		int word3 = rand() % length;
		while( !ifs.eof() )
		{
			ifs >> word2;
			++counter;
			if (counter == word3)
		  		word = word2;
		}
  	}
}

if (argc == 2) //if user specifies command line parameter
{
	ifstream ifs;
	ifs.open(argv[1], ios::in);
	if (ifs.fail())
	{
		cerr << argv[0] << ": " << argv[i] << " No such file or directory" << endl;
	}
	else
	{
		// Get length of file
		ifs.seekg(0, ios::end);
		const int length = ifs.tellg();
		ifs.seekg(0, ios::beg);

		int counter = 0;
		int word3 = rand() % length;
		while( !ifs.eof() )
		{
			ifs >> word2;
			++counter;
			if (counter == word3)
		  		word = word2;
		}
  	}
}
cout << word << endl;

	//cout <<"Please enter a word" << endl; (for manual input of word
	//cin >> word;

	masked = word;
	
	//Assigns dashes to each letter
	for (i = 0; i < masked.length(); i++)
	{
		masked[i] = '-';
		cout << masked[i];
	}
	cout << endl << "misses left: " << miss << endl;
	
	//First loop, tracks misses
	for (miss = 6; miss > 0; miss--)
	{
		cout <<"Enter a letter: ";
		cin >> guess;
		cout << endl;
		miss2 = miss;	
		//loop to check if we've already entered this letter before
		for (i = 0; i < 26; i++)
		{
			if ((guessmem[i] == guess[0]) == 1)
			{
				cout << guess << " has already been entered";
				miss++;
			}
			else;
			guessmem[i] = guess[0];
			cout << endl;
			break;
		}	


		//loop to "fill in" dashes in masked word
		for (i = 0; i < masked.length(); i++)
		{
			if ((guess[0] == word[i]) == 1)
				{
				masked[i] = guess[0];
				if (miss2 == miss)
				miss++;
				else;
				}
			else;
		}
		
		guessmem += guess;

		//Checks if the entire word has been entered - breaks out of loop if so
		if ((word == masked) == 1)
			break;
		else;
		cout << masked << endl;		
		cout <<"Misses left: " << (miss-1) << endl;
	}

	if (miss > 0)
	cout <<"Congratulations! " << word << " is the word! "<< endl;
	else 
	cout <<"You lose. " << word << " is the word." << endl;
}


It's working, with the exception of the random number generator - it only seems to 'pick' up on the words in the text file once every so often. about 80% of the time its not picking up words and the other 20% of the time is correctly does so.

For example, there should be a text file in the same folder called hangmanwords.txt, which spells out:

duck
goose
chicken
piano
hangman

etc. etc. of unspecified length.
Last edited on
This is what I'm getting in my output:

mosley@gacrux:~/main$ ./hw3_ex4


misses left: 6
Enter a letter: ^C
mosley@gacrux:~/main$ ./hw3_ex4


misses left: 6
Enter a letter: ^C
mosley@gacrux:~/main$ ./hw3_ex4
library
-------
misses left: 6
Enter a letter: ^C
mosley@gacrux:~/main$./hw3_ex4


misses left: 6
Enter a letter:

As you can see, the program only found a word once out of four tries
Last edited on
I think the issue is that tellg uses character position - in which case the length is measuring the total number of characters as opposed to the total number of lines in the text file. Does anyone know of a way to measure the number of lines in the text file as opposed to the number of characters?
You could read the entire file once with getline(), then seekg to the top again.
1
2
3
4
5
6
7
8
int length = 0;
while ( !ifs.eof() )
{
   getline( ifs, temp );
   length++;
}

ifs.seekg(0, ios::beg);
What should I be putting in for temp? I'm getting invalid conversion errors from 'void*' to 'char**' if I try to put in a number
It's the getline from the string header. temp was meant to be a std::string.
Topic archived. No new replies allowed.