Thread: Could Someone Please Explain This Code

  1. #1
    Registered User
    Join Date
    Apr 2004
    Posts
    9

    Could Someone Please Explain This Code

    Hi I got a code that I would like someone to explain to me. Its a code for a word guessing game. If possible could you please point out the technical bits behind the code and also comment it out in the code itself. Many thanks. Here is the code:

    Code:
    #include <stdio.h>
    #include <ctype.h>
    #include <string.h>
    #include <conio.h>
    #include <time.h>
    #include <stdlib.h>
    
    int  func (void);
    void wrong (void);
    void hello (void);
    
    #define MAX_WORDS    1024
    
    struct _WORDS
    {
      char* m_Array [MAX_WORDS];	// Every entry is a pointer to string
      int	m_iCount;		// How many filled in 'm_Array'
    };
    typedef struct _WORDS WORDS;
    
    void
    CreateWords (WORDS* pWords, char* pstrFileName)
    {
    	FILE*	pFile;
    	char	strLine [32];	// Assume words are no longer than 31 chars
    	int	iLastCharPos;
    
    	pFile = fopen (pstrFileName, "rt");
    	if (!pFile) {
    		fprintf (stderr, " Error: Couldn't open file `%s'!\n", pstrFileName);
    	}
    	else {
    		pWords->m_iCount = 0;
    		while (fgets (strLine, 31, pFile)) {
    			// Remove '\n', at the end, if any:
    			iLastCharPos = strlen (strLine) - 1;
    			if (strLine [iLastCharPos] == '\n')
    				strLine [iLastCharPos] = '\0';
    
    			pWords->m_Array [pWords->m_iCount] = strdup (strLine);
    			(pWords->m_iCount)++;
    			if (pWords->m_iCount == MAX_WORDS)
    				break;		// Array is full
    		}
    		fclose (pFile);
    	}
    }
    
    char*
    GetRandomWord (WORDS* pWords)
    {
    	return pWords->m_Array [rand () % pWords->m_iCount];
    }
    
    void
    DestroyWords (WORDS* pWords)
    {
    	int i;
    	for (i=0; i < pWords->m_iCount; i++)
    		free (pWords->m_Array [i]);
    }
    
    int
    main (int argc, char *argv[])
    {
    	/*
    	char words[10][10] = {"mythology", "astrology", "interface",
    			      "programme", "schedules", "faithless",
    			      "sandstorm", "bulgarian", "boulevard", "salvation"};*/
    	char	*temp;
    	WORDS	words;
    
        	int	count;
    	int	random;
    	int	flag;
    
        	char	*current;
    	char	*inserted;	// That's where the already inserted letters are
    				// stored
    	char	*solution;	// Give user a whole try -> premature end
        	char	ch;
        	int	i, t, q;	// Why don't reduce them to one?
    	char	finished;
    
        	// count = 50;		// Hell, how many letters do we have? Around 26 ...!?
    	count = 10;		// It would be more logic, if we put down tries to 10
    				// Better: 7/8
    	finished = 0;
        	flag = 2;
    
    	temp     = (char*) malloc (sizeof (char) * 32);
    	current  = (char*) malloc (sizeof (char) * 32);
    	inserted = (char*) malloc (sizeof (char) * count);
    	solution = (char*) malloc (sizeof (char) * 32);
    
    
    	CreateWords (&words, "words.dat");
    
    	srand (time (0));
    	
    	while (!finished) {
    		current = GetRandomWord (&words);
    		memset (temp, '_', strlen (current));
    		temp[strlen (current)] = '\0';
    		memset (inserted, 0, 32);
    		memset (solution, 0, 32);
    
    		/*
            	random = func();
    
    		for (q=0; q<strlen (words[random]); q++)
    			current[q] = words[random][q];
    		*/
    
    		while (1)
    		{
    		loop_begin:
    			clrscr ();
    			printf ("\n               --- Hangman ---\n");
    			printf ("                                  Tries left: %d\n\n", count);
    			printf (" Word: %s \n"
    				"                                  Wrong Guessed:\n"
    				"                                  --------------\n"
    				"                                  %c %c %c %c %c\n"
    				"                                  %c %c %c %c %c\n",
    				temp, inserted[0], inserted[1], inserted[2], inserted[3],
    				inserted[4], inserted[5], inserted[6], inserted[7],
    				inserted[8], inserted[9], inserted[9]); 
    			if (strcmp (temp, current) == 0) {
    				printf("\nYou did it. \nPress any key to continue ...");
    				break;
    			}
    			ch = tolower (getch ());
    			
    			if (ch == '?')
    				goto end;
    			else if (ch == '!') {
    				printf ("\n Solution: ");
    				scanf ("%s", solution);
    
    				if (strcmp (solution, current) == 0)
    					printf (" That's right!\n");
    				else {
    					printf (" That's wrong!\n");
    					printf (" Right answer was: %s\n", current);
    				}
    
    				break;
    			}
    			if (!isalpha (ch))
    				goto loop_begin;
    
    			/ if already inserted, skip the following
    			for (t=0; t<strlen (inserted); t++)
    				if (ch == inserted[t])
    					goto loop_begin;
    
    			flag = 0;
    			for (t=0; t<strlen (current); t++)
    				if (ch == tolower (current[t])) {
    					temp[t] = current[t];
    					flag = 2;
    				}
    
    			if (flag < 2) {
    				count--;
    				inserted[strlen (inserted)] = ch;
    			}
    
    			if (count <= 1) {
    				wrong ();
    				return 0;
    			}
    		}
    
    		ch = getche();
    	}
    
    end:
    	free (temp);
    	free (current);
    	free (inserted);
    	free (solution);
    	DestroyWords (&words);
    
    	return 0;
    }
    
    int
    func (void)
    {
    	return (int) rand() % 10;
    }
    
    void
    wrong (void)
    {
    	printf ("\n\nSorry, But You Have Run Out Of Your Tries. Please Retry The Program");
    }

  2. #2
    Software Developer jverkoey's Avatar
    Join Date
    Feb 2003
    Location
    New York
    Posts
    1,905
    just so you know in advance, most people here are occupied with other things, commenting someone else's code isn't exactly something people here like to do

    I'd suggest first trying to understand as much of the code as you can, and then ask specific questions about the parts you don't understand. If you don't understand any of it, go through the tutorials here again

    -just some advice, please don't take it the wrong way, we'd be more than happy to help you out, just not by commenting your code for you

  3. #3
    Registered User
    Join Date
    Apr 2004
    Posts
    9
    I bet all of your replies are negative, you seem to be one of those people the cant do much but talk alot. I wrote the code and now need to know the names of the technical bits I have used without noticing. So If you are not skilled enough to understand my code, dont bother opening your mouth

    Quote Originally Posted by jverkoey
    just so you know in advance, most people here are occupied with other things, commenting someone else's code isn't exactly something people here like to do

    I'd suggest first trying to understand as much of the code as you can, and then ask specific questions about the parts you don't understand. If you don't understand any of it, go through the tutorials here again

    -just some advice, please don't take it the wrong way, we'd be more than happy to help you out, just not by commenting your code for you

  4. #4
    Registered User linuxdude's Avatar
    Join Date
    Mar 2003
    Location
    Louisiana
    Posts
    926
    I don't see anything challenging on it. But you did typecast your malloc. you shouldn't do that. But jverkoey is right. Tell us what you don't understand. He does understand it all. He wrote his own language; I think that is good enough
    [EDIT]One of your comments is wrong.
    Code:
    char	strLine [32];	// Assume words are no longer than 31 chars
    The array can hold 32 to characters not 31[/EDIT]
    Last edited by linuxdude; 05-26-2004 at 06:04 PM.

  5. #5
    Software Developer jverkoey's Avatar
    Join Date
    Feb 2003
    Location
    New York
    Posts
    1,905
    *sigh*

    I honestly don't post negative posts that often, and didn't intend for this to be a negative post, it's just a lot of work to comment someone elses code for them

    I was working on my new win32 website, but now you've gone and made me feel bad

    Well, if you insist, here goes, just so you know i'm not evil:

    Code:
     
    // INCLUDES
    // Standard includes that we'll most likely need for the code
    #include <stdio.h>
    #include <ctype.h>
    #include <string.h>
    #include <conio.h>
    #include <time.h>
    #include <stdlib.h>
     
    // PROTOTYPES
    // Odd function names, but they work
    //int func (void); // This function is never used....
    void wrong (void);
    //void hello (void); // Neither is this one
     
    // DEFINES
    // Max number of words that we can read in.
    #define MAX_WORDS 1024
    // The following define was added so we can globally change the max
    // word size in case it happens to be too small.
    #define MAX_WORD_SIZE 32
     
    // STRUCTURES
    struct _WORDS
    {
    char* m_Array [MAX_WORDS];	// Every entry is a pointer to string
    int	m_iCount;		// How many filled in 'm_Array'
    };
    typedef struct _WORDS WORDS;
     
    // FUNCTIONS
    //
    // CreateWords
    // Takes in two parameters, a pointer to the WORDS structure we want to modify
    // and the filename to open. Opens the file and scans it for all of the words
    // inside of it, adding them to the pWords list that was passed in
    void CreateWords (WORDS* pWords, char* pstrFileName)
    {
    	if(!pWords || !pstrFileName) return;	// Error checking
    
    	FILE*	pFile;
    	char	strLine[MAX_WORD_SIZE];	// Assume words are no longer than 31 chars
    	int	iLastCharPos;
     
    	pFile = fopen (pstrFileName, "rt"); // Open up our file for reading text
    	if (!pFile) {
    		fprintf (stderr, " Error: Couldn't open file `%s'!\n", pstrFileName);
    	}
    	else {
    		pWords->m_iCount = 0;		 // Reset the word count
    
    // Read through the file one word at a time
    		while (fgets (strLine, MAX_WORD_SIZE-1, pFile)) {
    			// Remove '\n', at the end, if any:
    			iLastCharPos = strlen (strLine) - 1;
    			if (strLine [iLastCharPos] == '\n')
    			{
    				strLine [iLastCharPos] = '\0';
    				iLastCharPos--;	 // Update our new position in case we use it later
    			}
     
    // Make a copy of the string automatically (let strdup handle it for us) and point to it!
    			pWords->m_Array [pWords->m_iCount] = strdup (strLine);
    			(pWords->m_iCount)++;
    			if (pWords->m_iCount == MAX_WORDS)
    				break;		// Array is full
    		}
    // Make sure to close up the file so we don't have an open file hanging out in the program
    		fclose (pFile);
    	}
    }
     
    // GetRandomWord
    // Takes a WORDS pointer
    // Returns a random word from the list of words.
    char* GetRandomWord (WORDS* pWords)
    {
    	if(!pWords) return 0;	// Error checking just in case we don't pass a pointer
    	return pWords->m_Array[rand () % pWords->m_iCount];
    }
     
    // DestroyWords
    //	Takes a WORDS pointer
    //	Cleans up all of our dynamic memory we allocated when creating
    //	the words table
    void DestroyWords (WORDS* pWords)
    { 
    	if(!pWords) return 0;	// Error checking
    	int i;
    	for (i=0; i < pWords->m_iCount; i++)
    		free (pWords->m_Array );
    }
    
    
    [i]// main
    // Takes in the standard command-line parameters
    // Processes our program (of course)
    int main (int argc, char *argv[])
    {
    	char	temp[MAX_WORD_SIZE];
    	WORDS	words;	 // Create the words structure
     
    	const int	maxcount=10;
    	 int count=maxcount;
    	int	random;
    	int	flag;
     
    	char	current[MAX_WORD_SIZE];
    	char	inserted[maxcount*MAX_WORD_SIZE]; 
    	char	solution[MAX_WORD_SIZE];
     
    	char	ch;
    	int	i, t, q;	// Why don't reduce them to one?
    	char	finished;
     
    	finished = 0;
    //	flag = 2;		 // I don't see why this is needed, as it is initialized to 0 before
    								 // being tested at all
     
    // Not sure as to why this is needed.....it would be much better to just have
    // constant sizes for the ones that are constant
    /*
    	temp = (char*) malloc (sizeof (char) * MAX_WORD_SIZE);
    	current = (char*) malloc (sizeof (char) * MAX_WORD_SIZE);
    	solution = (char*) malloc (sizeof (char) * MAX_WORD_SIZE);
    	inserted = (char*) malloc (sizeof (char) * count);*/
     
    // Create our words list from the words.dat file which should hopefully be stored
    // in the same directory as this exe 
    	CreateWords (&words, "words.dat");
     
    // Seed the rand function so it's different every time
    	srand (time (0));
     
    // Our "game" loop starts here.
    	while (!finished) {
     
    // Grab a random word from the word list using our random word function
    		current = GetRandomWord (&words);
     
    // Clever way of filling in the temp array with lines for each letter
    // IE: if the word is CAT temp will be filled with _ _ _ or three underscores
    		memset (temp, '_', strlen (current));
    		temp[strlen (current)] = '\0';
     
    // Reset the inserted and solution strings
    		memset (inserted, 0, MAX_WORD_SIZE);
    		memset (solution, 0, MAX_WORD_SIZE);
     
    // Infinite loop unless we break
    		while (1)
    		{
    //		loop_begin:	// Sorry, but labels aren't the best way to go
    								 // I rarely use labels unless i'm desperate
     
    // Clear the screen of all text
    			clrscr ();
     
    // Output our "User Interface"
    			printf ("\n --- Hangman ---\n");
    
    // Don't forget to inform the user of the controls!
    			printf ("\n ? to quit ! to type in your guess \n");
    
    			printf (" Tries left: %d\n\n", count);
    			printf (" Word: %s \n", temp);
    			printf (" Wrong Guessed:\n");
    			printf (" --------------\n");
     
    // A little bit better way of outputting the letters we've guessed already
    			for(int a=0;a<10;a++)
    					printf(" %c",inserted[a]);
    			printf("\n");
     
    // Test if temp and current are equal...
    			if (strcmp (temp, current) == 0) {
    				printf("\nYou did it. \nPress any key to continue ...");
    				break;
    			}
     
    // Grab some user input...
    			ch = tolower (getch ());
     
    // Give up i'm guessing...
    			if (ch == '?')
    			{
    				finished=1;
    				break;
    			}
    			else if (ch == '!') {
    				printf ("\n Solution: ");
    // Prompt them to guess by typing it in all at once
    				scanf ("%s", solution);
     
    // Were they right?
    				if (strcmp (solution, current) == 0)
    					printf (" That's right!\n");
    				else {
    					printf (" That's wrong!\n");
    					printf (" Right answer was: %s\n", current);
    				}
     
    				break;
    			}
    			if (!isalpha (ch)) // If the user didn't enter a letter up to this point....
    				continue;		 // Jump to the beginning of the loop
     
    // Do NOT use strlen inside of a loop like this, it's very slow!
    			int insertedLength=strlen (inserted);
    			for (t=0; t<insertedLength; t++)
    				if (ch == inserted[t])
    					break;
    			 if(t!=insertedLength)	// We broke out prematurely...
    					 continue;				 // Skip to the beginning again
     
    // Reset the flag
    			flag = 0;
    			int lengthCurrent=strlen(current);
    			for (t=0; t<lengthCurrent; t++)
    				if (ch == tolower (current[t])) {
    					temp[t] = current[t];
    					flag = 2;
    				}
     
    // Test if the letter entered was a letter in the word to guess
    			if (flag==0) { // Changed from <2 because the only other value this can be is 0
    				count--;
    				int currLength=strlen(inserted);
    				inserted[currLength] = ch;
    				inserted[currLength+1]='\0'; // Don't forget to close it up just in case!
    // The method that was here before would work fine, but what would happen if
    // you wanted the user to be able to play multiple games?
    			}
     
    			if (count <= 1) {
    				wrong ();
    				return 0;
    			}
    		}
     
    		if(!finished)
    			ch = getche();
    	}
     
    // Don't need this anymore!
    /*
    	free (temp);
    	free (current);
    	free (inserted);
    	free (solution);*/
    // Clean up our word list
    	DestroyWords (&words);
     
    	return 0;
    }
    /*
    int func (void)
    {
    	return (int) rand() % 10;
    }
    */
    // Display that the user was wrong
    void wrong (void)
    {
    	printf ("\n\nSorry, But You Have Run Out Of Your Tries. Please Retry The Program");
    }
    *sheesh*

    now that i've spent about an hour going through YOUR code, i understand it INSIDE AND OUT

    YAY, I COMMENTED HANGMAN!!! *DANCES*

    anyways, this program is quite simple to be completely honest.

    Program Flow:

    Start off, initialize the word list from the .dat file and create our array of words
    Begin game loop
    -Display User Interface
    -Prompt user to guess
    -Did they want to quit/get the answer?
    --if so, do either one...
    -Otherwise, they must have guessed a letter
    --Is the letter in the word?
    ---Nope, add it to the list of wrong letters
    -end game loop, jump back up again....

    that's the basic gist of it

    So, yah, I wish I got payed to do this....lol

    I'm not that horrible of a person. It's just that, like I said, it's time consuming to do other people's commenting, when if they just sat down with the code for a while, they could figure it out. Now've you gone and made someone else go through YOUR code and you just seem to think that's normal.....well, i'm sorry if someone taught you that.

    So in the future, please just try and do a little of the work on your own, you're lucky i'm a nice guy

  6. #6
    C++ Developer XSquared's Avatar
    Join Date
    Jun 2002
    Location
    Ontario, Canada
    Posts
    2,718
    It's not a good way to start off your stay on these boards by flaming someone like jverkoey. He's been around for quite a while, and done quite a bit of advanced programming. He was just trying to explain to you that we won't do everything for you. We are not a substitute for your own brain. If you had said something along the lines of 'I understand these parts, but what does this part do...' we'd be more willing to help.
    Naturally I didn't feel inspired enough to read all the links for you, since I already slaved away for long hours under a blistering sun pressing the search button after typing four whole words! - Quzah

    You. Fetch me my copy of the Wall Street Journal. You two, fight to the death - Stewie

  7. #7
    Software Developer jverkoey's Avatar
    Join Date
    Feb 2003
    Location
    New York
    Posts
    1,905
    note, the code that is boldfaced and italisized is the code that i modified/added in some way, just so you know

    I added/fixed some parts of your program that were kinda.....weird, so i'm sorry if you don't like it

    *sigh*
    You're just the type of person that makes me cringe sometimes

    -edit-

    and please, don't EVER expect me to do this again, I just did it to prove a point.

    -edit 2-
    so now that i've lost an hour of work on my win32 website, i suppose i'd better try and catch up.....

    -edit 3-
    oh, and i'm sorry if my code doesn't work, i typed it all up in the reply window, so i have no idea if it will even compile, and frankly, i don't care. Have fun
    Last edited by jverkoey; 05-26-2004 at 06:29 PM.

  8. #8
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    *FLAME TIME!!!*

    I bet all of your replies are negative
    Nope. They're mostly positive and constructive, just like the one he posted. I don't think he could have phrased that nicer if he tried.
    you seem to be one of those people the cant do much but talk alot.
    He's a lot better than you are, judging from the questions/comments he's posted.
    I wrote the code and now need to know the names of the technical bits I have used without noticing.
    If you wrote it, chances are you can understand it. At least, you SHOULD be able to. Unless... *GASP* you copied it? No, you wouldn't do that...
    So If you are not skilled enough to understand my code
    He is, as has been proven quite extensively just a moment ago.
    dont bother opening your mouth
    He was helping you by pointing out a better way of getting help around here. You should appreciate that. Besides, the smiley faces should at least give you a clue that he's well meaning. Maybe you could take offense if they were angry faces or roll-eye faces, but they're not.

    And for the record, I'm not "one of those people the cant do much but talk alot" either - before you start that again. At least I can understand my own code.

    Over and out. *click*
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  9. #9
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Jverkoey, you shouldn't have commented the code for HelpMePlease. If you've seen any of HelpMePlease's posts, there's no way he could have written this code. Look how fancy it is, pointer's all over the place. I read one thread where he didn't even have a main() function. That's why he couldn't explain it.

    Newbies do not write code like that, and nonnewbies will understand it enough to comment it. Most of the time someone will ask what a certain line or lines of code do. But to post a whole program which you didn't write and ask to comment it is ridiculous.

  10. #10
    Software Developer jverkoey's Avatar
    Join Date
    Feb 2003
    Location
    New York
    Posts
    1,905
    i understand that, but he kinda ticked me off a bit (which is most likely what he intended).

    I realize i shouldn't have really posted it, but it's too late now and it's not really that big a deal, maybe he'll actually learn something from the code.

  11. #11
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Jverkoey I hope you are right, but this code is way too advanced for me, and although I'm no expert, I'm no beginner either.

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    It's quite obvious that that code was written by at least two people.
    And it seems likely that neither of them was HelpMePlease

    > Jverkoey, you shouldn't have commented the code for HelpMePlease.
    True enough, but I doubt that it will have much of an impact on the OP

    Besides, a couple of added bugs (well C code turned into C++ code) will sure keep the OP guessing at assignment hand-in time. So long as they go un-noticed / fixed, all will be well with the universe
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  13. #13
    www.entropysink.com
    Join Date
    Feb 2002
    Posts
    603
    Quote Originally Posted by HelpMePlease
    I wrote the code and now need to know the names of the technical bits I have used without noticing.
    I understand. Happens to me all the time. There I am coding away, when all of a sudden I realise I've used one of those technical bits without noticing. Sucks, doesn't it.

    Visit entropysink.com - It's what your PC is made for!

  14. #14
    It's full of stars adrianxw's Avatar
    Join Date
    Aug 2001
    Posts
    4,829
    Enough.

    The guys a jerk, lets leave it there.
    Wave upon wave of demented avengers march cheerfully out of obscurity unto the dream.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Writing Code
    By ILoveVectors in forum C++ Programming
    Replies: 4
    Last Post: 06-13-2005, 12:27 AM
  2. True ASM vs. Fake ASM ????
    By DavidP in forum A Brief History of Cprogramming.com
    Replies: 7
    Last Post: 04-02-2003, 04:28 AM
  3. Seems like correct code, but results are not right...
    By OmniMirror in forum C Programming
    Replies: 4
    Last Post: 02-13-2003, 01:33 PM
  4. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM
  5. Replies: 4
    Last Post: 01-16-2002, 12:04 AM