diff --git a/ui/ui.c b/ui/ui.c index 1ac6ac49827fbe6d2178ee82a2286316987f2a8c..4769aa671876a9565e7dfc8a129f422c1455e8f4 100644 --- a/ui/ui.c +++ b/ui/ui.c @@ -1,9 +1,9 @@ #include "ui.h" #define MENU_MAX 4 -#define TITLE_Y_OFFSET 5 -#define MENU_CHOICE_Y_OFFSET 23 -#define GAMEBOARD_Y_OFFSET 10 +#define TITLE_Y_OFFSET 2 +#define MENU_CHOICE_Y_OFFSET 20 +#define GAMEBOARD_Y_OFFSET 13 //========================== // PRIVATE @@ -12,6 +12,26 @@ WINDOW *ui_window = NULL; WINDOW *help = NULL; +char main_title[8][64] = {"$$\\ $$\\ $$$$$$\\ $$$$$$$\\ $$$$$$$\\ $$\\ $$$$$$$$\\ ", + "$$ | $\\ $$ |$$ __$$\\ $$ __$$\\ $$ __$$\\ $$ | $$ _____|", + "$$ |$$$\\ $$ |$$ / $$ |$$ | $$ |$$ | $$ |$$ | $$ | ", + "$$ $$ $$\\$$ |$$ | $$ |$$$$$$$ |$$ | $$ |$$ | $$$$$\\ ", + "$$$$ _$$$$ |$$ | $$ |$$ __$$< $$ | $$ |$$ | $$ __| ", + "$$$ / \\$$$ |$$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ | ", + "$$ / \\$$ | $$$$$$ |$$ | $$ |$$$$$$$ |$$$$$$$$\\ $$$$$$$$\\ ", + "\\__/ \\__| \\______/ \\__| \\__|\\_______/ \\________|\\________|"}; +char mode_solo_title[8][40] = {" $$$$$$\\ $$$$$$\\ $$\\ $$$$$$\\ ", "$$ __$$\\ $$ __$$\\ $$ | $$ __$$\\ ", + "$$ / \\__|$$ / $$ |$$ | $$ / $$ |", "\\$$$$$$\\ $$ | $$ |$$ | $$ | $$ |", + " \\____$$\\ $$ | $$ |$$ | $$ | $$ |", "$$\\ $$ |$$ | $$ |$$ | $$ | $$ |", + "\\$$$$$$ | $$$$$$ |$$$$$$$$\\ $$$$$$ |", " \\______/ \\______/ \\________|\\______/ "}; +char mode_1v1_title[8][54] = { + " $$\\ $$\\ $$\\ $$\\", "$$$$ | $$ | $$ | $$$$ |", + "\\_$$ | $$ | $$ | $$$$$$$\\ \\_$$ |", " $$ | \\$$\\ $$ |$$ _____| $$ |", + " $$ | \\$$\\$$ / \\$$$$$$\\ $$ |", " $$ | \\$$$ / \\____$$\\ $$ |", + " $$$$$$\\ \\$ / $$$$$$$ | $$$$$$\\", " \\______| \\_/ \\_______/ \\______|"}; +char mode_computer_title[8][21] = {"$$$$$$\\ $$$$$$\\ ", "\\_$$ _|$$ __$$\\ ", " $$ | $$ / $$ |", " $$ | $$$$$$$$ |", + " $$ | $$ __$$ |", " $$ | $$ | $$ |", "$$$$$$\\ $$ | $$ |", "\\______|\\__| \\__|"}; + /** * @brief Set the color scheme of the programm * @@ -75,6 +95,28 @@ void hide_help() { //========================== void printw_center(char *foo, int line) { mvaddstr(line, TERM_MID_COLS - (strlen(foo) / 2), foo); } +void draw_title(int id) { + for (int i = 0; i < TITLES_LINE_COUNT; i++) { + switch (id) { + case MAIN_TITLE_ID: + printw_center(main_title[i], i + TITLE_Y_OFFSET); + break; + + case SOLO_TITLE_ID: + printw_center(mode_solo_title[i], i + TITLE_Y_OFFSET); + break; + + case ONE_V_ONE_TITLE_ID: + printw_center(mode_1v1_title[i], i + TITLE_Y_OFFSET); + break; + + case COMPUTER_TITLE_ID: + printw_center(mode_computer_title[i], i + TITLE_Y_OFFSET); + break; + } + } +} + bool init_term() { ui_window = initscr(); cbreak(); @@ -108,20 +150,9 @@ void cleanup_term() { int show_menu() { hide_help(); - char title[8][64] = {"$$\\ $$\\ $$$$$$\\ $$$$$$$\\ $$$$$$$\\ $$\\ $$$$$$$$\\ ", - "$$ | $\\ $$ |$$ __$$\\ $$ __$$\\ $$ __$$\\ $$ | $$ _____|", - "$$ |$$$\\ $$ |$$ / $$ |$$ | $$ |$$ | $$ |$$ | $$ | ", - "$$ $$ $$\\$$ |$$ | $$ |$$$$$$$ |$$ | $$ |$$ | $$$$$\\ ", - "$$$$ _$$$$ |$$ | $$ |$$ __$$< $$ | $$ |$$ | $$ __| ", - "$$$ / \\$$$ |$$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ | ", - "$$ / \\$$ | $$$$$$ |$$ | $$ |$$$$$$$ |$$$$$$$$\\ $$$$$$$$\\ ", - "\\__/ \\__| \\______/ \\__| \\__|\\_______/ \\________|\\________|"}; - // Title print - if (!window_too_small()) { - for (int i = 0; i < 8; i++) - printw_center(title[i], i + TITLE_Y_OFFSET); - } + if (!window_too_small()) + draw_title(MAIN_TITLE_ID); // Menu print attron(COLOR_PAIR(GREEN_PAIR)); diff --git a/ui/ui.h b/ui/ui.h index 159238442c4f502012845c269c53ef36f6ee64e2..72dc2d9b801aa50e833124eb7d772d4fb0c8c1e9 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -23,6 +23,15 @@ #define MENU_COMPUTER 2 #define MENU_QUIT 3 +// Title lengths +#define TITLES_LINE_COUNT 8 + +// Title IDs +#define MAIN_TITLE_ID 0 +#define SOLO_TITLE_ID 1 +#define ONE_V_ONE_TITLE_ID 2 +#define COMPUTER_TITLE_ID 3 + // Control key handler #define ctrl(x) ((x)&0x1f) @@ -40,6 +49,13 @@ */ void printw_center(char *foo, int line); +/** + * @brief Print a big title + * + * @param id + */ +void draw_title(int id); + /** * @brief Initialize the terminal * diff --git a/wordle/wordle.c b/wordle/wordle.c index 4baccd713d7ed108e022f6520b10d280ad7d8b04..192f6c812638a5b51d924e159858d984fb5a0001 100644 --- a/wordle/wordle.c +++ b/wordle/wordle.c @@ -35,9 +35,13 @@ void initialize_game() { /** * @brief Terminate a game */ -void terminate_game() { - _game_finished = true; +void terminate_game() { _game_finished = true; } +/** + * @brief Destroy a game + * + */ +void destroy_game() { for (int i = 0; i < TRIES_COUNT; i++) { free(tries[i]); free(validations[i]); @@ -47,6 +51,22 @@ void terminate_game() { free(validations); } +/** + * @brief Restart the game + * + */ +void restart_game() { + current_try_id = 0; + current_try_letter_id = 0; + + for (int i = 0; i < TRIES_COUNT; i++) { + for (int j = 0; j < WORD_LENGHT; j++) { + validations[i][j] = 0; + tries[i][j] = '\0'; + } + } +} + /** * @brief Condition(s) to lose a game * @@ -55,21 +75,36 @@ void terminate_game() { */ 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) + return false; + } + + return true; +} + /** * @brief Render the game for the selected gamemode */ void render_game() { switch (gamemode) { case GAMEMODE_SOLO: - printw_center("Solo", 5); + draw_title(SOLO_TITLE_ID); break; case GAMEMODE_1_V_1: - printw_center("Player 1", 5); + draw_title(ONE_V_ONE_TITLE_ID); break; case GAMEMODE_COMPUTER: - printw_center("Computer assisted", 5); + draw_title(COMPUTER_TITLE_ID); break; } @@ -89,11 +124,27 @@ bool validate_letter(int key) { return (islower(key) || isupper(key)); } * @brief Validate the last guess */ int *validate_guess(char answer[WORD_LENGHT], char try[WORD_LENGHT]) { - int a[WORD_LENGHT] = {0, 2, 0, 1, 0}; int *validation = calloc(WORD_LENGHT, sizeof(int)); + char cpy[WORD_LENGHT + 1]; + strcpy(cpy, answer); + + for (int i = 0; i < WORD_LENGHT; i++) { + if (strchr(cpy, try[i]) == NULL) + continue; - for (int i = 0; i < WORD_LENGHT; i++) - validation[i] = a[i]; + if (try[i] == answer[i]) { + validation[i] = LETTER_PLACED; + cpy[i] = ' '; + continue; + } + + char *addr; + if ((addr = strchr(answer, try[i])) != NULL) { + validation[i] = LETTER_WRONG_PLACE; + cpy[(int)(addr - answer)] = ' '; // Get the index of the found char + continue; + } + } return validation; } @@ -137,15 +188,16 @@ void launch_game() { initialize_game(); while (!game_finished()) { + // Render + render_game(); + // Guard clause - if (lose_condition()) { - terminate_game(); + if (win_condition() || lose_condition()) { + restart_game(); + handle_controls(getch()); continue; } - // Render - render_game(); - // Key handling // || Need to check letter by letter every time to be able to continue using // || shortcut keys like Ctrl+h during a guess. @@ -168,6 +220,8 @@ void launch_game() { handle_controls(key); refresh(); } + + destroy_game(); } bool game_finished() { return _game_finished; } \ No newline at end of file diff --git a/wordle/wordle.h b/wordle/wordle.h index 40167569623de27a47a60675688662f47da4dbd6..5909314608958a0a5eefa3facca74a99be00d671 100644 --- a/wordle/wordle.h +++ b/wordle/wordle.h @@ -15,6 +15,11 @@ #define TRIES_COUNT 6 #define WORD_LENGHT 5 +// Try validation values +#define LETTER_PLACED 2 +#define LETTER_WRONG_PLACE 1 +#define LETTER_NOT_PRESENT 0 + /** * @brief Set the gamemode *