Reading random string from file

Hi. I have to do the "hangman game" as homework.
The "hangman word" needs to be read from a file. It needs to be a random word from that file. How do i do that?
Ive come this far:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main()
{
    FILE *pFil;
  char word[MAX_WORD_LEN];	/* Word to guess (from file) */
  char mask[MAX_WORD_LEN];	/* Masked word (shown on screen) */
  int ch;			/* User selection */
  int count;			/* Number of guesses */
  int result;			/* Winner */
  int len;


  srand( time(0) );
 
 pFil = fopen("hangman.txt", "r");
 
    while(!feof(pFil))
 {  
     fscanf(pFil, "%s", )
     
 }
Read all the words into an array and then pick one. There is hardly another way. If you know how many words there are in a file, you could pick a (smaller) number and count the words from the file until you find the one you picked. You still have to read the file in order though.
Can i store multiple strings in an array? Or do i have to use a 2 dimensional array?

And when i finish storing my strings in the array, how to i printf a random string from that array?
Yes, a 2d array. Or a vector of strings, if you're using C++ (though it looks like C). If the array is char words[a_lot][MAX_WORD_LEN]; then you get a random word by doing strcpy(word, words[rand()%number_of_words]);.
Ok here is my whole code. Do u see any faults? (Assume that i do not have to choose a random string from file.). Its not working.


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
#include <stdio.h>
#include <cstdlib>
//#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
//#include<stdbool.h>
#include<string.h>
#include<time.h>

#define MAX_WORD_LEN 20

const int MAX_GUESS = 6;
const char ABORT_CH = '0';
const int LOOSE = 0;
const int WIN = 1;
const int ABORTED = 2;

char get_user_input(char *str);
void draw_hangman(char *str, int count);
int win_loose(char str);
void clear_stdin();


int main()
{
    FILE *pFil;
  char word[MAX_WORD_LEN];	/* Word to guess (from file) */
  char mask[MAX_WORD_LEN];	/* Masked word (shown on screen) */
  char hangman[7]={0};
  int ch;			/* User selection */
  int count;			/* Number of guesses */
  int result;			/* Winner */
  int len, i=0;



 pFil = fopen("hangman.txt", "r");

     fscanf(pFil, "%s", word);



  while( true ){

    printf( "Welcome HANG MAN 2011\n");
    printf( "You have %d guesses (cancel with 0)\n", MAX_GUESS );

    printf( "Computer chose a word of %d letters\n", len );
  
   len=strlen (word);
        for(i=0; i<len; i++)
        {mask[i]='_';}

    while( true ){
        printf("%s", mask);
        printf("\nGuess a letter (a-z): ");

        scanf("%c", &ch);
        count++;
    for(i=0; i<len; i++)
        if(mask[i]==ch)
            {mask[i]=ch;
            printf("%s", mask);}
        else   {draw_hangman(hangman, count);
            printf("%s", hangman); }

    if((count==6) && (hangman[6]==NULL))
        result = LOOSE;

    else if(strcmp(word, mask)==0)
        result = WIN;
}

    if( result == WIN ){
      printf("Congrats, you won!\n");
    }else if( result == LOOSE ){
      printf("Youve lost, the word was: %s\n", word);
    }else{
      printf("Cancelled\n");
    }

    ch = get_user_input("Play again (j/n)?): ");
    if( ch == 'n' || ch == 'N' )
      break;
}

  return 0;
}




void draw_hangman(char *hangman,int count){
 hangman++;

    if(count==1)
       {hangman="_______\n";}
    if (count==2);
        {hangman="|\n";}
    if (count==3);
        {hangman="0\n";}
    if (count==4);
        {hangman="// | \\\n";}
    if (count==5);
        {hangman="|\n";}
    if (count==6);
        {hangman="// \\\n";}

}


char get_user_input(char *str){
	char tkn= '0';

	return tkn;
}

Note that the last function (draw hangman) draws the head when count is one, and the neck when count is two, etc, using a pointer.
How exactly is it not working?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void draw_hangman(char *hangman,int count){
 hangman++;

    if(count==1)
       {hangman="_______\n";}
    if (count==2);
        {hangman="|\n";}
    if (count==3);
        {hangman="0\n";}
    if (count==4);
        {hangman="// | \\\n";}
    if (count==5);
        {hangman="|\n";}
    if (count==6);
        {hangman="// \\\n";}

}


Note that hangman is a local variable. Any changes to that variable will not be discernable outside of the function. Why does your function not do what it says it does?

From the name I would expect something more like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void draw_hangman( int count )
{
    static char const* figure[] =
    {
        "    ___\n",
        "    |\n",
        "    0\n",
        "  / | \\\n",
        "    |\n",
        "   / \\\n"
    };

    if ( count > sizeof(figure) / sizeof(figure[0]) )
        count = sizeof(figure) / sizeof(figure[0]) ;

    for ( unsigned i=0; i < count; ++i )
        std::cout << figure[i] ;
}
Ok. The first problem is it does not read the txt file. I put it in the same catalog as the cpp file. But it still does not read it. I receive an error.

cire: hangman is a local variable yes, but it is a pointer. My idea is to make the pointer point to the hangman array, depending on how many guesses (count) the user has made. The pointer hangman, is pointing at an array called hangman[]. So my idea is to make pointer point at hangmand[count].
Isee that ive made an error there by increasing hangman++, since its a local variable. But what about the rest. I thought that u can change the memory pointed to by pointer by using hangman="..".

Would u be able to use C code when writing code? I do not understand c++. Thank u guys for ur time.
cire: hangman is a local variable yes, but it is a pointer.

pointers are no different from other variables.


My idea is to make the pointer point to the hangman array, depending on how many guesses (count) the user has made.

Then you must either pass the address of the pointer you want to change, or, in C++, pass a reference to the pointer.


I thought that u can change the memory pointed to by pointer by using hangman="..".

You can change the memory pointed to by a pointer by doing *hangman = or hangman[index] =. But doing hangman = modifies the pointer itself.


Would u be able to use C code when writing code? I do not understand c++.

You do realize this is a C++ site, yes?

Replace line 17 in the code above with printf( "%s", figure[i]); and you've got a purely C version.
Ok.
Yes I realize that, but i hope i can just get help with this last homework i have, if thats ok.

right now im having a problem with the compile printing too many times.
First, it prints Guess(a-z): _______ And then when i guess, everything works fine, except the next time it prints Guess(a-z): _______ It prints it twice before i have the chance to guess.
So the compiler will show:
Guess(a-z): _______ h (h is my guess)
Guess(a-z): h______ Guess(a-z): h______:

Any idea why?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
while(true){
 printf("Guess (a-z):%s ", mask);
 scanf("%c", &g);
 count++;


 for(i=0; i<len; i++){
    if(word[i]==g)
        {mask[i]=g;
            p=1;}
    else continue;}

while(p!=1)
    {f++;
    draw_hangman(fel);}

}



Another problem i have is that the hangman figure prints like this:
1
2
3
4
5
    |
    0
  / | 
    |
   / 


One arm and one leg missing. If I add an extra arm to both sides, then it will print 2 arms on one side, and one arm on the other side, etc.
Last edited on
right now im having a problem with the compile printing too many times.
1
2
 printf("Guess (a-z):%s ", mask);
 scanf("%c", &g);


On your initial guess you enter a letter and a newline. You enter "a\n" for instance. the scanf extracts the 'a' from the input stream, but leaves the '\n' in. The next iteration of the loop the scanf extracts the newline from the previous input operation.

There are a couple ways around this. The simplest is probably to usescanf(" %c", &g);, which skips all leading whitespace when reading.

Another problem i have is that the hangman figure prints like this:

Just change the name to hanggimp, and you're good to go!

If you use the strings I used in the code above to print your hangman slices, this wouldn't be an issue.

But, why is it an issue? The backslash character is a known as the "escape" character when it comes to string and character literals in C++. We use it to denote other special characters in those literals (e.g. '\n' is a newline character, '\'' is used to denote the single quote character.) So, just like we "escape" the newline character we must also "escape" the backslash character if we want to use it in a literal. There is nothing special about the forward slash, so it doesn't need to be escaped.

So: "/ | \\" translates to / | \

Ok. Im almost done. I have a few more things left.
I want the user to be able to cancel the game whenever he wants by pressing "0". How do i do that?





Then, the teacher wrote the code

1
2
3
ch = get_user_input("Play again (j/n)?): ");
    if( ch == 'n' || ch == 'N' )
      break;


This code is linked to this function:
1
2
3
4
char get_user_input(char *str){
	char tkn= '0';

	return tkn;

}

It seems he wants me to ask player if he wants to play again, by using a function with a pointer as u see. How do i go about doing that? The code does not run like this. Right now the game does not ask user if he wants to play again. It just restarts without asking. So a few things must be missing.

The thing i really do not understand is why does he write a question in the function parameter? Is it supposed to ask already and get a user input? And why does he assign a "0" to tkn?
Last edited on
get_user_input() could be like this:

1
2
3
4
5
6
7
char get_user_input(char *str){
	char tkn= '0';
        
        printf ("%s\n", str);   /* ask the user if it wants to play again */
        tkn = getchar();    /*  read user choice */
	return tkn;
}
Last edited on
Thanks. Now i think i only have 3 problems left, i think.
Sometimes the compiler ignores a bodypart, and sometimes it draws it. Although the game works fully without having to draw them all the time but i dont want my teacher picking on that small problem.
The same goes for when the game ends. I say that i wanna play again. Sometimes it restarts it but sometimes it doesnt. Weird.
Here is my code for drawing the hangman:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int draw_hangman(int wrong){
 char fig[14] ={"_______\n"};
 char fig2[10]={"   |\n"};
 char fig3[10]={"   0\n"};
 char fig4[11]={"// | \\\\ \n"};
 char fig5[10]={"   |\n"};
 char fig6[11]={" // \\\\ \n"};

if(wrong==1)
    {printf("%s",fig);
    return wrong;}
else if(wrong==2)
    {printf("%s%s",fig,fig2);return wrong;}
else if(wrong==3)
    {printf("%s%s%s",fig,fig2,fig3);return wrong;}
else if(wrong==4)
    {printf("%s%s%s%s",fig,fig2,fig3,fig4);return wrong;}
else if(wrong==5)
    {printf("%s%s%s%s%s",fig,fig2,fig3,fig4,fig5);return wrong;}
else if(wrong==6)
    {printf("%s%s%s%s%s%s",fig,fig2,fig3,fig4,fig5,fig6);return wrong;}
}



And one more thing. When i say that i dont wanna play anymore, the game ends but the console is still open for me to input characters. Why? I break out of that loop and come to return 0;, but still.
Last edited on
Topic archived. No new replies allowed.