Kommentare

This commit is contained in:
jw 2025-11-06 14:42:16 +01:00
parent b7089376a1
commit 8555ca8fb5

View File

@ -1,14 +1,15 @@
#include "game.h" #include "game.h" // Enthält Definitionen wie MAX_SEARCH_FIELD_LEN und MAX_WORD_LEN
#include <time.h> #include <time.h> // Für Zeitfunktionen, z.B. zur Initialisierung von Zufallszahlen
#include <stdlib.h> #include <stdlib.h> // Für rand(), malloc(), etc.
#include <string.h> #include <string.h> // Für Stringfunktionen wie strnlen()
#include <ctype.h> #include <ctype.h> // Für toupper(), um Buchstaben in Großbuchstaben umzuwandeln
#include <stdio.h> #include <stdio.h> // Für printf(), um das Spielfeld auszugeben
#define MAX_RAND_TRIES_PER_WORD 10 #define MAX_RAND_TRIES_PER_WORD 10 // Maximale Anzahl zufälliger Platzierungsversuche pro Wort
#define EMPTY_CHAR 0 #define EMPTY_CHAR 0 // Kennzeichnung für ein leeres Feld im Spielfeld
// Prüft, ob ein Wort an (x,y) in gegebener Richtung passt.
// dir = 0 -> horizontal; dir = 1 -> vertikal // Prüft, ob ein Wort an Position (x,y) in gegebener Richtung ins Spielfeld passt
// dir = 0 → horizontal; dir = 1 → vertikal
static int canPlaceAt(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], static int canPlaceAt(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN],
unsigned int searchFieldLen, unsigned int searchFieldLen,
unsigned int x, unsigned int y, unsigned int x, unsigned int y,
@ -16,24 +17,29 @@ static int canPlaceAt(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LE
int dir) int dir)
{ {
if (dir == 0) { // horizontal if (dir == 0) { // horizontal
// Prüfen, ob das Wort über den rechten Rand hinausgeht
if (x + wordLen > searchFieldLen) return 0; if (x + wordLen > searchFieldLen) return 0;
// Prüfen, ob jedes Zeichen entweder leer ist oder bereits passt
for (unsigned int k = 0; k < wordLen; ++k) { for (unsigned int k = 0; k < wordLen; ++k) {
char c = (char)toupper((unsigned char)word[k]); char c = (char)toupper((unsigned char)word[k]); // Zeichen in Großbuchstaben
char cell = salad[y][x + k]; char cell = salad[y][x + k]; // Aktuelles Feld
if (cell != EMPTY_CHAR && cell != c) return 0; if (cell != EMPTY_CHAR && cell != c) return 0; // Konflikt → nicht platzierbar
} }
} else { // vertikal } else { // vertikal
// Prüfen, ob das Wort über den unteren Rand hinausgeht
if (y + wordLen > searchFieldLen) return 0; if (y + wordLen > searchFieldLen) return 0;
for (unsigned int k = 0; k < wordLen; ++k) { for (unsigned int k = 0; k < wordLen; ++k) {
char c = (char)toupper((unsigned char)word[k]); char c = (char)toupper((unsigned char)word[k]);
char cell = salad[y + k][x]; char cell = salad[y + k][x];
if (cell != EMPTY_CHAR && cell != c) return 0; if (cell != EMPTY_CHAR && cell != c) return 0;
} }
} }
return 1; return 1; // Wort kann platziert werden
} }
// Trägt ein Wort an (x,y) in gegebener Richtung ein // Trägt ein Wort an Position (x,y) in gegebener Richtung ins Spielfeld ein
static void placeAt(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], static void placeAt(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN],
unsigned int x, unsigned int y, unsigned int x, unsigned int y,
const char *word, unsigned int wordLen, const char *word, unsigned int wordLen,
@ -50,61 +56,64 @@ static void placeAt(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN],
} }
} }
// Creates the word salad by placing words randomly and filling empty spaces // Erstellt das Wortsuchfeld, platziert Wörter und füllt leere Felder mit Zufallsbuchstaben
// Rückgabewert: Anzahl der tatsächlich platzierten Wörter // Rückgabewert: Anzahl der erfolgreich platzierten Wörter
int createWordSalad(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], int createWordSalad(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN],
unsigned int searchFieldLen, unsigned int searchFieldLen,
const char words[][MAX_WORD_LEN], const char words[][MAX_WORD_LEN],
unsigned int wordCount) unsigned int wordCount)
{ {
// Ungültige Feldgröße -> nichts tun und 0 zurückgeben // Ungültige Feldgröße → nichts tun
if (searchFieldLen == 0 || searchFieldLen > MAX_SEARCH_FIELD_LEN) { if (searchFieldLen == 0 || searchFieldLen > MAX_SEARCH_FIELD_LEN) {
return 0; return 0;
} }
// Feld initial mit EMPTY_CHAR füllen // Initialisiere das Spielfeld mit EMPTY_CHAR
for (unsigned int r = 0; r < searchFieldLen; ++r) { for (unsigned int r = 0; r < searchFieldLen; ++r) {
for (unsigned int c = 0; c < searchFieldLen; ++c) { for (unsigned int c = 0; c < searchFieldLen; ++c) {
salad[r][c] = EMPTY_CHAR; salad[r][c] = EMPTY_CHAR;
} }
} }
int placedCount = 0; int placedCount = 0; // Zähler für erfolgreich platzierte Wörter
// Für jedes Wort versuchen wir eine Platzierung // Versuche, jedes Wort zu platzieren
for (unsigned int i = 0; i < wordCount; ++i) { for (unsigned int i = 0; i < wordCount; ++i) {
const char *word = words[i]; const char *word = words[i];
if (!word) continue; if (!word) continue;
size_t rawLen = strnlen(word, MAX_WORD_LEN); size_t rawLen = strnlen(word, MAX_WORD_LEN); // Wortlänge ermitteln
if (rawLen == 0) continue; if (rawLen == 0) continue;
unsigned int wordLen = (unsigned int)rawLen; unsigned int wordLen = (unsigned int)rawLen;
// Wenn Wort länger als die Feldkante ist, passt es weder horizontal noch vertikal -> überspringen // Wenn das Wort zu lang ist, überspringen
if (wordLen > searchFieldLen) { if (wordLen > searchFieldLen) {
continue; continue;
} }
int placed = 0; int placed = 0; // Flag, ob das Wort platziert wurde
// Zufällige Versuche // Zufällige Platzierungsversuche
for (int t = 0; t < MAX_RAND_TRIES_PER_WORD && !placed; ++t) { for (int t = 0; t < MAX_RAND_TRIES_PER_WORD && !placed; ++t) {
int dir = rand() % 2; // 0=H, 1=V int dir = rand() % 2; // Richtung zufällig wählen: 0 = horizontal, 1 = vertikal
// Berechnung der maximalen Startpositionen
unsigned int maxX = (dir == 0) ? (searchFieldLen - wordLen) : (searchFieldLen - 1); unsigned int maxX = (dir == 0) ? (searchFieldLen - wordLen) : (searchFieldLen - 1);
unsigned int maxY = (dir == 1) ? (searchFieldLen - wordLen) : (searchFieldLen - 1); unsigned int maxY = (dir == 1) ? (searchFieldLen - wordLen) : (searchFieldLen - 1);
// Zufällige Startposition innerhalb der Grenzen
unsigned int x = (maxX > 0) ? (unsigned int)(rand() % (maxX + 1)) : 0; unsigned int x = (maxX > 0) ? (unsigned int)(rand() % (maxX + 1)) : 0;
unsigned int y = (maxY > 0) ? (unsigned int)(rand() % (maxY + 1)) : 0; unsigned int y = (maxY > 0) ? (unsigned int)(rand() % (maxY + 1)) : 0;
// Prüfen und ggf. platzieren
if (canPlaceAt(salad, searchFieldLen, x, y, word, wordLen, dir)) { if (canPlaceAt(salad, searchFieldLen, x, y, word, wordLen, dir)) {
placeAt(salad, x, y, word, wordLen, dir); placeAt(salad, x, y, word, wordLen, dir);
placed = 1; placed = 1;
} }
} }
// Fallback: deterministische Vollsuche // Fallback: systematische Suche, falls Zufall nicht funktioniert hat
if (!placed) { if (!placed) {
for (int dir = 0; dir < 2 && !placed; ++dir) { for (int dir = 0; dir < 2 && !placed; ++dir) {
unsigned int limitX = (dir == 0) ? (searchFieldLen - wordLen + 1) : searchFieldLen; unsigned int limitX = (dir == 0) ? (searchFieldLen - wordLen + 1) : searchFieldLen;
@ -122,34 +131,32 @@ int createWordSalad(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN],
} }
if (placed) { if (placed) {
placedCount++; placedCount++; // Erfolgreich platziertes Wort zählen
} }
// Nicht platzierbare Wörter werden einfach ignoriert (zählen nicht). // Nicht platzierbare Wörter werden ignoriert
} }
// Restliche Felder **immer** mit Zufallsbuchstaben füllen, auch wenn 0 Wörter platziert wurden // Fülle alle verbleibenden Felder mit zufälligen Buchstaben
for (unsigned int r = 0; r < searchFieldLen; ++r) { for (unsigned int r = 0; r < searchFieldLen; ++r) {
for (unsigned int c = 0; c < searchFieldLen; ++c) { for (unsigned int c = 0; c < searchFieldLen; ++c) {
if (salad[r][c] == EMPTY_CHAR) { if (salad[r][c] == EMPTY_CHAR) {
salad[r][c] = (char)('A' + (rand() % 26)); salad[r][c] = (char)('A' + (rand() % 26)); // Zufallsbuchstabe AZ
} }
} }
} }
// Anzahl der platzierten Wörter zurückgeben (Tests erwarten dies) return placedCount; // Anzahl der platzierten Wörter zurückgeben
return placedCount;
} }
// Prints the word salad to console // Gibt das fertige Wortsuchfeld auf der Konsole aus
void showWordSalad(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], void showWordSalad(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN],
unsigned int searchFieldLen) unsigned int searchFieldLen)
{ {
for (unsigned int r = 0; r < searchFieldLen; ++r) { for (unsigned int r = 0; r < searchFieldLen; ++r) {
for (unsigned int c = 0; c < searchFieldLen; ++c) { for (unsigned int c = 0; c < searchFieldLen; ++c) {
// Da wir immer auffüllen, sollte hier nie EMPTY_CHAR erscheinen char ch = salad[r][c]; // Zeichen aus dem Feld
char ch = salad[r][c]; printf("%c ", ch); // Ausgabe mit Leerzeichen
printf("%c ", ch);
} }
printf("\n"); printf("\n"); // Zeilenumbruch nach jeder Reihe
} }
} }