// ---------------------------------------------------------------------- // System Headers // ---------------------------------------------------------------------- #include #include #include #include #include // ---------------------------------------------------------------------- // Local Headers // ---------------------------------------------------------------------- #include "util.h" // ---------------------------------------------------------------------- // removeCRLF - Strip \r and \n from the end of 's' // ---------------------------------------------------------------------- static char *removeCRLF(char *s) { int i = strlen(s) - 1; while(i >= 0 && (s[i] == '\r' || s[i] == '\n')) s[i--] = '\0'; return(s); } // ---------------------------------------------------------------------- // getLetter - Prompt user for a single letter // ---------------------------------------------------------------------- static char getLetter() { char buffer[255] = { '\0' }; char returnValue = '\0'; while(!returnValue) { int lines = 0; printf("Enter letter: "); do { fgets(buffer, sizeof(buffer), stdin); lines++; } while(!strchr(buffer, '\n')); if(lines == 1 && strlen(removeCRLF(buffer)) == 1 && isalpha(buffer[0])) returnValue = (char)tolower(buffer[0]); } return(returnValue); } // ---------------------------------------------------------------------- // getWord - Returns the word to be guessed // ---------------------------------------------------------------------- static const char *getWord() { static const char *list[] = { "aardvark", "blackbird", "chameleon", "dragonfly", "elephant", "flamingo", "goldfish", "horsefly", "iguana", "jellyfish", "kangaroo", "ladybug", "millipede", "nautilus", "orangutan", "pheasant", "quail", "roadrunner", "seahorse", "tarantula", "urchin", "vulture", "woodpecker", "xerus", "yellowjacket", "zebra" }; static const int n = SIZE(list); return(list[utilRandomValue() % n]); } // ---------------------------------------------------------------------- // stageZero - Returns initial game state // ---------------------------------------------------------------------- static const char *stageZero() { static const char *s = " +----+ \n" " | | \n" " | | \n" " | \n" " | \n" " | \n" " | \n" " | \n" " | \n" " | \n" " | \n"; return(s); } // ---------------------------------------------------------------------- // stageOne - Returns state corresponding to one miss // ---------------------------------------------------------------------- static const char *stageOne() { static const char *s = " +----+ \n" " | | \n" " | | \n" " | O \n" " | \n" " | \n" " | \n" " | \n" " | \n" " | \n" " | \n"; return(s); } // ---------------------------------------------------------------------- // stageTwo - Returns state corresponding to two misses // ---------------------------------------------------------------------- static const char *stageTwo() { static const char *s = " +----+ \n" " | | \n" " | | \n" " | O \n" " | | \n" " | \n" " | \n" " | \n" " | \n" " | \n" " | \n"; return(s); } // ---------------------------------------------------------------------- // stageThree - Returns state corresponding to three misses // ---------------------------------------------------------------------- static const char *stageThree() { static const char *s = " +----+ \n" " | | \n" " | | \n" " | O \n" " | | \n" " | + \n" " | \n" " | \n" " | \n" " | \n" " | \n"; return(s); } // ---------------------------------------------------------------------- // stageFour - Returns state corresponding to four misses // ---------------------------------------------------------------------- static const char *stageFour() { static const char *s = " +----+ \n" " | | \n" " | | \n" " | O \n" " | | \n" " | ---+ \n" " | \n" " | \n" " | \n" " | \n" " | \n"; return(s); } // ---------------------------------------------------------------------- // stageFive - Returns state corresponding to five misses // ---------------------------------------------------------------------- static const char *stageFive() { static const char *s = " +----+ \n" " | | \n" " | | \n" " | O \n" " | | \n" " | --+-- \n" " | \n" " | \n" " | \n" " | \n" " | \n"; return(s); } // ---------------------------------------------------------------------- // stageSix - Returns state corresponding to six misses // ---------------------------------------------------------------------- static const char *stageSix() { static const char *s = " +----+ \n" " | | \n" " | | \n" " | O \n" " | | \n" " | --+-- \n" " | | \n" " | \n" " | \n" " | \n" " | \n"; return(s); } // ---------------------------------------------------------------------- // stageSeven - Returns state corresponding to seven misses // ---------------------------------------------------------------------- static const char *stageSeven() { static const char *s = " +----+ \n" " | | \n" " | | \n" " | O \n" " | | \n" " | --+-- \n" " | | \n" " | + \n" " | \n" " | \n" " | \n"; return(s); } // ---------------------------------------------------------------------- // stageEight - Returns state corresponding to eight misses // ---------------------------------------------------------------------- static const char *stageEight() { static const char *s = " +----+ \n" " | | \n" " | | \n" " | O \n" " | | \n" " | --+-- \n" " | | \n" " | + \n" " | / \n" " | / \n" " | \n"; return(s); } // ---------------------------------------------------------------------- // stageNine - Returns state corresponding to nine misses // ---------------------------------------------------------------------- static const char *stageNine() { static const char *s = " +----+ \n" " | | \n" " | | \n" " | O \n" " | | \n" " | --+-- \n" " | | \n" " | + \n" " | / \\ \n" " | / \\ \n" " | \n"; return(s); } // ---------------------------------------------------------------------- // getStage - Returns the state for the supplied number of misses // ---------------------------------------------------------------------- static const char *getStage(int misses) { typedef const char *(*StageFunction)(); static const StageFunction list[] = { stageZero, stageOne, stageTwo, stageThree, stageFour, stageFive, stageSix, stageSeven, stageEight, stageNine }; static const int n = SIZE(list); return( misses < 0 || misses >= n ? NULL : list[misses]() ); } // ---------------------------------------------------------------------- // showCurrent - Display the current guess // ---------------------------------------------------------------------- static void showCurrent(const char *current) { int i = 0; printf("Current Guess: "); for(i = 0; current[i]; i ++) { if(i > 0) printf(" "); printf("%c", toupper(current[i])); } printf("\n\n"); } // ---------------------------------------------------------------------- // showMessage - Tell the user 'You Win' or 'You Lose' based on whether // 'word' is NULL or not // ---------------------------------------------------------------------- static void showMessage(const char *word) { printf("---------------\n"); printf("You %s\n", word ? "Lose" : "Win"); printf("---------------\n"); if(word) printf("\nThe Word Was: %s\n", word); } // ---------------------------------------------------------------------- // countChar - Return how many times 'c' was found in 's' // ---------------------------------------------------------------------- static int countChar(const char *s, char c) { int count = 0; for(int i = 0; s[i]; i ++) if(s[i] == c) count++; return(count); } // ---------------------------------------------------------------------- // updateCurrent - Reveal any HIDDEN_CHAR chars in 'current' whose // underlying char is 'c' // // Note that 'HIDDEN_CHAR' is the character that is displayed in the // place of not-yet-guessed letters in the current word // ---------------------------------------------------------------------- #define HIDDEN_CHAR '*' static bool updateCurrent(char *current, const char *word, char c) { bool returnValue = false; for(int i = 0; current[i]; i ++) { if(current[i] == HIDDEN_CHAR && word[i] == c) { if(!returnValue) returnValue = true; current[i] = word[i]; } } return(returnValue); } // ---------------------------------------------------------------------- // main // ---------------------------------------------------------------------- int main() { const char *word = getWord(); char current[255] = { '\0' }; int misses = 0; int i = 0; while(word[i]) current[i++] = HIDDEN_CHAR; for(;;) { char c = '\0'; const char *stage = getStage(misses); printf("%s\n", stage); // If this stage has no next stage, we're done if(!getStage(misses + 1)) { showMessage(word); break; } showCurrent(current); // If 'current' has no remaining HIDDEN_CHAR characters // the puzzle has been solved if(countChar(current, HIDDEN_CHAR) == 0) { showMessage(NULL); break; } // Prompt user for next letter and then // apply it to current c = getLetter(); printf("\n"); if(!updateCurrent(current, word, c)) misses++; } return(0); }