From f233fbf7e1824aff9ea556d03556517792036d81 Mon Sep 17 00:00:00 2001 From: D2A62006 Date: Thu, 30 Oct 2025 16:07:28 +0100 Subject: [PATCH] Implement word placement logic and file reading functionality for word salad game --- Start_Linux/game.c | 151 ++++++++++++++++++++++++++++++++++++++++-- Start_Linux/game.o | Bin 0 -> 10208 bytes Start_Linux/input.c | 35 ++++++++-- Start_Linux/input.o | Bin 0 -> 7536 bytes Start_Linux/main.c | 22 +++++- Start_Linux/runTests | Bin 0 -> 47248 bytes Start_Mac/game.c | 151 ++++++++++++++++++++++++++++++++++++++++-- Start_Mac/input.c | 35 ++++++++-- Start_Mac/main.c | 22 +++++- Start_Windows/game.c | 151 ++++++++++++++++++++++++++++++++++++++++-- Start_Windows/input.c | 35 ++++++++-- Start_Windows/main.c | 22 +++++- 12 files changed, 582 insertions(+), 42 deletions(-) create mode 100644 Start_Linux/game.o create mode 100644 Start_Linux/input.o create mode 100644 Start_Linux/runTests diff --git a/Start_Linux/game.c b/Start_Linux/game.c index d8cc133..dbd0ded 100644 --- a/Start_Linux/game.c +++ b/Start_Linux/game.c @@ -2,22 +2,159 @@ #include #include #include +#include #define MAX_RAND_TRIES_PER_WORD 10 #define EMPTY_CHAR 0 -//TODO: Spiellogik implementieren: -/* * Wörter aus der Wortliste zufällig horizontal oder vertikal platzieren - * restliche Felder mit zufälligen Buchstaben füllen */ +// Helper function to check if a word can be placed at a specific position +static int canPlaceWord(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], + const char *word, unsigned int row, unsigned int col, + int horizontal, unsigned int searchFieldLen) +{ + unsigned int wordLen = strlen(word); + + if (horizontal) + { + // Check if word fits horizontally + if (col + wordLen > searchFieldLen) + return 0; + + // Check if all positions are empty or match the word + for (unsigned int i = 0; i < wordLen; i++) + { + if (salad[row][col + i] != EMPTY_CHAR && salad[row][col + i] != word[i]) + return 0; + } + } + else + { + // Check if word fits vertically + if (row + wordLen > searchFieldLen) + return 0; + + // Check if all positions are empty or match the word + for (unsigned int i = 0; i < wordLen; i++) + { + if (salad[row + i][col] != EMPTY_CHAR && salad[row + i][col] != word[i]) + return 0; + } + } + + return 1; +} + +// Helper function to place a word at a specific position +static void placeWord(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], + const char *word, unsigned int row, unsigned int col, + int horizontal) +{ + unsigned int wordLen = strlen(word); + + if (horizontal) + { + for (unsigned int i = 0; i < wordLen; i++) + { + salad[row][col + i] = word[i]; + } + } + else + { + for (unsigned int i = 0; i < wordLen; i++) + { + salad[row + i][col] = word[i]; + } + } +} // Creates the word salad by placing words randomly and filling empty spaces -int createWordSalad(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldLen, const char words[][MAX_WORD_LEN], unsigned int wordCount) +int createWordSalad(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], + unsigned int searchFieldLen, + const char words[][MAX_WORD_LEN], + unsigned int wordCount) { - + // Initialize random seed + srand(time(NULL)); + + // Initialize the grid with empty characters + for (unsigned int i = 0; i < searchFieldLen; i++) + { + for (unsigned int j = 0; j < searchFieldLen; j++) + { + salad[i][j] = EMPTY_CHAR; + } + } + + unsigned int placedWords = 0; + + // Try to place each word + for (unsigned int w = 0; w < wordCount; w++) + { + unsigned int wordLen = strlen(words[w]); + int placed = 0; + + // Skip empty words or words that are too long + if (wordLen == 0 || wordLen > searchFieldLen) + continue; + + // Try to place the word MAX_RAND_TRIES_PER_WORD times + for (int tries = 0; tries < MAX_RAND_TRIES_PER_WORD && !placed; tries++) + { + // Random direction: 0 = horizontal, 1 = vertical + int horizontal = rand() % 2; + + // Random position + unsigned int row = rand() % searchFieldLen; + unsigned int col = rand() % searchFieldLen; + + // Check if word can be placed + if (canPlaceWord(salad, words[w], row, col, horizontal, searchFieldLen)) + { + placeWord(salad, words[w], row, col, horizontal); + placed = 1; + placedWords++; + } + } + } + + // Fill remaining empty spaces with random letters + for (unsigned int i = 0; i < searchFieldLen; i++) + { + for (unsigned int j = 0; j < searchFieldLen; j++) + { + if (salad[i][j] == EMPTY_CHAR) + { + salad[i][j] = 'A' + (rand() % 26); + } + } + } + + return placedWords; } // Prints the word salad to console -void showWordSalad(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldLen) +void showWordSalad(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], + unsigned int searchFieldLen) { - + printf("\nWord Salad:\n"); + printf(" "); + + // Print column numbers + for (unsigned int i = 0; i < searchFieldLen; i++) + { + printf("%2u ", i); + } + printf("\n"); + + // Print rows with row numbers + for (unsigned int i = 0; i < searchFieldLen; i++) + { + printf("%2u ", i); + for (unsigned int j = 0; j < searchFieldLen; j++) + { + printf("%2c ", salad[i][j]); + } + printf("\n"); + } + printf("\n"); } diff --git a/Start_Linux/game.o b/Start_Linux/game.o new file mode 100644 index 0000000000000000000000000000000000000000..b24fb38c5588635cec2defe0c8a2445ffa5c61ff GIT binary patch literal 10208 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 Com^1> literal 0 HcmV?d00001 diff --git a/Start_Linux/input.c b/Start_Linux/input.c index ed77805..7326eda 100644 --- a/Start_Linux/input.c +++ b/Start_Linux/input.c @@ -2,11 +2,38 @@ #include #include -// TODO: -// eine Funktion implementieren, die ein einzelnes Wort aus einer Textdatei (words.txt) einliest und als C-String zurückgibt. - // Read words from file and store in 'words' array int readWords(FILE *file, char words[][MAX_WORD_LEN], unsigned int maxWordCount) { - + unsigned int wordCount = 0; + char line[MAX_LINE_LEN]; + + // Read file line by line + while (fgets(line, MAX_LINE_LEN, file) != NULL && wordCount < maxWordCount) + { + // Process each line to extract words separated by delimiters + char *token = strtok(line, " ,;\n\t\r"); + + while (token != NULL && wordCount < maxWordCount) + { + // Convert word to uppercase and store it + unsigned int i = 0; + while (token[i] != '\0' && i < MAX_WORD_LEN - 1) + { + words[wordCount][i] = toupper((unsigned char)token[i]); + i++; + } + words[wordCount][i] = '\0'; + + // Only count non-empty words + if (i > 0) + { + wordCount++; + } + + token = strtok(NULL, " ,;\n\t\r"); + } + } + + return wordCount; } \ No newline at end of file diff --git a/Start_Linux/input.o b/Start_Linux/input.o new file mode 100644 index 0000000000000000000000000000000000000000..3e2cd34fbfa98a0789d5f7df5c4b5caaa6297af2 GIT binary patch literal 7536 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 literal 0 HcmV?d00001 diff --git a/Start_Linux/main.c b/Start_Linux/main.c index 03da755..d08a203 100644 --- a/Start_Linux/main.c +++ b/Start_Linux/main.c @@ -36,10 +36,26 @@ int main(int argc, char *argv[]) // Create the word salad by placing words into grid placedWords = createWordSalad(wordSalad, SALAD_SIZE, words, wordCount); - // TODO: // Check if all words were successfully placed - // Start the game if successful - // error message if some words couldn't be placed + if (placedWords == wordCount) + { + // All words placed successfully - start the game + printf("Successfully placed all %u words!\n", placedWords); + showWordSalad(wordSalad, SALAD_SIZE); + + // Start the graphical game + startGraphicalGame(wordSalad, SALAD_SIZE, words, wordCount); + } + else + { + // Some words couldn't be placed + fprintf(stderr, "Warning: Could only place %u out of %u words.\n", + placedWords, wordCount); + showWordSalad(wordSalad, SALAD_SIZE); + + // Start the game anyway with the words that were placed + startGraphicalGame(wordSalad, SALAD_SIZE, words, wordCount); + } } else diff --git a/Start_Linux/runTests b/Start_Linux/runTests new file mode 100644 index 0000000000000000000000000000000000000000..a9e5151eedd26f472450c33d06b94db65ebbbec9 GIT binary patch literal 47248 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

2+jOzh>?O>o70SXzWC>g} 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 #include #include +#include #define MAX_RAND_TRIES_PER_WORD 10 #define EMPTY_CHAR 0 -//TODO: Spiellogik implementieren: -/* * Wörter aus der Wortliste zufällig horizontal oder vertikal platzieren - * restliche Felder mit zufälligen Buchstaben füllen */ +// Helper function to check if a word can be placed at a specific position +static int canPlaceWord(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], + const char *word, unsigned int row, unsigned int col, + int horizontal, unsigned int searchFieldLen) +{ + unsigned int wordLen = strlen(word); + + if (horizontal) + { + // Check if word fits horizontally + if (col + wordLen > searchFieldLen) + return 0; + + // Check if all positions are empty or match the word + for (unsigned int i = 0; i < wordLen; i++) + { + if (salad[row][col + i] != EMPTY_CHAR && salad[row][col + i] != word[i]) + return 0; + } + } + else + { + // Check if word fits vertically + if (row + wordLen > searchFieldLen) + return 0; + + // Check if all positions are empty or match the word + for (unsigned int i = 0; i < wordLen; i++) + { + if (salad[row + i][col] != EMPTY_CHAR && salad[row + i][col] != word[i]) + return 0; + } + } + + return 1; +} + +// Helper function to place a word at a specific position +static void placeWord(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], + const char *word, unsigned int row, unsigned int col, + int horizontal) +{ + unsigned int wordLen = strlen(word); + + if (horizontal) + { + for (unsigned int i = 0; i < wordLen; i++) + { + salad[row][col + i] = word[i]; + } + } + else + { + for (unsigned int i = 0; i < wordLen; i++) + { + salad[row + i][col] = word[i]; + } + } +} // Creates the word salad by placing words randomly and filling empty spaces -int createWordSalad(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldLen, const char words[][MAX_WORD_LEN], unsigned int wordCount) +int createWordSalad(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], + unsigned int searchFieldLen, + const char words[][MAX_WORD_LEN], + unsigned int wordCount) { - + // Initialize random seed + srand(time(NULL)); + + // Initialize the grid with empty characters + for (unsigned int i = 0; i < searchFieldLen; i++) + { + for (unsigned int j = 0; j < searchFieldLen; j++) + { + salad[i][j] = EMPTY_CHAR; + } + } + + unsigned int placedWords = 0; + + // Try to place each word + for (unsigned int w = 0; w < wordCount; w++) + { + unsigned int wordLen = strlen(words[w]); + int placed = 0; + + // Skip empty words or words that are too long + if (wordLen == 0 || wordLen > searchFieldLen) + continue; + + // Try to place the word MAX_RAND_TRIES_PER_WORD times + for (int tries = 0; tries < MAX_RAND_TRIES_PER_WORD && !placed; tries++) + { + // Random direction: 0 = horizontal, 1 = vertical + int horizontal = rand() % 2; + + // Random position + unsigned int row = rand() % searchFieldLen; + unsigned int col = rand() % searchFieldLen; + + // Check if word can be placed + if (canPlaceWord(salad, words[w], row, col, horizontal, searchFieldLen)) + { + placeWord(salad, words[w], row, col, horizontal); + placed = 1; + placedWords++; + } + } + } + + // Fill remaining empty spaces with random letters + for (unsigned int i = 0; i < searchFieldLen; i++) + { + for (unsigned int j = 0; j < searchFieldLen; j++) + { + if (salad[i][j] == EMPTY_CHAR) + { + salad[i][j] = 'A' + (rand() % 26); + } + } + } + + return placedWords; } // Prints the word salad to console -void showWordSalad(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldLen) +void showWordSalad(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], + unsigned int searchFieldLen) { - + printf("\nWord Salad:\n"); + printf(" "); + + // Print column numbers + for (unsigned int i = 0; i < searchFieldLen; i++) + { + printf("%2u ", i); + } + printf("\n"); + + // Print rows with row numbers + for (unsigned int i = 0; i < searchFieldLen; i++) + { + printf("%2u ", i); + for (unsigned int j = 0; j < searchFieldLen; j++) + { + printf("%2c ", salad[i][j]); + } + printf("\n"); + } + printf("\n"); } diff --git a/Start_Mac/input.c b/Start_Mac/input.c index ed77805..7326eda 100644 --- a/Start_Mac/input.c +++ b/Start_Mac/input.c @@ -2,11 +2,38 @@ #include #include -// TODO: -// eine Funktion implementieren, die ein einzelnes Wort aus einer Textdatei (words.txt) einliest und als C-String zurückgibt. - // Read words from file and store in 'words' array int readWords(FILE *file, char words[][MAX_WORD_LEN], unsigned int maxWordCount) { - + unsigned int wordCount = 0; + char line[MAX_LINE_LEN]; + + // Read file line by line + while (fgets(line, MAX_LINE_LEN, file) != NULL && wordCount < maxWordCount) + { + // Process each line to extract words separated by delimiters + char *token = strtok(line, " ,;\n\t\r"); + + while (token != NULL && wordCount < maxWordCount) + { + // Convert word to uppercase and store it + unsigned int i = 0; + while (token[i] != '\0' && i < MAX_WORD_LEN - 1) + { + words[wordCount][i] = toupper((unsigned char)token[i]); + i++; + } + words[wordCount][i] = '\0'; + + // Only count non-empty words + if (i > 0) + { + wordCount++; + } + + token = strtok(NULL, " ,;\n\t\r"); + } + } + + return wordCount; } \ No newline at end of file diff --git a/Start_Mac/main.c b/Start_Mac/main.c index 03da755..d08a203 100644 --- a/Start_Mac/main.c +++ b/Start_Mac/main.c @@ -36,10 +36,26 @@ int main(int argc, char *argv[]) // Create the word salad by placing words into grid placedWords = createWordSalad(wordSalad, SALAD_SIZE, words, wordCount); - // TODO: // Check if all words were successfully placed - // Start the game if successful - // error message if some words couldn't be placed + if (placedWords == wordCount) + { + // All words placed successfully - start the game + printf("Successfully placed all %u words!\n", placedWords); + showWordSalad(wordSalad, SALAD_SIZE); + + // Start the graphical game + startGraphicalGame(wordSalad, SALAD_SIZE, words, wordCount); + } + else + { + // Some words couldn't be placed + fprintf(stderr, "Warning: Could only place %u out of %u words.\n", + placedWords, wordCount); + showWordSalad(wordSalad, SALAD_SIZE); + + // Start the game anyway with the words that were placed + startGraphicalGame(wordSalad, SALAD_SIZE, words, wordCount); + } } else diff --git a/Start_Windows/game.c b/Start_Windows/game.c index d8cc133..dbd0ded 100644 --- a/Start_Windows/game.c +++ b/Start_Windows/game.c @@ -2,22 +2,159 @@ #include #include #include +#include #define MAX_RAND_TRIES_PER_WORD 10 #define EMPTY_CHAR 0 -//TODO: Spiellogik implementieren: -/* * Wörter aus der Wortliste zufällig horizontal oder vertikal platzieren - * restliche Felder mit zufälligen Buchstaben füllen */ +// Helper function to check if a word can be placed at a specific position +static int canPlaceWord(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], + const char *word, unsigned int row, unsigned int col, + int horizontal, unsigned int searchFieldLen) +{ + unsigned int wordLen = strlen(word); + + if (horizontal) + { + // Check if word fits horizontally + if (col + wordLen > searchFieldLen) + return 0; + + // Check if all positions are empty or match the word + for (unsigned int i = 0; i < wordLen; i++) + { + if (salad[row][col + i] != EMPTY_CHAR && salad[row][col + i] != word[i]) + return 0; + } + } + else + { + // Check if word fits vertically + if (row + wordLen > searchFieldLen) + return 0; + + // Check if all positions are empty or match the word + for (unsigned int i = 0; i < wordLen; i++) + { + if (salad[row + i][col] != EMPTY_CHAR && salad[row + i][col] != word[i]) + return 0; + } + } + + return 1; +} + +// Helper function to place a word at a specific position +static void placeWord(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], + const char *word, unsigned int row, unsigned int col, + int horizontal) +{ + unsigned int wordLen = strlen(word); + + if (horizontal) + { + for (unsigned int i = 0; i < wordLen; i++) + { + salad[row][col + i] = word[i]; + } + } + else + { + for (unsigned int i = 0; i < wordLen; i++) + { + salad[row + i][col] = word[i]; + } + } +} // Creates the word salad by placing words randomly and filling empty spaces -int createWordSalad(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldLen, const char words[][MAX_WORD_LEN], unsigned int wordCount) +int createWordSalad(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], + unsigned int searchFieldLen, + const char words[][MAX_WORD_LEN], + unsigned int wordCount) { - + // Initialize random seed + srand(time(NULL)); + + // Initialize the grid with empty characters + for (unsigned int i = 0; i < searchFieldLen; i++) + { + for (unsigned int j = 0; j < searchFieldLen; j++) + { + salad[i][j] = EMPTY_CHAR; + } + } + + unsigned int placedWords = 0; + + // Try to place each word + for (unsigned int w = 0; w < wordCount; w++) + { + unsigned int wordLen = strlen(words[w]); + int placed = 0; + + // Skip empty words or words that are too long + if (wordLen == 0 || wordLen > searchFieldLen) + continue; + + // Try to place the word MAX_RAND_TRIES_PER_WORD times + for (int tries = 0; tries < MAX_RAND_TRIES_PER_WORD && !placed; tries++) + { + // Random direction: 0 = horizontal, 1 = vertical + int horizontal = rand() % 2; + + // Random position + unsigned int row = rand() % searchFieldLen; + unsigned int col = rand() % searchFieldLen; + + // Check if word can be placed + if (canPlaceWord(salad, words[w], row, col, horizontal, searchFieldLen)) + { + placeWord(salad, words[w], row, col, horizontal); + placed = 1; + placedWords++; + } + } + } + + // Fill remaining empty spaces with random letters + for (unsigned int i = 0; i < searchFieldLen; i++) + { + for (unsigned int j = 0; j < searchFieldLen; j++) + { + if (salad[i][j] == EMPTY_CHAR) + { + salad[i][j] = 'A' + (rand() % 26); + } + } + } + + return placedWords; } // Prints the word salad to console -void showWordSalad(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldLen) +void showWordSalad(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], + unsigned int searchFieldLen) { - + printf("\nWord Salad:\n"); + printf(" "); + + // Print column numbers + for (unsigned int i = 0; i < searchFieldLen; i++) + { + printf("%2u ", i); + } + printf("\n"); + + // Print rows with row numbers + for (unsigned int i = 0; i < searchFieldLen; i++) + { + printf("%2u ", i); + for (unsigned int j = 0; j < searchFieldLen; j++) + { + printf("%2c ", salad[i][j]); + } + printf("\n"); + } + printf("\n"); } diff --git a/Start_Windows/input.c b/Start_Windows/input.c index ed77805..7326eda 100644 --- a/Start_Windows/input.c +++ b/Start_Windows/input.c @@ -2,11 +2,38 @@ #include #include -// TODO: -// eine Funktion implementieren, die ein einzelnes Wort aus einer Textdatei (words.txt) einliest und als C-String zurückgibt. - // Read words from file and store in 'words' array int readWords(FILE *file, char words[][MAX_WORD_LEN], unsigned int maxWordCount) { - + unsigned int wordCount = 0; + char line[MAX_LINE_LEN]; + + // Read file line by line + while (fgets(line, MAX_LINE_LEN, file) != NULL && wordCount < maxWordCount) + { + // Process each line to extract words separated by delimiters + char *token = strtok(line, " ,;\n\t\r"); + + while (token != NULL && wordCount < maxWordCount) + { + // Convert word to uppercase and store it + unsigned int i = 0; + while (token[i] != '\0' && i < MAX_WORD_LEN - 1) + { + words[wordCount][i] = toupper((unsigned char)token[i]); + i++; + } + words[wordCount][i] = '\0'; + + // Only count non-empty words + if (i > 0) + { + wordCount++; + } + + token = strtok(NULL, " ,;\n\t\r"); + } + } + + return wordCount; } \ No newline at end of file diff --git a/Start_Windows/main.c b/Start_Windows/main.c index 03da755..d08a203 100644 --- a/Start_Windows/main.c +++ b/Start_Windows/main.c @@ -36,10 +36,26 @@ int main(int argc, char *argv[]) // Create the word salad by placing words into grid placedWords = createWordSalad(wordSalad, SALAD_SIZE, words, wordCount); - // TODO: // Check if all words were successfully placed - // Start the game if successful - // error message if some words couldn't be placed + if (placedWords == wordCount) + { + // All words placed successfully - start the game + printf("Successfully placed all %u words!\n", placedWords); + showWordSalad(wordSalad, SALAD_SIZE); + + // Start the graphical game + startGraphicalGame(wordSalad, SALAD_SIZE, words, wordCount); + } + else + { + // Some words couldn't be placed + fprintf(stderr, "Warning: Could only place %u out of %u words.\n", + placedWords, wordCount); + showWordSalad(wordSalad, SALAD_SIZE); + + // Start the game anyway with the words that were placed + startGraphicalGame(wordSalad, SALAD_SIZE, words, wordCount); + } } else