initial commit

This commit is contained in:
bePrivate
2023-10-28 19:45:39 +02:00
commit c927e6496d
6 changed files with 512 additions and 0 deletions
Executable
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 mnjx
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Executable
+10
View File
@@ -0,0 +1,10 @@
first:
gcc src/main.c -o main
install:
echo "alias wordle='$(realpath build/main)'" >> ~/.bashrc
echo "WORDLE_PATH='$(realpath build/main)'" >> ~/.bashrc
export WORDLE_PATH
source ~/.bashrc
run:
./build/main
Executable
+22
View File
@@ -0,0 +1,22 @@
# Wordle
Yet another recreation of the game Wordle (now in C)
# Usage
1. Clone the repo
`git clone https://gitlab.com/bePrivate/wordlec`
2. Change into the cloned directory
`cd wordlec`
3. Start the game
`make && make run`
# How to play
After starting, you are prompted to enter a word. When you enter it, you will see it on
the screen. You will see whether each letter is at the correct place or not, or if it
even is in the word in the first place. You have six tries, then you lose and the correct
word is shown to you. If you win, the number of guesses is displayed, along with the
correct word.
Executable
+101
View File
@@ -0,0 +1,101 @@
crane
stove
house
hound
apple
spear
blood
river
ocean
table
chair
phone
bible
cable
trash
juice
paper
stack
queue
graph
earth
gnome
linux
green
black
white
brown
arrow
space
bread
break
drink
board
floor
glass
latex
fever
cough
metro
bingo
cloth
clock
proof
range
brick
shark
ingot
crate
crook
woman
image
timer
coast
plant
stone
horse
mouse
wheel
knife
towel
tower
rover
cover
shirt
video
audio
clone
virus
vodka
sirup
water
plane
plain
photo
radio
berry
shell
guess
paint
screw
frame
place
plank
curve
plate
spoon
mouth
onion
route
issue
start
three
seven
eight
crypt
queen
price
token
night
rebel
crown
Executable
BIN
View File
Binary file not shown.
+358
View File
@@ -0,0 +1,358 @@
/*
Wordle game implementation in the C programming language
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#define RESET "\x1b[0m" // color 0
#define RED "\x1b[31m" // color 1
#define GREEN "\x1b[32m" // color 2
#define YELLOW "\x1b[33m" // color 3
char wordlist_path[1024];
char wordlist[16384][6]; // 2^14
int len_wordlist = 0;
int flag_verbose = 0;
int flag_worldlist = 0;
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" }
};
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;
}
}
/*
prints the help & usage for the user to know what to do
*/
void print_help_and_usage() {
fprintf(stdout,
"Help and usage for Wordle:\n"
"\n"
"Help:\n"
"--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"
"--verbose ............................ be verbose (show what the program is doing aka debug info)\n"
"--help ............................... show this help screen\n"
"\n"
"Usage:\n"
"\n"
"wordle\n"
"=> starts Wordle with the default wordlist\n"
"wordle --wordlist <path_to_wordlist_file>\n"
"=> starts Wordle with a specified wordlist\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();
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 5; j++) {
switch (pf_props[i][j][1]) {
case '0':
printf("| %c ", playfield[i][j]);
break;
case '1':
printf("| " RED "%c " RESET, playfield[i][j]);
break;
case '2':
printf("| " GREEN "%c " RESET, playfield[i][j]);
break;
case '3':
printf("| " YELLOW "%c " RESET, playfield[i][j]);
break;
}
}
printf("|\n");
}
printf("\n");
}
/*
prompt the user for their input
*/
void prompt(char user_input[]) {
printf(">> ");
scanf("%5s", user_input);
}
/*
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 < sizeof(word)/sizeof(word[0]); i++) {
if (word[i] == target) return i;
}
return -1;
}
/*
evaluate the loss
*/
void eval_lose() {
if (turns >= 6) {
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_props(word); // eval correct/incorrect/oop letters
put_word_into_playfield(word);
} else {
clear();
printf("Word %s not in wordlist\n", word);
sleep(2);
}
eval_lose();
}
/*
# 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);
}
/*
pass the arguments
*/
int argparse(int argc, char *argv[]) {
int flag_error = 0;
for (int i = 0; i < argc; i++) {
/*
look for invalid arguments
*/
for (int j = 1; j < argc; j++) {
if (strcmp(argv[j], "--wordlist") != 0 && strcmp(argv[j-1], "--wordlist") != 0 && strcmp(argv[j], "--verbose") != 0 && strcmp(argv[j], "--help") != 0) {
fprintf(stderr, "Invalid argument %s\n", argv[j]);
flag_error = 1;
}
}
/*
print the help & usage
*/
if (strcmp(argv[i], "--help") == 0) {
print_help_and_usage();
return 0;
}
/*
getting the debug flag for debug printing
*/
if (strcmp(argv[i], "--verbose") == 0 && flag_verbose == 0) {
flag_verbose = 1;
}
/*
getting the path to the wordlist
*/
if (strcmp(argv[i], "--wordlist") == 0 && flag_worldlist == 0) {
flag_worldlist = 1;
if (argv[i+1] != NULL) { // if there is an argument present after that, read it as the wordlist path
strcpy(wordlist_path, argv[i+1]);
} else {
fprintf(stderr, "Missing argument after %s\nUsage: %s <path_to_wordlist_file>\n", argv[i], argv[i]);
flag_error = 1;
}
} else if (strcmp(argv[i], "--wordlist") != 0 && flag_worldlist == 0) {
strcpy(wordlist_path, "lib/wordlist");
}
}
if (file_exists(wordlist_path) == 0) {
fprintf(stderr, "File %s not found\n", wordlist_path);
flag_error = 1;
}
if (flag_verbose == 1) printf("wordlist_path: %s\n", wordlist_path);
return flag_error;
}
/*
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);
}
int main(int argc, char *argv[]) {
// pass the arguments
if (argparse(argc, argv) == 1) return 1;
// prerequisite 1
get_random_word(word_to_guess, wordlist_path);
// steps
while (win == 0 && lose == 0) {
game();
if (quit == 1) return 2;
}
// print winning message
show_win_lose_message();
return 0;
}