summaryrefslogtreecommitdiff
path: root/wordle.c
blob: c98ffdee269b0b4d9d33d8bf519917742681dd09 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
//TODO: Quordle mode, multiple different length words
/** Making my own version/clone of the popular "wordle" game.   hello
 * This is more of a way to help me solidfy my knowledge of 
 * programming and the C programming language than it is to
 * actually play the game, but hopefully in the end this game
 * pulls it weight in entertainment value.
 */
#include <stdio.h>  //FILE,printf(),fopen(),fclose(),fgets()
#include <assert.h> //assert()
#include <stdlib.h> //rand(),srand(),system()
#include <time.h>   //time()
#include <string.h> //strncpy()
#include <inttypes.h> //strtoimax(), int8_t


#define LARGEDICT   8939
#define WORDLEN 5
//#define DEBUG
#ifdef DEBUG
#define SMALLDICT   3
static const char* SMALLFILE = "test_file"; 
#endif
#ifndef DEBUG
#define SMALLDICT   3858
static const char* SMALLFILE = "small_dict";
#endif

static const char* LARGEFILE = "large_dict";
static const char* GAMESPLAYED = "games_played";
static const char* TOTALWINS = "total_wins";
static const char* WINSTREAK = "win_streak";

int main(void)
{
    //Open file and make sure it exists
    FILE* larger_dict_fptr = fopen(LARGEFILE, "r");
    FILE* smaller_dict_fptr = fopen(SMALLFILE, "r");
    assert(larger_dict_fptr != NULL && "File pointer returned NULL, make sure file exists and is spelled correctly");
    assert(smaller_dict_fptr != NULL && "File pointer returned NULL, make sure file exists and is spelled correctly");


    //Get words from both game (SMALL) and user (LARGE) dictionary and store them in two, two dimensional arrays, 
    //then strip the newline character, when done close the file
    char larger_word_array[LARGEDICT][WORDLEN + 2]; //plus 2 to account for newline character and null character added by fgets
    char smaller_word_array[SMALLDICT][WORDLEN + 2];

    for (int i = 0; i < LARGEDICT; ++i) {
        if (fgets(larger_word_array[i], WORDLEN + 2, larger_dict_fptr) != NULL) { // added 2 to WORDLEN because fgets starts where it left off before
            assert(larger_word_array[i][WORDLEN+1] == '\0' && "word_array is not holding the characters that it is supposed to");
            larger_word_array[i][WORDLEN] = '\0';
        }
    }
    fclose(larger_dict_fptr); 

    for (int i = 0; i < SMALLDICT; ++i) {
        if (fgets(smaller_word_array[i], WORDLEN + 2, smaller_dict_fptr) != NULL) { // added 2 to WORDLEN because fgets starts where it left off before
            assert(smaller_word_array[i][WORDLEN+1] == '\0' && "word_array is not holding the characters that it is supposed to");
            smaller_word_array[i][WORDLEN] = '\0';
        }
    }
    fclose(smaller_dict_fptr); 


    //Get random number then store the word in that position in the array to be used for the game
    char chosen_word[WORDLEN + 1];
    srand(time(0));
    int random_num = rand() % SMALLDICT;
    strncpy(chosen_word, smaller_word_array[random_num], WORDLEN);
    
    //Finds the number of duplicate letters in word and stores in corresponding array at same location
    short int chosen_duplicates[5] = {0,0,0,0,0};
        for (int i = WORDLEN - 1; i > 0; --i) {
            for (int j = i - 1; j >= 0; --j) {
                if (chosen_word[i] == chosen_word[j]) {
                    chosen_duplicates[i]++;
                }      
           } 
        }

    //Prepare for user input and let them know they can start playing
    system("clear");
    printf("You can now start making your guesses below.\n\n");

#ifdef DEBUG
        printf("\n\nword is: %s\n\n", chosen_word);
#endif


    //Play game until they win or lose
    int8_t tries = 0, count = 0, is_a_word = 0, guess_duplicates[5] = {0,0,0,0,0};  //used int8_t intead of using char to store a very small # for clarity
    int number_of_letters = 0; 
    char guess_word[WORDLEN+1];

    while (count != 5 && tries != 6) {
A:
        count = 0;
        is_a_word = 0;
        number_of_letters = 0;

        fflush(stdin); //Undefined behavior, but it fixed my problem (maybe while getchar or something later, when less lazy)
        printf("%d: ", tries + 1);
        scanf("%6s%n",guess_word, &number_of_letters);

        //check length of input to make sure it is good
        if (number_of_letters != (WORDLEN)) {
            printf("Word is not five letters in length. Please try again.\n");
            goto A;
        }

        for (int i = 0; i < LARGEDICT; ++i) {
           if (!strcmp(guess_word, larger_word_array[i])) {
              is_a_word = 1; 
            }
        } 

        if (!is_a_word) {
            printf("Not a valid word, try again.\n");
            goto A;
        }


        //Finds the number of duplicate letters in word and stores in corresponding array at same location
        for (int i = WORDLEN - 1; i > 0; --i) {
            for (int j = i - 1; j >= 0; --j) {
                if (guess_word[i] == guess_word[j]) {
                    guess_duplicates[i]++;
                }      
           } 
        }
        
        printf("   ");

        //prints the corresponding symbol depending on if the letter is correct, in the wrong spot or neither
        for (int i = 0; i < WORDLEN; i++) {
            for (int j = 0; j < WORDLEN; j++) {
                if ( guess_word[i] == chosen_word[i] ) {
                    printf("$");
                    ++count;
                    break;
                } else if ( guess_word[i] == chosen_word[j] ) {
                        if ( !guess_duplicates[i] && guess_word[j] != chosen_word[j]) {
                            printf("*");
                            break;
                        } else {
                            --guess_duplicates[i];
                        }
                 } else if ( j == (WORDLEN - 1) ) {
                        printf("_");
                 }
            }
        }

        ++tries;
        printf("\n\n\n");
    }
    
    //open three files, that hold information about the total games played, the total wins, and the current win streak and make sure they opened correctly
    FILE* win_streak_fptr = fopen(WINSTREAK, "r+");
    FILE* total_wins_fptr = fopen(TOTALWINS, "r+");
    FILE* total_games_fptr = fopen(GAMESPLAYED, "r+");
    assert(win_streak_fptr != NULL && "File pointer returned NULL, make sure file exists and is spelled correctly");
    assert(total_wins_fptr != NULL && "File pointer returned NULL, make sure file exists and is spelled correctly");
    assert(total_games_fptr != NULL && "File pointer returned NULL, make sure file exists and is spelled correctly");


    //increment total in total_games by one
    //if you won, print so, add one to current win streak, and total games won
    //if you lost, reset win streak total to 0 
    //calculate win percentage from total wins divided by total games times 100
    //total games, total wins, win streak, win percentage (double)
    char file_strings[3][11];
    long int file_ints[3];
    double win_percentage;
    char* endptr;
    enum whichFIle {winStreak = 0, totalWins = 1, totalGames = 2};

    fscanf(win_streak_fptr, "%10s", file_strings[winStreak]);
    fscanf(total_wins_fptr, "%10s", file_strings[totalWins]);
    fscanf(total_games_fptr, "%10s", file_strings[totalGames]);

    file_ints[winStreak] = strtoimax(file_strings[winStreak],&endptr,10); 
    file_ints[totalWins] = strtoimax(file_strings[totalWins],&endptr,10); 
    file_ints[totalGames] = strtoimax(file_strings[totalGames],&endptr,10); 


    file_ints[totalGames] += 1;

    if (count == 5) {
        file_ints[winStreak] += 1;
        file_ints[totalWins] += 1;
        printf("You won!\n");
    } else {
        printf("You Lost!\n");
        printf("The word was: %s.\n",chosen_word);
        file_ints[winStreak] = 0;
    }

    win_percentage = ( (double) file_ints[totalWins] / (double) file_ints[totalGames] ) * 100;

    printf("Your winnning streak is: %ld\nYour winning percentage is: %.2lf\n", file_ints[winStreak], win_percentage);

    //Return all the values back to their corresponding files and close up shop
    fseek(win_streak_fptr, 0, SEEK_SET);
    fseek(total_games_fptr, 0, SEEK_SET);
    fseek(total_wins_fptr, 0, SEEK_SET); 

    fprintf(win_streak_fptr, "%ld\n", file_ints[winStreak]);
    fprintf(total_games_fptr, "%ld\n", file_ints[totalGames]);
    fprintf(total_wins_fptr, "%ld\n", file_ints[totalWins]);

    fflush(win_streak_fptr);
    fflush(total_games_fptr);
    fflush(total_wins_fptr);

    fclose(win_streak_fptr);
    fclose(total_games_fptr);
    fclose(total_wins_fptr);
    return 0;
}