#include #include #include #include #include "puzzles.h" #include "console.h" #include "highscore.h" /* Number of wrong guesses allowed. Game is over when the player has made N wrong guesses */ #define N 7 /* The max number of entries on the highscore list */ #define M 4 #define CHEATING 1 struct hangmanGameState { char playerName[NAME_MAX]; int numberOfWrongGuesses; int numberOfCorrectGuesses; int charGuessed[128]; /* a boolean pr letter in the ASCII alphabet. 1: Guessed or always revealed. 0: Not guessed yet*/ }; typedef struct hangmanGameState hangmanGameState; enum answer {yes, no}; typedef enum answer answer; void initHangman (void); answer askUser(char *question); void playHangman (char playerName[]); char *getPlayerName(); void initGame (char playerName[], hangmanGameState *state); void presentPuzzleOutline(puzzle secretPuzzle, hangmanGameState gameState); void presentRemainingAlphabet(hangmanGameState gameState); char *secretPhraseOutline(char *phrase, hangmanGameState gameState); char getUsersGuess(); void updateGameState(hangmanGameState *gameState, puzzle p, char playersGuess); int occurrencesOfCharInString(char ch, char* str); void gameStatistics(hangmanGameState gameState, puzzle p); void presentSecretPuzzle(puzzle p); char mobilCharMapping(char ch); int wonOrLost(hangmanGameState gameState,puzzle secretPuzzle); void handleHighscore(hangmanGameState gameState,puzzle secretPuzzle, int wonGame); void playSound(); void presentHighscoreList(highscoreEntry *hsl, int n); int main(void){ char *playerName; answer again; playerName = getPlayerName(); initHangman(); do{ playHangman(playerName); again = askUser("Do you want to play again"); } while (again == yes); } char *getPlayerName(){ char *playerName = (char*)malloc(NAME_MAX); printf("What is your name? "); fgets(playerName, NAME_MAX, stdin); playerName[strlen(playerName)-1] = '\0'; return playerName; } void initHangman (void){ srand(time(NULL)); initPuzzles("puzzles.txt"); } answer askUser(char *question){ char ch; do { printf("%s [y/n]? ", question); while (isspace(ch = fgetc(stdin))); if (ch == 'y') return yes; else if (ch == 'n') return no;} while (ch != 'y' || ch != 'n'); } void playHangman (char playerName[]){ int aPuzzleNumber, wonGame; puzzle secretPuzzle; hangmanGameState gameState; char playersGuess; initGame(playerName, &gameState); aPuzzleNumber = rand() % numberOfPuzzles(); secretPuzzle = getPuzzle(aPuzzleNumber); while ((gameState.numberOfWrongGuesses < N) && (gameState.numberOfCorrectGuesses < secretPuzzle.numberOfCharsToGuess)){ gameStatistics(gameState, secretPuzzle); presentPuzzleOutline(secretPuzzle,gameState); printf("\n"); presentRemainingAlphabet(gameState); printf("\n"); if (CHEATING) presentSecretPuzzle(secretPuzzle); printf("\n"); playersGuess = getUsersGuess(); clrconsole(); updateGameState(&gameState, secretPuzzle, playersGuess); } gameStatistics(gameState, secretPuzzle); wonGame = wonOrLost(gameState,secretPuzzle); handleHighscore(gameState, secretPuzzle, wonGame); } char getUsersGuess(){ char ch; printf("What is you next guess: "); while (isspace(ch = fgetc(stdin))); return ch; } void initGame (char playerName[], hangmanGameState *state){ strcpy(state->playerName, playerName); state->numberOfWrongGuesses = 0; state->numberOfCorrectGuesses = 0; int i; for (i=0; i < 128; i++){ if (isalpha(i)) state->charGuessed[i] = 0; else state->charGuessed[i] = 1; } initHighscoreFacility("highscorefile"); clrconsole(); } void presentPuzzleOutline(puzzle secretPuzzle, hangmanGameState gameState){ printf("Category: %s\n", secretPuzzle.category); printf("Secret phrase: %s\n", secretPhraseOutline(secretPuzzle.phrase, gameState)); } void presentRemainingAlphabet(hangmanGameState gameState){ int i; printf("Remaining letters: "); printf("\n"); for (i = 65; i <= 90; i++) if (!gameState.charGuessed[i]) printf("%c", i); printf("\n"); for (i = 65; i <= 90; i++) if (!gameState.charGuessed[i]) printf("%c", mobilCharMapping(i)); printf("\n"); } char *secretPhraseOutline(char *phrase, hangmanGameState gameState){ char *result; int i; result = calloc(strlen(phrase) + 1, 1); /* already with zero contents */ for(i = 0; i < strlen(phrase); i++){ if (gameState.charGuessed[phrase[i]] == 1) /* Already guessed, or always char always revealed */ result[i] = phrase[i]; else if (isalpha(phrase[i])) result[i] = mobilCharMapping(phrase[i]); else result[i] = '?'; /* Should not happen */ } return result; } void updateGameState(hangmanGameState *gameState, puzzle p, char playersGuess){ int oc; oc = occurrencesOfCharInString(playersGuess, p.phrase); char lowerCaseGuess, upperCaseGuess; if (oc == 0){ /* Wrong guess. No occurrences of playersGuess in secret phrase*/ gameState->numberOfWrongGuesses++; playSound(); /* Not here */ } else if ((oc > 0) && gameState->charGuessed[playersGuess] == 0){ /* oc occurrences of playersGuess in secret phrase. This letter has not been guessed before */ gameState->numberOfCorrectGuesses += oc; if (isalpha(playersGuess)){ lowerCaseGuess = tolower(playersGuess); upperCaseGuess = toupper(playersGuess); /* Mark both upper and lower case letter as guessed */ gameState->charGuessed[lowerCaseGuess] = 1; gameState->charGuessed[upperCaseGuess] = 1; } } } /* How many times does ch occur in str */ int occurrencesOfCharInString(char ch, char* str){ int i, res = 0; for(i=0; i hsl->score)){ printf("You made it to the highscore list\n"); fflush(stdout); strcpy(newEntry.name,gameState.playerName); newEntry.score = points; hsMerged = insertIntoHighscoreList(newEntry, hsl, numberOfEntries); if (numberOfEntries + 1 > M){ reducedHsl = hsMerged + 1; newNumberOfEntries = numberOfEntries; } else{ reducedHsl = hsMerged; newNumberOfEntries = numberOfEntries + 1; } writeHighscoreList(reducedHsl, newNumberOfEntries); presentHighscoreList(reducedHsl, newNumberOfEntries); } else{ printf("You did not make it to the highscore list\n"); presentHighscoreList(hsl, numberOfEntries); } } void presentHighscoreList(highscoreEntry *hsl, int n){ int i; for (i = n-1; i >= 0; i--) printf("%s : %d\n", hsl[i].name, hsl[i].score); } void playSound (){ fputc(7, stdout); }