//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 //FILE,printf(),fopen(),fclose(),fgets() #include //assert() #include //rand(),srand(),system() #include //time() #include //strncpy() #include //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; }