Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions exercises/practice/hang/hangman.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include "hangman.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>

Hangman* create_game(const char* word) {
Hangman* game = malloc(sizeof(Hangman));
if (!game) return NULL;

game->word = strdup(word);
game->masked_word = malloc(strlen(word) + 1);
game->guessed_letters = calloc(26, sizeof(int));

for (size_t i = 0; i < strlen(word); i++) {
game->masked_word[i] = '_';
}
game->masked_word[strlen(word)] = '\0';

game->remaining_guesses = 9;
game->status = STATUS_ONGOING;

return game;
}

void destroy_game(Hangman* game) {
if (!game) return;
free(game->word);
free(game->masked_word);
free(game->guessed_letters);
free(game);
}

void guess_letter(Hangman* game, char letter) {
if (strcmp(game->status, STATUS_ONGOING) != 0) {
fprintf(stderr, "The game has already ended.\n");
exit(1);
}

letter = tolower(letter);
if (game->guessed_letters[letter - 'a']) {
game->remaining_guesses--;
return;
}

game->guessed_letters[letter - 'a'] = 1;

int correct = 0;
for (size_t i = 0; i < strlen(game->word); i++) {
if (tolower(game->word[i]) == letter) {
game->masked_word[i] = game->word[i];
correct = 1;
}
}

if (!correct) {
game->remaining_guesses--;
}

if (strcmp(game->word, game->masked_word) == 0) {
game->status = STATUS_WIN;
} else if (game->remaining_guesses == 0) {
game->status = STATUS_LOSE;
}
}

const char* get_masked_word(Hangman* game) {
return game->masked_word;
}

const char* get_status(Hangman* game) {
return game->status;
}
22 changes: 22 additions & 0 deletions exercises/practice/hang/hangman.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef HANGMAN_H
#define HANGMAN_H

#define STATUS_WIN "win"
#define STATUS_LOSE "lose"
#define STATUS_ONGOING "ongoing"

typedef struct {
char* word;
char* masked_word;
int* guessed_letters;
int remaining_guesses;
const char* status;
} Hangman;

Hangman* create_game(const char* word);
void destroy_game(Hangman* game);
void guess_letter(Hangman* game, char letter);
const char* get_masked_word(Hangman* game);
const char* get_status(Hangman* game);

#endif
60 changes: 60 additions & 0 deletions exercises/practice/hang/hangman_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "test-framework/unity.h"
#include "hangman.h"
#include "string.h"

void setUp(void) {
}

void tearDown(void) {
}

void test_initial_state(void) {
Hangman* game = create_game("foo");
TEST_ASSERT_EQUAL_STRING(STATUS_ONGOING, get_status(game));
TEST_ASSERT_EQUAL_STRING("___", get_masked_word(game));
TEST_ASSERT_EQUAL_INT(9, game->remaining_guesses);
destroy_game(game);
}

// void test_game_lost_after_10_wrong_guesses(void) {
// Hangman* game = create_game("foo");

// for (int i = 0; i < 10; i++) {
// guess_letter(game, 'x');
// }

// TEST_ASSERT_EQUAL_STRING(STATUS_LOSE, get_status(game));

// destroy_game(game);
// }

void test_correct_guess_reveals_letter(void) {
Hangman* game = create_game("foobar");
guess_letter(game, 'b');
TEST_ASSERT_EQUAL_STRING(STATUS_ONGOING, get_status(game));
TEST_ASSERT_EQUAL_STRING("___b__", get_masked_word(game));
TEST_ASSERT_EQUAL_INT(9, game->remaining_guesses);
destroy_game(game);
}

void test_wrong_guess_reduces_remaining(void) {
Hangman* game = create_game("foo");
guess_letter(game, 'x');
TEST_ASSERT_EQUAL_STRING(STATUS_ONGOING, get_status(game));
TEST_ASSERT_EQUAL_STRING("___", get_masked_word(game));
TEST_ASSERT_EQUAL_INT(8, game->remaining_guesses);
destroy_game(game);
}



int main(void) {
UNITY_BEGIN();

RUN_TEST(test_initial_state);
//RUN_TEST(test_game_lost_after_10_wrong_guesses);
RUN_TEST(test_correct_guess_reveals_letter);
RUN_TEST(test_wrong_guess_reduces_remaining);

return UNITY_END();
}
14 changes: 14 additions & 0 deletions exercises/practice/hang/makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CC = gcc
CFLAGS = -Wall -Wextra -std=c99

SRC = hangman.c test-framework/unity.c hangman_test.c
OUT = test_runner

all: test

test:
$(CC) $(CFLAGS) $(SRC) -o $(OUT)
./$(OUT)

clean:
rm -f $(OUT)
Loading
Loading