Code:
#include "hangman.h"
/****************************************************************************
* Function main() is the entry point for the program.
****************************************************************************/
int main(void)
{
char word[MAX_WORD_LEN + 1];
unsigned wrongGuesses = 0;
int guessedLetters[ALPHABET_SIZE] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
init(word);
do
{
displayWord(word, guessedLetters);
if(guessLetter(word, guessedLetters) == BAD_GUESS)
wrongGuesses++;
displayHangman(wrongGuesses);
} while(isGameOver(word, guessedLetters, wrongGuesses) != GAME_OVER);
return EXIT_SUCCESS;
}
/****************************************************************************
* Function init() choses a word for the hangman game from the words[] array.
****************************************************************************/
void init(char* word)
{
const char* words[NUM_WORDS] = {
"array", "auto", "break", "case", "cast",
"character", "comment", "compiler", "constant", "continue",
"default", "double", "dynamic", "else", "enum",
"expression", "extern", "file", "float", "function",
"goto", "heap", "identifier", "library", "linker",
"long", "macro", "operand", "operator", "pointer",
"prototype", "recursion", "register", "return", "short",
"signed", "sizeof", "stack", "statement", "static",
"string", "struct", "switch", "typedef", "union",
"unsigned", "variable", "void", "volatile", "while"
};
srand(time(NULL));
strcpy(word, words[rand() % NUM_WORDS]);
}
/****************************************************************************
* Function displayWord() prints the word to screen with all letters that
* have not been correctly guessed blanked out with an underscore.
* Output example:
* +-+-+-+-+-+-+-+-+-+-+
* |i|d|e|n|_|i|_|i|e|r|
* +-+-+-+-+-+-+-+-+-+-+
****************************************************************************/
void displayWord(char* word, int* guessedLetters)
{
char *ptr;
for(ptr=word; *ptr !='\0'; ptr++)
{
if(guessedLetters[*ptr-'a'] = 1)
printf("%c", *ptr);
else
printf("-");
}
}
/****************************************************************************
* Function guessLetter() prompts the user to enter one letter. The function
* maintains an array of guessed letters. The function returns GOOD_GUESS
* or BAD_GUESS depending on whether or not the letter is in the word.
****************************************************************************/
int guessLetter(char* word, int* guessedLetters)
{
char guess[3];
char *ptr = word;
int result = BAD_GUESS;
int valid = FALSE;
do
{
printf("\nEnter a letter: ");
fgets(guess, 3, stdin);
valid = isValid(guess);
if(valid == TRUE)
{
if(guess[0] < 'a' || guess[0] > 'z')
{
valid = FALSE;
printf("Invalid characters, try again!");
}
}
} while(valid = FALSE);
for(ptr=word; *ptr !='\0'; ptr++)
{
if(guess[0] == *ptr)
{
guessedLetters[(int)guess[0] - 'a'] = 1;
result = GOOD_GUESS;
break;
}
}
if(result == BAD_GUESS)
{
guessedLetters[(int)guess[0] - 'a'] = 2;
printf("\nWrong Guess, Please try again!\n");
}
return result;
}
/****************************************************************************
* Function displayHangman() displays an ascii art drawing to complement the
* game. The drawing varies depending on the number of wrong guesses.
* When there are no wrong guesses, an empty drawing is displayed:
* **********
* * *
* * *
* * *
* * *
* * *
* * *
* **********
* When there are 10 wrong guesses (and the game is over), the complete
* drawing is displayed:
* **********
* * +--+ *
* * | | *
* * | O *
* * | -+- *
* * | / \ *
* * +----- *
* **********
* You need to display an appropriate drawing depending on the number of
* wrong guesses:
* - 0 wrong: empty drawing.
* - 1 wrong: include floor.
* - 2 wrong: include vertical beam.
* - 3 wrong: include horizontal beam.
* - 4 wrong: include noose.
* - 5 wrong: include head.
* - 6 wrong: include body.
* - 7 wrong: include left arm.
* - 8 wrong: include right arm.
* - 9 wrong: include left leg.
* - 10 wrong: include right leg (complete drawing).
****************************************************************************/
void displayHangman(unsigned wrongGuesses)
{
if(wrongGuesses == 1)
printf("-----");
else if(wrongGuesses == 2)
printf("+\n|\n|\n|\n|\n+-----");
else if(wrongGuesses == 3)
printf("+--+\n|\n|\n|\n|\n+-----");
else if(wrongGuesses == 4)
printf("+--+\n| |\n|\n|\n|\n+-----");
else if(wrongGuesses == 5)
printf("+--+\n| |\n| o\n|\n|\n+-----");
else if(wrongGuesses == 6)
printf("+--+\n| |\n| o\n| +\n|\n+-----");
else if(wrongGuesses == 7)
printf("+--+\n| |\n| o\n| -+\n|\n+-----");
else if(wrongGuesses == 8)
printf("+--+\n| |\n| o\n| -+-\n|\n+-----");
else if(wrongGuesses == 9)
printf("+--+\n| |\n| o\n| -+-\n| /\n+-----");
else if(wrongGuesses == 10)
printf("+--+\n| |\n| o\n| -+-\n| // \n+-----");
}
/****************************************************************************
* Function isGameOver() is the final step in the program. The game is over
* if either all letters in the word have been guessed, or the player has run
* out of guesses. The player is congratulated if he/she wins. The word is
* displayed to the player if he/she loses. This function returns either
* GAME_OVER or GAME_CONTINUE.
****************************************************************************/
int isGameOver(char* word, int* guessedLetters, unsigned wrongGuesses)
{
int noWords = 0;
int i;
for(i=0; i<ALPHABET_SIZE; i++)
{
if(guessedLetters[i] == 1)
noWords++;
}
if(noWords = strlen(word))
{
printf("Congratulations! You have guessed the word!");
return GAME_OVER;
}
if(wrongGuesses >= MAX_GUESS)
{
printf("You have exceeded the number of allocated guesses! Game Over!");
return GAME_OVER;
}
else
GAME_CONTINUE;
}
/****************************************************************************
* Function readRestOfLine() is used for buffer clearing. Source:
* https://inside.cs.rmit.edu.au/~sdb/teaching/C-Prog/CourseDocuments/
* FrequentlyAskedQuestions/
****************************************************************************/
void readRestOfLine()
{
int c;
/* Read until the end of the line or end-of-file. */
while ((c = fgetc(stdin)) != '\n' && c != EOF)
;
/* Clear the error and end-of-file flags. */
clearerr(stdin);
}
int isValid(char *input)
{
int valid = FALSE;
if(input[strlen(input)-1] != '\n')
{
printf("Input too long, please try again!");
readRestOfLine();
}
else
{
input[strlen(input)-1] = '\0';
valid = TRUE;
}
return valid;
}