/* hangman.c - a hangman game similar to one seen on some *nix machines.* * * * hangman [wordlist] * * if wordlist is not specified, reads words in current * * directory if it exists, else reads dict:words. * * * * hangman (C) 1989 by Gary L. Brant * * * * :ts=8 */ #include #include #include #include char word[30]; char dead_man[][4] = { " O ", "/|\\", " | ", "/ \\" }; char guessed[28]; /* letters already guessed */ int count = 0; /* count of letters in guessed */ char blimp[30]; /* string of -'s length of word */ char dictionary[30]; /* file name of dictionary */ float curavg = 0.0; float overavg = 0.0; int wordno = 0; long totalwrong = 0L; int done = 0; int raw_mode = 0; /* true if currently in raw mode */ FILE *dict, *fopen (); struct stat statbuf; long size; main (argc, argv) int argc; char *argv[]; { int i; if (argc > 1) { if ((dict = fopen (argv[1], "r")) == NULL) { printf ("can't open %s\n", argv[1]); exit (20); } else strcpy (dictionary, argv[1]); } else if ((dict = fopen ("words", "r")) == NULL) { if ((dict = fopen ("dict:words", "r")) == NULL) { printf ("can't find dictionary\n"); exit (20); } else strcpy (dictionary, "dict:words"); } else strcpy (dictionary, "words"); if ((stat (dictionary, &statbuf)) == -1) { printf ("can't get info for %s\n", dictionary); quit (10); } size = statbuf.st_size; srand ((int) time ((long *) 0)); /* use time as random seed */ do { /* loop until user says no more */ getword (); /* get word from dictionary */ set_raw (); raw_mode = 1; hangman (); /* play one word game */ newgame (); set_con (); raw_mode = 0; } while (!done); quit (0); } /* get a random number. */ long getran () { long time (); unsigned long i, j; i = rand (); j = rand (); i += 65536 * j; /* fabricate a random long int */ return (i); } /* get a word from the dictionary for use in the game */ getword () { register int i, len; long num; long position; for (;;) { num = getran (); /* get an random long integer */ position = num % size; if ((fseek (dict, position, 0)) != 0) { printf ("can't seek on %s\n", dictionary); quit (10); } fgets (word, 29, dict); if (fgets (word, 29, dict) == NULL) continue; if ((len = strlen (word) - 1) < 4) continue; for (i = 0; i < len; i++) if (word[i] < 'a' || word[i] > 'z') goto nogood; word[len] = '\0'; return; /* return word found */ nogood: continue; } } /* play one word game, return as soon as guesses used up or word guessed. * Display a congratulatory message before exiting if player guessed the * word, else display the word. */ hangman () { char guess; /* the current guess */ int i; int togo; /* number of letters still to be guessed */ int wrong = 0; /* number of incorrect guesses */ char getcharacter (); /* get user's input */ nextword (); redraw (); togo = strlen (word); while (togo > 0) { /* haven't guessed all the characters */ int dup = 0; /* if letter was guessed before */ for (;;) { /* do until guess is a character */ scr_curs (12, 8); scr_eol (); fflush (stdout); guess = getcharacter (); putc (guess, stdout); if (guess == '\f') /* redraw screen if ^L */ redraw (); else if (!isalpha (guess)) { /* disallow non-alpha characters */ scr_beep (); scr_curs (12, 8); scr_eol (); scr_curs (13, 0); fputs ("Not a valid guess, ", stdout); if (guess < ' ') { char bad[4]; bad[0] = '^'; bad[1] = guess + 'A' - 1; bad[2] = '\0'; fputs (bad, stdout); } else putc (guess, stdout); } else break; /* drop out of loop if alpha */ } for (i = 0; guessed[i]; i++) if (guess == guessed[i]) { dup = 1; break; } scr_curs (13, 0); scr_eol (); if (dup) { /* if previously guessed */ printf ("Already guessed %c", guess); dup = 0; } else { int inword = 0; /* if guess in word */ for (i = 0; word[i]; i++) { if (guess == word[i]) { inword = 1; togo--; blimp[i] = guess; scr_curs (11, i+8); putc (guess, stdout); /* place letter in word */ if (togo == 0) { /* if word completed */ insert (guess); scr_curs (13, 0); fputs ("You got it!", stdout); return; } } } if (!inword) { wrong++; /* scorekeeping */ totalwrong++; curavg += 1.0 / ((float) wordno); scr_curs (6, 49); /* update current average on screen */ printf ("%8.4f", curavg); switch (wrong) { case 1: scr_curs (3, 10); putc ('O', stdout); dead_man[0][1] = 'O'; break; case 2: scr_curs (4, 10); putc ('|', stdout); dead_man[1][1] = '|'; break; case 3: scr_curs (5, 10); putc ('|', stdout); dead_man[2][1] = '|'; break; case 4: scr_curs (6, 9); putc ('/', stdout); dead_man[3][0] = '/'; break; case 5: scr_curs (4, 9); putc ('/', stdout); dead_man[1][0] = '/'; break; case 6: scr_curs (4, 11); putc ('\\', stdout); dead_man[1][2] = '\\'; break; case 7: scr_curs (6, 11); putc ('\\', stdout); dead_man[3][2] = '\\'; scr_curs (13, 0); fputs ("The word was: ", stdout); fputs (word, stdout); return; } } insert (guess); } } return; } /* game over; inquire from player whether to play another */ newgame () { char c; scr_curs (14, 0); fputs ("Another word? ", stdout); for (;;) { fflush (stdout); c = getcharacter (); if (c == 'n') { done = 1; return; } else if (c == 'y') return; scr_curs (15, 0); fputs ("Please type 'y' or 'n'", stdout); scr_curs (14, 15); } } /* redraw display at beginning of new word or at user request (^L) */ redraw () { int i; scr_clear (); scr_curs (1, 5); fputs ("______", stdout); scr_curs (2, 5); fputs ("| |", stdout); scr_curs (3, 5); putc ('|', stdout); scr_curs (3, 10); putc (dead_man[0][1], stdout); scr_curs (3, 32); fputs ("Guessed: ", stdout); fputs (guessed, stdout); scr_curs (4, 5); putc ('|', stdout); scr_curs (4, 9); for (i = 0; i < 3; i++) putc (dead_man[1][i], stdout); scr_curs (5, 5); putc ('|', stdout); scr_curs (5, 9); for (i = 0; i < 3; i++) putc (dead_man[2][i], stdout); scr_curs (5, 32); printf ("Word #: %d", wordno); scr_curs (6, 5); putc ('|', stdout); scr_curs (6, 9); for (i = 0; i < 3; i++) putc (dead_man[3][i], stdout); scr_curs (6, 32); printf ("Current Average: %8.4f", curavg); scr_curs (7, 3); fputs ("__|_____", stdout); scr_curs (7, 32); printf ("Overall Average: %8.4f", overavg); scr_curs (8, 3); putc ('|', stdout); scr_curs (8, 10); fputs ("|___", stdout); scr_curs (9, 3); fputs ("|_________|", stdout); scr_curs (11, 1); fputs ("Word: ", stdout); fputs (blimp, stdout); scr_curs (12, 0); fputs ("Guess:", stdout); fflush (stdout); } /* reset stuff for next word */ nextword () { int i, j; for (i = 0; i < 4; i++) for (j = 0; j < 3; j++) dead_man[i][j] = ' '; for (i = 0; i < strlen (word); i++) blimp[i] = '-'; blimp[i] = '\0'; for (i = 0; i < 28; i++) guessed[i] = '\0'; count = 0; wordno++; overavg = curavg; curavg = ((float) totalwrong) / ((float) wordno); } /* get user's input */ char getcharacter () { while (!WaitForChar (Input (), 100L) && stdin->_bp >= stdin->_bend); return (tolower (getc (stdin))); } /* insert letter just guessed into list of guessed letters; also update list * on screen for player. */ insert (guess) register char guess; { if (count == 0) { /* first guess ? */ guessed[count++] = guess; scr_curs (3, 42); putc (guess, stdout); } else { register int i, j; for (i = 0; i < count; i++) if (guessed[i] > guess) break; for (j = count; j > i; j--) guessed[j] = guessed[j-1]; guessed[i] = guess; /* add the guess to list of */ /* previously guessed letters*/ scr_curs (3, i+42); fputs (&guessed[i], stdout); /* update list on screen */ count++; } } /* needed, since Manx version apparently doesn't work */ scr_eol () { static char clr[] = {0x9b, 'K', '\0'}; fputs (clr, stdout); } /* in order to have a chance at cleaning up & exiting gracefully */ _abort () { puts ("^C"); quit (0); } quit (code) int code; { if (dict) fclose (dict); set_con (); exit (code); } _wb_parse () { }