diff --git a/test.c b/test.c index 7e3e3aaa5b6611b143e6c207e0ff0a39904cf13b..edd9bc63a7523aff7e554fe21bebceab8c1bc468 100644 --- a/test.c +++ b/test.c @@ -1,17 +1,24 @@ #include "unity/unity.h" #include "word-bank/test/bank-test.h" +#include "wordle/test/wordle-test.h" -void setUp(void) { - // set stuff up here -} +void setUp(void) { setup_wordle(); } -void tearDown(void) { - // clean stuff up here -} +void tearDown(void) { teardown_wordle(); } // not needed when using generate_test_runner.rb int main(void) { UNITY_BEGIN(); + // Bank RUN_TEST(test_random_word_should_be_jeter); + RUN_TEST(test_bank_size_should_be_1529); + + // Wordle + RUN_TEST(test_gamemode_should_be_solo); + RUN_TEST(test_gamemode_should_be_versus); + RUN_TEST(test_gamemode_should_be_computer); + RUN_TEST(test_answer_shoud_be_balai); + RUN_TEST(test_validate_letter_should_be_false); + RUN_TEST(test_validate_letter_should_be_true); return UNITY_END(); } \ No newline at end of file diff --git a/word-bank/bank.c b/word-bank/bank.c index 32a7e4946ee488907b4d76c7620529539541290b..c10952874d251dfb20595841cb590caa0341aa6b 100644 --- a/word-bank/bank.c +++ b/word-bank/bank.c @@ -122,6 +122,20 @@ char *get_random_word() { return bank[rand() % bank_count]; } -char **get_bank() { return bank; } +char **get_bank() { + if (bank == NULL) { + init_bank(); + load_bank(); + } + + return bank; +} + +int get_bank_size() { + if (bank == NULL) { + init_bank(); + load_bank(); + } -int get_bank_size() { return bank_count; } \ No newline at end of file + return bank_count; +} \ No newline at end of file diff --git a/word-bank/test/bank-test.c b/word-bank/test/bank-test.c index b7e7a7cc76318a69ecfe81af06ccaff568f7511f..79af85e78b90e94119b63d479518e159657faa5f 100644 --- a/word-bank/test/bank-test.c +++ b/word-bank/test/bank-test.c @@ -6,3 +6,9 @@ void test_random_word_should_be_jeter(void) { TEST_ASSERT_EQUAL_STRING("JETER", word); } + +void test_bank_size_should_be_1529(void) { + int count = get_bank_size(); + + TEST_ASSERT_EQUAL_INT(count, 1529); +} \ No newline at end of file diff --git a/word-bank/test/bank-test.h b/word-bank/test/bank-test.h index 8fc70fb1ee7340665b96da86325d0cd87b465b13..809cf6984b75da2461bfa3c1174918f55a0980ca 100644 --- a/word-bank/test/bank-test.h +++ b/word-bank/test/bank-test.h @@ -7,5 +7,6 @@ #include <time.h> void test_random_word_should_be_jeter(void); +void test_bank_size_should_be_1529(void); #endif diff --git a/wordle/test/wordle-test.c b/wordle/test/wordle-test.c new file mode 100644 index 0000000000000000000000000000000000000000..9acefaa2d880acb5e21969b6fcc72656ca117487 --- /dev/null +++ b/wordle/test/wordle-test.c @@ -0,0 +1,59 @@ +#include "wordle-test.h" + +void setup_wordle(void) { initialize_game(); } + +void teardown_wordle(void) { destroy_game(); } + +void test_gamemode_should_be_solo(void) { + set_gamemode(MENU_SOLO); + + TEST_ASSERT_EQUAL_INT(MENU_SOLO, get_gamemode()); +} + +void test_gamemode_should_be_versus(void) { + set_gamemode(MENU_1_V_1); + + TEST_ASSERT_EQUAL_INT(MENU_1_V_1, get_gamemode()); +} + +void test_gamemode_should_be_computer(void) { + set_gamemode(MENU_COMPUTER); + + TEST_ASSERT_EQUAL_INT(MENU_COMPUTER, get_gamemode()); +} + +void test_answer_shoud_be_balai(void) { + char target[WORD_LENGHT + 1] = "BALAI"; + + set_gamemode(MENU_SOLO); + set_answer(target); + + TEST_ASSERT_EQUAL_STRING(target, get_answer()); +} + +void test_validate_letter_should_be_false(void) { + set_gamemode(MENU_SOLO); + + for (int i = '\0'; i <= '@'; i++) + TEST_ASSERT_FALSE(validate_letter(i)); +} + +void test_validate_letter_should_be_true(void) { + set_gamemode(MENU_SOLO); + + for (int i = 'a'; i <= 'z'; i++) + TEST_ASSERT_TRUE(validate_letter(i)); + + for (int i = 'A'; i <= 'Z'; i++) + TEST_ASSERT_TRUE(validate_letter(i)); +} + +void test_letter_placement_control_should_return_all_0(void) { + int target[WORD_LENGHT] = {0, 0, 0, 0, 0}; + set_gamemode(MENU_SOLO); + + set_answer("BALAI"); + set_try("PONTS"); + + TEST_ASSERT_EQUAL_INT_ARRAY(target, letter_placement_control(), WORD_LENGHT); +} \ No newline at end of file diff --git a/wordle/test/wordle-test.h b/wordle/test/wordle-test.h new file mode 100644 index 0000000000000000000000000000000000000000..980f67f979c94fb99a93cc6825427a3ca37e30db --- /dev/null +++ b/wordle/test/wordle-test.h @@ -0,0 +1,19 @@ +#ifndef WORDLE_TEST_H +#define WORDLE_TEST_H + +#include "../../unity/unity.h" +#include "../wordle.h" +#include <stdio.h> +#include <time.h> + +void setup_wordle(void); +void teardown_wordle(void); +void test_gamemode_should_be_solo(void); +void test_gamemode_should_be_versus(void); +void test_gamemode_should_be_computer(void); +void test_answer_shoud_be_balai(void); +void test_validate_letter_should_be_false(void); +void test_validate_letter_should_be_true(void); +void test_letter_placement_control_should_return_all_0(void); + +#endif diff --git a/wordle/wordle.c b/wordle/wordle.c index 21af6b50f7ee2d7e864d188a4c3fef67f05432d4..3ae5fbe7457b35724f63d37b6c5b420fe1b05f5d 100644 --- a/wordle/wordle.c +++ b/wordle/wordle.c @@ -13,8 +13,68 @@ int current_try_id = 0; int current_try_letter_id = 0; /** - * @brief Initialize the game + * @brief Render the game for the selected gamemode */ +void render_game() { + switch (gamemode) { + case GAMEMODE_SOLO: + draw_title(SOLO_TITLE_ID); + break; + + case GAMEMODE_1_V_1: + draw_title(ONE_V_ONE_TITLE_ID); + break; + + case GAMEMODE_COMPUTER: + draw_title(COMPUTER_TITLE_ID); + break; + } + + show_gameboard(TRIES_COUNT, WORD_LENGHT, tries, validations, score); +} + +/** + * @brief Handle controls + * + * @param key + */ +void handle_controls(int key) { + switch (key) { + case KEYBIND_HELP: + toggle_help(); + break; + + case KEYBIND_QUIT: + terminate_game(); + break; + + case KEYBIND_GUESS: + if (!validate_guess(tries[current_try_id])) + break; + + // Validations + int *tmp = letter_placement_control(chosen_word, tries[current_try_id]); + for (int i = 0; i < WORD_LENGHT; i++) + validations[current_try_id][i] = tmp[i]; + free(tmp); + + current_try_id += 1; + current_try_letter_id = 0; + + // Place correct letters from previous in the current one + if (current_try_id < TRIES_COUNT) { + for (int i = 0; i < WORD_LENGHT; i++) { + if (validations[current_try_id - 1][i] == LETTER_PLACED) + tries[current_try_id][i] = tries[current_try_id - 1][i]; + } + } + break; + } +} + +//========================== +// PUBLIC +//========================== void initialize_game() { // Reset game variables _game_finished = false; @@ -23,7 +83,7 @@ void initialize_game() { score = 0; // Tries and answer setup - chosen_word = get_random_word(); + set_answer(get_random_word()); tries = calloc(TRIES_COUNT, sizeof(char *)); validations = malloc(sizeof(int *) * TRIES_COUNT); @@ -34,15 +94,8 @@ void initialize_game() { } } -/** - * @brief Terminate a game - */ void terminate_game() { _game_finished = true; } -/** - * @brief Destroy a game - * - */ void destroy_game() { for (int i = 0; i < TRIES_COUNT; i++) { free(tries[i]); @@ -53,13 +106,9 @@ void destroy_game() { free(validations); } -/** - * @brief Restart the game - * - */ void restart_game() { score += (TRIES_COUNT - current_try_id) * 10; - chosen_word = get_random_word(); + set_answer(get_random_word()); current_try_id = 0; current_try_letter_id = 0; @@ -72,20 +121,8 @@ void restart_game() { } } -/** - * @brief Condition(s) to lose a game - * - * @return true - * @return false - */ bool lose_condition() { return (current_try_id > TRIES_COUNT - 1); } -/** - * @brief Condition(s) to win a game - * - * @return true - * @return false - */ bool win_condition() { for (int i = 0; i < WORD_LENGHT; i++) { if (validations[current_try_id - (current_try_id > 0 ? 1 : 0)][i] != LETTER_PLACED) @@ -95,58 +132,27 @@ bool win_condition() { return true; } -/** - * @brief Render the game for the selected gamemode - */ -void render_game() { - switch (gamemode) { - case GAMEMODE_SOLO: - draw_title(SOLO_TITLE_ID); - break; - - case GAMEMODE_1_V_1: - draw_title(ONE_V_ONE_TITLE_ID); - break; - - case GAMEMODE_COMPUTER: - draw_title(COMPUTER_TITLE_ID); - break; - } - - show_gameboard(TRIES_COUNT, WORD_LENGHT, tries, validations, score); -} - -/** - * @brief Check if the given letter is a lowercase letter only (ASCII code) - * - * @param key - * @return true - * @return false - */ bool validate_letter(int key) { return (islower(key) || isupper(key)); } -/** - * @brief Control the placement of each letter - */ -int *letter_placement_control(char answer[WORD_LENGHT], char try[WORD_LENGHT]) { +int *letter_placement_control() { int *validation = calloc(WORD_LENGHT, sizeof(int)); char cpy[WORD_LENGHT + 1]; - strcpy(cpy, answer); + strcpy(cpy, chosen_word); for (int i = 0; i < WORD_LENGHT; i++) { - if (strchr(cpy, try[i]) == NULL) + if (strchr(cpy, tries[current_try_id][i]) == NULL) continue; - if (try[i] == answer[i]) { + if (tries[current_try_id][i] == chosen_word[i]) { validation[i] = LETTER_PLACED; cpy[i] = ' '; continue; } char *addr; - if ((addr = strchr(answer, try[i])) != NULL) { + if ((addr = strchr(chosen_word, tries[current_try_id][i])) != NULL) { validation[i] = LETTER_WRONG_PLACE; - cpy[(int)(addr - answer)] = ' '; // Get the index of the found char and replace with space + cpy[(int)(addr - chosen_word)] = ' '; // Get the index of the found char and replace with space continue; } } @@ -154,23 +160,16 @@ int *letter_placement_control(char answer[WORD_LENGHT], char try[WORD_LENGHT]) { return validation; } -/** - * @brief Is a try valid - * - * @param try - * @return true - * @return false - */ -bool validate_guess(char try[WORD_LENGHT]) { +bool validate_guess(char current_try[WORD_LENGHT]) { // Length check - if (strlen(try) < WORD_LENGHT) + if (strlen(current_try) < WORD_LENGHT) return false; // Presence check char **bank = get_bank(); bool present = false; for (int i = 0; i < get_bank_size(); i++) { - if (!strcmp(bank[i], try)) + if (!strcmp(bank[i], current_try)) present = true; } @@ -184,49 +183,15 @@ bool validate_guess(char try[WORD_LENGHT]) { return true; } -/** - * @brief Handle controls - * - * @param key - */ -void handle_controls(int key) { - switch (key) { - case KEYBIND_HELP: - toggle_help(); - break; - - case KEYBIND_QUIT: - terminate_game(); - break; - - case KEYBIND_GUESS: - if (!validate_guess(tries[current_try_id])) - break; +void set_gamemode(int menu_gamemode) { gamemode = menu_gamemode; } - // Validations - int *tmp = letter_placement_control(chosen_word, tries[current_try_id]); - for (int i = 0; i < WORD_LENGHT; i++) - validations[current_try_id][i] = tmp[i]; - free(tmp); +void set_answer(char answer[WORD_LENGHT]) { chosen_word = answer; } - current_try_id += 1; - current_try_letter_id = 0; +void set_try(char current_try[WORD_LENGHT]) { tries[current_try_id] = current_try; } - // Place correct letters from previous in the current one - if (current_try_id < TRIES_COUNT) { - for (int i = 0; i < WORD_LENGHT; i++) { - if (validations[current_try_id - 1][i] == LETTER_PLACED) - tries[current_try_id][i] = tries[current_try_id - 1][i]; - } - } - break; - } -} +int get_gamemode() { return gamemode; } -//========================== -// PUBLIC -//========================== -void set_gamemode(int menu_gamemode) { gamemode = menu_gamemode; } +char *get_answer() { return chosen_word; } void launch_game() { initialize_game(); diff --git a/wordle/wordle.h b/wordle/wordle.h index 4e5ad9bcd1061f7ad769de4a05499cb1ab535882..871bf274ccdb97dd0673b3e8eac6dcff602633ce 100644 --- a/wordle/wordle.h +++ b/wordle/wordle.h @@ -21,6 +21,67 @@ #define LETTER_WRONG_PLACE 1 #define LETTER_NOT_PRESENT 0 +/** + * @brief Initialize the game + */ +void initialize_game(); + +/** + * @brief Terminate a game + */ +void terminate_game(); + +/** + * @brief Destroy a game + * + */ +void destroy_game(); + +/** + * @brief Restart the game + * + */ +void restart_game(); + +/** + * @brief Condition(s) to lose a game + * + * @return true + * @return false + */ +bool lose_condition(); + +/** + * @brief Condition(s) to win a game + * + * @return true + * @return false + */ +bool win_condition(); + +/** + * @brief Check if the given letter is a lowercase letter only (ASCII code) + * + * @param key + * @return true + * @return false + */ +bool validate_letter(int key); + +/** + * @brief Control the placement of each letter + */ +int *letter_placement_control(); + +/** + * @brief Is a try valid + * + * @param try + * @return true + * @return false + */ +bool validate_guess(char current_try[WORD_LENGHT]); + /** * @brief Set the gamemode * @@ -28,6 +89,36 @@ */ void set_gamemode(int menu_gamemode); +/** + * @brief Set the answer + * + * @warning Should only be used in test procedure or privately + * @param answer + */ +void set_answer(char answer[WORD_LENGHT]); + +/** + * @brief Set the current try + * + * @warning Should only be used in test procedure + * @param current_try + */ +void set_try(char current_try[WORD_LENGHT]); + +/** + * @brief Get the gamemode + * + * @return int + */ +int get_gamemode(); + +/** + * @brief Get the answer + * + * @return + */ +char *get_answer(); + /** * @brief Launch the game *