mirror of
https://github.com/TheAlgorithms/C
synced 2024-11-21 13:01:34 +03:00
* Add files via upload feat: added hangman game #967 * Update hangman.c * Update hangman.c * Update hangman.c * Update hangman.c * Update hangman.c * Update hangman.c Updated so that game instance was held as struct - can include current guess in game_instance too if preferred. * Update hangman.c * Update hangman.c * Add files via upload Adding test file * Update hangman.c * Update hangman.c Co-authored-by: David Leal <halfpacho@gmail.com> Co-authored-by: Sharon "Cass" Cassidy <monadicdiffusive@proton.me>
This commit is contained in:
parent
2b885108b8
commit
71a7cf3bc4
291
games/hangman.c
Normal file
291
games/hangman.c
Normal file
@ -0,0 +1,291 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief C implementation of [Hangman Game](https://en.wikipedia.org/wiki/Hangman_(game))
|
||||
* @details
|
||||
* Simple, readable version of hangman.
|
||||
* Changed graphic to duck instead of traditional stick figure (same number of guesses).
|
||||
* @author [AtlantaEmrys2002](https://github.com/AtlantaEmrys2002)
|
||||
*/
|
||||
|
||||
#include <ctype.h> /// for main() - tolower()
|
||||
#include <stdio.h> /// for main(), new_word(), new_guess(), won() - I/O operations
|
||||
#include <stdlib.h> /// for all functions - exit(), rand() and file functions
|
||||
#include <string.h> /// for main() - for string operations strlen, strchr, strcpy
|
||||
#include <time.h> /// for new_game() - used with srand() for declaring new game instance
|
||||
|
||||
/*
|
||||
* @brief game_instance structure that holds current state of game
|
||||
*/
|
||||
struct game_instance{
|
||||
|
||||
char current_word[30]; ///< word to be guessed by player
|
||||
char hidden[30]; ///< hidden version of word that is displayed to player
|
||||
int size; ///< size of word
|
||||
int incorrect; ///< number of incorrect guesses
|
||||
char guesses[25]; ///< previous guesses
|
||||
int guesses_size; ///< size of guesses array
|
||||
|
||||
};
|
||||
|
||||
// function prototypes
|
||||
struct game_instance new_game(void); // creates a new game
|
||||
int new_guess(char, const char guesses[], int size); // checks if player has already played letter
|
||||
int in_word(char, const char word[], unsigned int size); // checks if letter is in word
|
||||
void picture(int score); // outputs image of duck (instead of hang man)
|
||||
void won(const char word[], int score); // checks if player has won or lost
|
||||
|
||||
/**
|
||||
* @brief Main Function
|
||||
* @returns 0 on exit
|
||||
*/
|
||||
int main() {
|
||||
|
||||
struct game_instance game = new_game(); // new game created
|
||||
char guess; // current letter guessed by player
|
||||
|
||||
// main loop - asks player for guesses
|
||||
while ((strchr(game.hidden, '_') != NULL) && game.incorrect <= 12) {
|
||||
do {
|
||||
printf("\n****************************\n");
|
||||
printf("Your word: ");
|
||||
|
||||
for (int i = 0; i < game.size; i++) {
|
||||
printf("%c ", game.hidden[i]);
|
||||
}
|
||||
|
||||
if (game.guesses_size > 0) {
|
||||
printf("\nSo far, you have guessed: ");
|
||||
for (int i = 0; i < game.guesses_size; i++) {
|
||||
printf("%c ", game.guesses[i]);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nYou have %d guesses left.", (12 - game.incorrect));
|
||||
printf("\nPlease enter a letter: ");
|
||||
scanf(" %c", &guess);
|
||||
guess = tolower(guess);
|
||||
|
||||
} while (new_guess(guess, game.guesses, game.guesses_size) != -1);
|
||||
|
||||
game.guesses[game.guesses_size] = guess; // adds new letter to guesses array
|
||||
game.guesses_size++; // updates size of guesses array
|
||||
|
||||
if (in_word(guess, game.current_word, game.size) == 1) {
|
||||
printf("That letter is in the word!");
|
||||
for (int i = 0; i < game.size; i++) {
|
||||
if ((game.current_word[i]) == guess) {
|
||||
game.hidden[i] = guess;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("That letter is not in the word.\n");
|
||||
(game.incorrect)++;
|
||||
}
|
||||
picture(game.incorrect);
|
||||
}
|
||||
|
||||
won(game.current_word, game.incorrect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief checks if letter has been guessed before
|
||||
* @param new_guess letter that has been guessed by player
|
||||
* @param guesses array of player's previous guesses
|
||||
* @param size size of guesses[] array
|
||||
* @returns 1 if letter has been guessed before
|
||||
* @returns -1 if letter has not been guessed before
|
||||
*/
|
||||
int new_guess(char new_guess, const char guesses[], int size) {
|
||||
|
||||
for (int j = 0; j < size; j++) {
|
||||
if (guesses[j] == new_guess) {
|
||||
printf("\nYou have already guessed that letter.");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief checks if letter is in current word
|
||||
* @param letter letter guessed by player
|
||||
* @param word current word
|
||||
* @param size length of word
|
||||
* @returns 1 if letter is in word
|
||||
* @returns -1 if letter is not in word
|
||||
*/
|
||||
int in_word(char letter, const char word[], unsigned int size) {
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
if ((word[i]) == letter) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief creates a new game - generates a random word and stores in global variable current_word
|
||||
* @returns current_game - a new game instance containing randomly selected word, its length and hidden version of word
|
||||
*/
|
||||
struct game_instance new_game() {
|
||||
|
||||
char word[30]; // used throughout function
|
||||
|
||||
FILE *fptr;
|
||||
fptr = fopen("games/words.txt", "r");
|
||||
|
||||
if (fptr == NULL){
|
||||
fprintf(stderr, "File not found.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// counts number of words in file - assumes each word on new line
|
||||
int line_number = 0;
|
||||
while (fgets(word, 30, fptr) != NULL) {
|
||||
line_number++;
|
||||
}
|
||||
|
||||
rewind(fptr);
|
||||
|
||||
// generates random number
|
||||
int random_num;
|
||||
srand(time(NULL));
|
||||
random_num = rand() % line_number;
|
||||
|
||||
// selects randomly generated word
|
||||
int s = 0;
|
||||
while (s <= random_num){
|
||||
fgets(word, 30, fptr);
|
||||
s++;
|
||||
}
|
||||
|
||||
// formats string correctly
|
||||
if (strchr(word, '\n') != NULL){
|
||||
word[strlen(word) - 1] = '\0';
|
||||
}
|
||||
|
||||
fclose(fptr);
|
||||
|
||||
// creates new game instance
|
||||
struct game_instance current_game;
|
||||
strcpy(current_game.current_word, word);
|
||||
current_game.size = strlen(word);
|
||||
for (int i = 0; i < (strlen(word)); i++) {
|
||||
current_game.hidden[i] = '_';
|
||||
}
|
||||
current_game.incorrect = 0;
|
||||
current_game.guesses_size = 0;
|
||||
|
||||
return current_game;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief checks if player has won or lost
|
||||
* @param word the word player has attempted to guess
|
||||
* @param score how many incorrect guesses player has made
|
||||
* @returns void
|
||||
*/
|
||||
void won(const char word[], int score) {
|
||||
if (score > 12) {
|
||||
printf("\nYou lost! The word was: %s.\n", word);
|
||||
}
|
||||
else {
|
||||
printf("\nYou won! You had %d guesses left.\n", (12 - score));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief gradually draws duck as player gets letters incorrect
|
||||
* @param score how many incorrect guesses player has made
|
||||
* @returns void
|
||||
*/
|
||||
void picture(int score) {
|
||||
|
||||
switch(score) {
|
||||
|
||||
case 12:
|
||||
printf("\n _\n"
|
||||
" __( ' )> \n"
|
||||
" \\_ < _ ) ");
|
||||
break;
|
||||
|
||||
case 11:
|
||||
printf("\n _\n"
|
||||
" __( ' )\n"
|
||||
" \\_ < _ ) ");
|
||||
break;
|
||||
|
||||
case 10:
|
||||
printf("\n _\n"
|
||||
" __( )\n"
|
||||
" \\_ < _ ) ");
|
||||
break;
|
||||
|
||||
case 9:
|
||||
printf("\n \n"
|
||||
" __( )\n"
|
||||
" \\_ < _ ) ");
|
||||
break;
|
||||
|
||||
case 8:
|
||||
printf("\n \n"
|
||||
" __( \n"
|
||||
" \\_ < _ ) ");
|
||||
break;
|
||||
|
||||
case 7:
|
||||
printf("\n \n"
|
||||
" __ \n"
|
||||
" \\_ < _ ) ");
|
||||
break;
|
||||
|
||||
case 6:
|
||||
printf("\n \n"
|
||||
" _ \n"
|
||||
" \\_ < _ ) ");
|
||||
break;
|
||||
|
||||
case 5:
|
||||
printf("\n \n"
|
||||
" _ \n"
|
||||
" _ < _ ) ");
|
||||
break;
|
||||
|
||||
case 4:
|
||||
printf("\n \n"
|
||||
" \n"
|
||||
" _ < _ ) ");
|
||||
break;
|
||||
|
||||
case 3:
|
||||
printf("\n \n"
|
||||
" \n"
|
||||
" < _ ) ");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
printf("\n \n"
|
||||
" \n"
|
||||
" _ ) ");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
printf("\n \n"
|
||||
" \n"
|
||||
" ) ");
|
||||
break;
|
||||
|
||||
case 0:
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("\n _\n"
|
||||
" __( ' )> QUACK!\n"
|
||||
" \\_ < _ ) ");
|
||||
break;
|
||||
}
|
||||
}
|
8
games/words.txt
Normal file
8
games/words.txt
Normal file
@ -0,0 +1,8 @@
|
||||
dog
|
||||
cat
|
||||
tree
|
||||
flower
|
||||
table
|
||||
programming
|
||||
language
|
||||
testing
|
Loading…
Reference in New Issue
Block a user