update code organization

This commit is contained in:
bePrivate
2023-10-31 22:41:48 +01:00
parent f5918ba52d
commit d5b863b6ca
2 changed files with 328 additions and 272 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ Proven working on Linux ONLY. Contributions welcome!
`make && make install`
4. Run the game
`wordlec` (`wordlec --help` for help)
`wordlec` (`wordlec -h/--help` for help)
# How to play
+327 -271
View File
@@ -3,7 +3,8 @@
*/
/* TODO:
* maybe implement user-specified colors for theming
* implement user-specified colors for theming
* therefore renaming the colors from smt like INCORRECT to INCORRECT etc.
*/
#include <stdio.h>
@@ -12,18 +13,32 @@
#include <unistd.h>
#include <time.h>
char *RESET = "\x1b[0m";
char *RED = "\x1b[31m";
char *GREEN = "\x1b[32m";
char *YELLOW = "\x1b[33m";
char *GRAY = "\x1b[7m";
char *RESET = "\x1b[0m";
char *INCORRECT = "\x1b[31m";
char *CORRECT = "\x1b[32m";
char *OUTOFPLACE = "\x1b[33m";
char *ASCII = "\x1b[7m";
char wordlist_path[1024];
char wordlist[16384][6]; // 2^14
int len_wordlist = 0;
int flag_verbose = 0;
int flag_worldlist = 0;
int flag_light_theme = 0;
int flag_verbose = 0;
int flag_worldlist = 0;
int flag_light_theme = 0;
int len_wordlist = 0;
int lose = 0;
char pf_props[6][5][2] = {
// <char> <colorcode>
// letter 0, 1, 2, 3 or 4 where
// 0 (RESET) is not yet guessed
// 1 (INCORRECT) default red, is incorrect,
// 2 (CORRECT) default green, is correct and
// 3 (OUTOFPLACE) default yellow, is out-of-place
{ " 0", " 0", " 0", " 0", " 0" },
{ " 0", " 0", " 0", " 0", " 0" },
{ " 0", " 0", " 0", " 0", " 0" },
{ " 0", " 0", " 0", " 0", " 0" },
{ " 0", " 0", " 0", " 0", " 0" },
{ " 0", " 0", " 0", " 0", " 0" }
};
char playfield[6][5] = {
{ ' ', ' ', ' ', ' ', ' ' },
{ ' ', ' ', ' ', ' ', ' ' },
@@ -32,247 +47,41 @@ char playfield[6][5] = {
{ ' ', ' ', ' ', ' ', ' ' },
{ ' ', ' ', ' ', ' ', ' ' }
};
char pf_props[6][5][2] = {
// <char> <colorcode>
// letter 0, 1, 2 or 3 where
// 0 (RESET) is not yet guessed
// 1 (RED) is out-of-place,
// 2 (GREEN) is correct and
// 3 (YELLOW) is incorrect
{ " 0", " 0", " 0", " 0", " 0" },
{ " 0", " 0", " 0", " 0", " 0" },
{ " 0", " 0", " 0", " 0", " 0" },
{ " 0", " 0", " 0", " 0", " 0" },
{ " 0", " 0", " 0", " 0", " 0" },
{ " 0", " 0", " 0", " 0", " 0" }
};
int quit = 0;
int turns = 0;
int win = 0;
char wordlist_path[1024];
char wordlist[16384][6]; // 2^14
char word_to_guess[5];
int turns = 0;
int win = 0;
int lose = 0;
int quit = 0;
/*
tests if a file exists
return 0 - yes
return 1 - no
*/
int file_exists(char path[]) {
if (access(path, F_OK) != 0) {
return 0;
} else {
return 1;
}
}
*
*
* END OF GLOBAL VARIABLES
* =======================
* START OF FUNCTIONS
*
*
*/
/*
prints the help & usage for the user to know what to do
*/
void print_help_and_usage() {
fprintf(stdout,
"Help and usage for wordlec:\n"
"\n"
"Help:\n"
"-w/--wordlist <path_to_wordlist_file> ........... specify a custom wordlist\n"
" RULES: five characters on each line (no empty lines),\n"
" each new line is separated by '\\n' (Enter/Return)\n"
"-l/--light-theme ................................ activate light theme\n"
"-v/--verbose .................................... be verbose (show what the program is doing aka debug info)\n"
"-h/--help ....................................... show this help screen\n"
);
}
/*
gets a random word from the given wordlist
*/
void get_random_word(char word_to_guess[], char wordlist_path[]) {
FILE* wordlist_file = fopen(wordlist_path, "r");
char ch;
int i = 0;
char temp_word[6];
while ((ch = fgetc(wordlist_file)) != EOF) {
if (ch != '\n') {
temp_word[i] = ch;
i++;
} else {
temp_word[i] = '\0';
i = 0;
strcpy(wordlist[len_wordlist], temp_word);
len_wordlist++;
}
}
srand(time(NULL));
strcpy(word_to_guess, wordlist[rand() % len_wordlist]);
}
/*
clears the console/screen
*/
void clear() {
printf("\e[1;1H\e[2J");
}
/*
prints the current state of the game
shows
correct letters
incorrect letters
and out-of-place letters
also the previous attempts
*/
void show() {
clear();
printf("%s╔═══╦═══╦═══╦═══╦═══╗%s\n", GRAY, RESET);
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 5; j++) {
switch (pf_props[i][j][1]) {
case '0':
printf("%s║ %c ", GRAY, playfield[i][j]);
break;
case '1':
printf("%s║%s %c %s", GRAY, RED, playfield[i][j], RESET);
break;
case '2':
printf("%s║%s %c %s", GRAY, GREEN, playfield[i][j], RESET);
break;
case '3':
printf("%s║%s %c %s", GRAY, YELLOW, playfield[i][j], RESET);
break;
}
}
printf("%s║%s\n", GRAY, RESET);
if (i < 5) printf("%s╠═══╬═══╬═══╬═══╬═══╣%s\n", GRAY, RESET);
}
printf("%s╚═══╩═══╩═══╩═══╩═══╝%s\n", GRAY, RESET);
}
/*
prompt the user for their input
*/
void prompt(char user_input[]) {
int c;
printf(">> ");
scanf("%5s", user_input);
while ((c = getchar()) != '\n' && c != EOF);
}
/*
linear search helper function for searching within the wordlist
*/
int search_wordlist(char wordlist[][6], char target[]) {
for (int i = 0; i < len_wordlist; i++) {
if (strcmp(wordlist[i], target) == 0) return i;
}
return -1;
}
/*
helper function for searching within a string
*/
int search_word(char word[], char target) {
for (int i = 0; i < strlen(word); i++) {
if (word[i] == target) return i;
}
return -1;
}
/*
evaluate the loss
*/
void eval_lose() {
if (turns >= 5 && win == 0) {
lose = 1;
}
}
/*
evaluate the win
*/
void eval_win(int i) {
if (strcmp(wordlist[i], word_to_guess) == 0) {
win = 1;
}
}
/*
helper function for evaluating the properties of a word
*/
void eval_props(char word[]) {
for (int i = 0; i < 5; i++) {
if (word_to_guess[i] == word[i]) {
pf_props[turns][i][0] = word[i];
pf_props[turns][i][1] = '2';
} else if (search_word(word_to_guess, word[i]) != -1 && word_to_guess[i] != word[i]) {
pf_props[turns][i][0] = word[i];
pf_props[turns][i][1] = '3';
} else if (search_word(word_to_guess, word[i]) == -1) {
pf_props[turns][i][0] = word[i];
pf_props[turns][i][1] = '1';
}
}
}
/*
put a valid word into the playfield
*/
void put_word_into_playfield(char word[]) {
strcpy(playfield[turns], word);
turns++;
// resetting the rest of the playfield
for (int i = turns; i < turns + (6 - turns); i++) {
strcpy(playfield[i], " ");
}
}
/*
evaluate the word
*/
void eval_word(char word[]) {
printf("\n%d\n", search_wordlist(wordlist, word));
if (search_wordlist(wordlist, word) != -1) {
eval_win(search_wordlist(wordlist, word));
eval_lose();
eval_props(word); // eval correct/incorrect/oop letters
put_word_into_playfield(word);
} else {
clear();
printf("Word %s not in wordlist\n", word);
sleep(2);
}
}
/*
# prerequisites:
& 1 choose a random word from a wordlist
# algo steps:
& 1 clear the screen
& 2 display the current state of the playfield
& 3 prompt the user to enter a word
& 4 evaluate the word
& 5 print the word on the screen with the corresponding parameters at each letter (right position, wrong position, not in word)
& 6.1 if the user entered the right word, show a winning message and exit
& 6.2 if the user has tried 6 times already, show a losing message, the word and exit
*/
void game() {
// step 1 & 2
show();
// step 3
char user_input[5];
prompt(user_input);
// implemented a quit function
if (user_input[0] == 'q') quit = 1;
// step 4 & 5
eval_word(user_input);
}
int argparse(int argc, char *argv[]);
void clear();
void eval_lose();
void eval_props(char word[]);
void eval_win(int i);
void eval_word(char word[]);
int file_exists(char path[]);
void game();
void get_random_word(char word_to_guess[], char wordlist_path[]);
int main(int argc, char *argv[]);
void print_help_and_usage();
void prompt(char user_input[]);
void put_word_into_playfield(char word[]);
int search_word(char word[], char target);
int search_wordlist(char wordlist[][6], char target[]);
void set_theme();
void show();
void show_win_lose_message();
/*
pass the arguments
@@ -283,9 +92,22 @@ int argparse(int argc, char *argv[]) {
/*
look for invalid arguments
*/
if (strcmp(argv[i], argv[0]) != 0 && strcmp(argv[i], "--wordlist") != 0 && strcmp(argv[i-1], "--wordlist") != 0 && strcmp(argv[i], "--verbose") != 0 && strcmp(argv[i], "--help") != 0 && strcmp(argv[i], "-h") != 0 && strcmp(argv[i], "-w") != 0 && strcmp(argv[i-1], "-w") != 0 && strcmp(argv[i], "-v") != 0 && strcmp(argv[i], "-l") != 0 && strcmp(argv[i], "--light-theme") != 0) {
fprintf(stderr, "Invalid argument %s\n", argv[i]);
flag_error = 1;
if (strcmp(argv[i], argv[0]) != 0 &&
strcmp(argv[i], "-h") != 0 &&
strcmp(argv[i], "--help") != 0 &&
strcmp(argv[i], "-l") != 0 &&
strcmp(argv[i], "--light-theme") != 0 &&
strcmp(argv[i], "-t") != 0 &&
strcmp(argv[i], "--theme") != 0
strcmp(argv[i], "-v") != 0 &&
strcmp(argv[i], "--verbose") != 0 &&
strcmp(argv[i], "-w") != 0 &&
strcmp(argv[i-1], "-w") != 0 &&
strcmp(argv[i], "--wordlist") != 0 &&
strcmp(argv[i-1], "--wordlist") != 0 &&
) {
fprintf(stderr, "Invalid argument %s\n", argv[i]);
flag_error = 1;
}
/*
@@ -363,33 +185,134 @@ int argparse(int argc, char *argv[]) {
}
/*
shows the message after the game ends
clears the console/screen
*/
void show_win_lose_message() {
show();
if (win == 1 && lose == 0) fprintf(stdout, "You won! It took you %d guesses. The word was %s.\n", turns, word_to_guess);
if (win == 0 && lose == 1) fprintf(stdout, "You lost. :( The word was %s.\n", word_to_guess);
void clear() {
printf("\e[1;1H\e[2J");
}
/*
set the theme (light/dark)
evaluate the loss
*/
void set_theme() {
if (flag_light_theme == 1) {
RESET = "\x1b[0;0m";
RED = "\x1b[0;41m";
GREEN = "\x1b[0;42m";
YELLOW = "\x1b[0;43m";
GRAY = "\x1b[0;7m";
} else {
RESET = "\x1b[37;0m";
RED = "\x1b[37;41m";
GREEN = "\x1b[37;42m";
YELLOW = "\x1b[37;43m";
GRAY = "\x1b[37;90m";
void eval_lose() {
if (turns >= 5 && win == 0) {
lose = 1;
}
}
/*
helper function for evaluating the properties of a word
*/
void eval_props(char word[]) {
for (int i = 0; i < 5; i++) {
if (word_to_guess[i] == word[i]) {
pf_props[turns][i][0] = word[i];
pf_props[turns][i][1] = '2';
} else if (search_word(word_to_guess, word[i]) != -1 && word_to_guess[i] != word[i]) {
pf_props[turns][i][0] = word[i];
pf_props[turns][i][1] = '3';
} else if (search_word(word_to_guess, word[i]) == -1) {
pf_props[turns][i][0] = word[i];
pf_props[turns][i][1] = '1';
}
}
}
/*
evaluate the win
*/
void eval_win(int i) {
if (strcmp(wordlist[i], word_to_guess) == 0) {
win = 1;
}
}
/*
evaluate the word
*/
void eval_word(char word[]) {
printf("\n%d\n", search_wordlist(wordlist, word));
if (search_wordlist(wordlist, word) != -1) {
eval_win(search_wordlist(wordlist, word));
eval_lose();
eval_props(word); // eval correct/incorrect/oop letters
put_word_into_playfield(word);
} else {
clear();
printf("Word %s not in wordlist\n", word);
sleep(2);
}
}
/*
tests if a file exists
return 0 - yes
return 1 - no
*/
int file_exists(char path[]) {
if (access(path, F_OK) != 0) {
return 0;
} else {
return 1;
}
}
/*
# prerequisites:
& 1 choose a random word from a wordlist
# algo steps:
& 1 clear the screen
& 2 display the current state of the playfield
& 3 prompt the user to enter a word
& 4 evaluate the word
& 5 print the word on the screen with the corresponding parameters at each letter (right position, wrong position, not in word)
& 6.1 if the user entered the right word, show a winning message and exit
& 6.2 if the user has tried 6 times already, show a losing message, the word and exit
*/
void game() {
// step 1 & 2
show();
// step 3
char user_input[5];
prompt(user_input);
// implemented a quit function
if (user_input[0] == 'q') quit = 1;
// step 4 & 5
eval_word(user_input);
}
/*
gets a random word from the given wordlist
*/
void get_random_word(char word_to_guess[], char wordlist_path[]) {
FILE* wordlist_file = fopen(wordlist_path, "r");
char ch;
int i = 0;
char temp_word[6];
while ((ch = fgetc(wordlist_file)) != EOF) {
if (ch != '\n') {
temp_word[i] = ch;
i++;
} else {
temp_word[i] = '\0';
i = 0;
strcpy(wordlist[len_wordlist], temp_word);
len_wordlist++;
}
}
srand(time(NULL));
strcpy(word_to_guess, wordlist[rand() % len_wordlist]);
}
/*
driver code
*/
int main(int argc, char *argv[]) {
// pass the arguments
int args = argparse(argc, argv);
@@ -416,4 +339,137 @@ int main(int argc, char *argv[]) {
show_win_lose_message();
return 0;
}
/*
prints the help & usage for the user to know what to do
*/
void print_help_and_usage() {
fprintf(stdout,
"Help and usage for wordlec:\n"
"\n"
"Help:\n"
"-w/--wordlist <path_to_wordlist_file>\n"
" specify a custom wordlist\n"
" RULES: five characters on each line (no empty lines),\n"
" each new line is separated by '\\n' (Enter/Return)\n"
"-t/--theme <correct_color> <incorrect_color> <out_of_place_color> <ascii_art_color>\n" // TODO: make work
" specify the colors in which the playfield will be visible\n"
" RULES: choose the color from this list:\n"
" [ black, red, green, yellow, blue, magenta, cyan, white ]\n"
" append ':b' (background color) or ':f' (foreground color)\n"
" add a ';' between the background and foreground colors\n"
" EXAMPLE: '-t green:f;black:b cyan:b;white:f red:b;black:f white:b;black:f'\n"
"-l/--light-theme\n"
" activate light theme\n"
"-v/--verbose\n"
" be verbose (show what the program is doing aka debug info)\n"
"-h/--help\n"
" show this help screen\n"
);
}
/*
prompt the user for their input
*/
void prompt(char user_input[]) {
int c;
printf(">> ");
scanf("%5s", user_input);
while ((c = getchar()) != '\n' && c != EOF);
}
/*
put a valid word into the playfield
*/
void put_word_into_playfield(char word[]) {
strcpy(playfield[turns], word);
turns++;
// resetting the rest of the playfield
for (int i = turns; i < turns + (6 - turns); i++) {
strcpy(playfield[i], " ");
}
}
/*
helper function for searching within a string
*/
int search_word(char word[], char target) {
for (int i = 0; i < strlen(word); i++) {
if (word[i] == target) return i;
}
return -1;
}
/*
linear search helper function for searching within the wordlist
*/
int search_wordlist(char wordlist[][6], char target[]) {
for (int i = 0; i < len_wordlist; i++) {
if (strcmp(wordlist[i], target) == 0) return i;
}
return -1;
}
/*
set the theme (light/dark)
*/
void set_theme() {
if (flag_light_theme == 1) {
RESET = "\x1b[0;0m";
INCORRECT = "\x1b[0;41m";
CORRECT = "\x1b[0;42m";
OUTOFPLACE = "\x1b[0;43m";
ASCII = "\x1b[0;7m";
} else {
RESET = "\x1b[37;0m";
INCORRECT = "\x1b[37;41m";
CORRECT = "\x1b[37;42m";
OUTOFPLACE = "\x1b[37;43m";
ASCII = "\x1b[37;90m";
}
}
/*
prints the current state of the game
shows
correct letters
incorrect letters
and out-of-place letters
also the previous attempts
*/
void show() {
clear();
printf("%s╔═══╦═══╦═══╦═══╦═══╗%s\n", ASCII, RESET);
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 5; j++) {
switch (pf_props[i][j][1]) {
case '0':
printf("%s║ %c ", ASCII, playfield[i][j]);
break;
case '1':
printf("%s║%s %c %s", ASCII, INCORRECT, playfield[i][j], RESET);
break;
case '2':
printf("%s║%s %c %s", ASCII, CORRECT, playfield[i][j], RESET);
break;
case '3':
printf("%s║%s %c %s", ASCII, OUTOFPLACE, playfield[i][j], RESET);
break;
}
}
printf("%s║%s\n", ASCII, RESET);
if (i < 5) printf("%s╠═══╬═══╬═══╬═══╬═══╣%s\n", ASCII, RESET);
}
printf("%s╚═══╩═══╩═══╩═══╩═══╝%s\n", ASCII, RESET);
}
/*
shows the message after the game ends
*/
void show_win_lose_message() {
show();
if (win == 1 && lose == 0) fprintf(stdout, "You won! It took you %d guesses. The word was %s.\n", turns, word_to_guess);
if (win == 0 && lose == 1) fprintf(stdout, "You lost. :( The word was %s.\n", word_to_guess);
}