initial commit
This commit is contained in:
@@ -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.
|
||||||
@@ -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
|
||||||
@@ -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
@@ -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
|
||||||
+358
@@ -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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user