diff --git a/highscores.txt b/highscores.txt index 40f06ee..e69de29 100644 --- a/highscores.txt +++ b/highscores.txt @@ -1,7 +0,0 @@ -<<<<<<< HEAD -Alex;14964 -======= -player_name;7977 -player_name;7952 ->>>>>>> 510edf85859637799b1b334b2bf6c5deff0adb80 -player1;3999 diff --git a/numbers.c b/numbers.c index e7e4df6..2b10404 100644 --- a/numbers.c +++ b/numbers.c @@ -7,7 +7,7 @@ // --- Vergleichsfunktionen --- -// 1. Vergleichsfunktion für qsort (vergleicht unsigned int-Werte) +// 1. Vergleichsfunktion für qsort int compare_unsigned_int(const void *a, const void *b) { unsigned int arg1 = *(const unsigned int*)a; unsigned int arg2 = *(const unsigned int*)b; @@ -17,10 +17,8 @@ int compare_unsigned_int(const void *a, const void *b) { return 0; } -// 2. Vergleichsfunktion für den Binärbaum (vergleicht die *Daten* der Knoten) -// Die Argumente sind Pointer auf die *Daten* (void*), d.h. Pointer auf unsigned int. +// 2. Vergleichsfunktion für den Binärbaum int compare_tree_data(const void *arg1, const void *arg2) { - // Cast der void*-Pointer auf unsigned int*-Pointer unsigned int val1 = *(const unsigned int*)arg1; unsigned int val2 = *(const unsigned int*)arg2; @@ -29,100 +27,66 @@ int compare_tree_data(const void *arg1, const void *arg2) { return 0; } -//TODO: getDuplicate und createNumbers implementieren -/* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen. - * Sicherstellen, dass beim Befüllen keine Duplikate entstehen. - * Duplizieren eines zufälligen Eintrags im Array. - * in `getDuplicate()`: Sortieren des Arrays und Erkennen der doppelten Zahl durch Vergleich benachbarter Elemente. */ - -// Returns len random numbers between 1 and 2x len in random order which are all different, except for two entries. -// Returns NULL on errors. Use your implementation of the binary search tree to check for possible duplicates while -// creating random numbers. -/* * Erzeugt ein Array mit (len - 1) eindeutigen Zufallszahlen und einem Duplikat. - * Die Duplikatprüfung erfolgt über den Binärbaum (addToTree). - */ +/* * Erzeugt ein Array mit (len - 1) eindeutigen Zufallszahlen und einem Duplikat. */ unsigned int *createNumbers(unsigned int len) { - if (len == 0) { - return NULL; - } + if (len == 0) return NULL; + + // --- NEU: Zufallsgenerator initialisieren --- + // Wir verwenden eine statische Variable, damit srand nur ein einziges Mal + // aufgerufen wird, auch wenn createNumbers mehrfach benutzt wird. + static int is_seeded = 0; + if (!is_seeded) { + srand(time(NULL)); // Initialisiert den Generator mit der aktuellen Zeit + is_seeded = 1; + } + // --------------------------------------------- - // 1. Initialisierung - // Der BST wird zunächst als NULL initialisiert, da addToTree rekursiv arbeitet. TreeNode *root = NULL; - // 2. Speicher für das Ziel-Array allokieren unsigned int *numbers = (unsigned int *)malloc(len * sizeof(unsigned int)); - if (numbers == NULL) { - return NULL; - } + if (numbers == NULL) return NULL; unsigned int count = 0; unsigned int max_val = 2 * len; - - // Speichert den Wert, der später dupliziert wird (aus dem Array gewählt) unsigned int value_to_duplicate = 0; - // 3. Erzeugen von len - 1 eindeutigen Zufallszahlen + // Erzeugen von len - 1 eindeutigen Zufallszahlen while (count < len - 1) { unsigned int random_num = (rand() % max_val) + 1; int is_duplicate = 0; - // Wir müssen die Zahl als dynamisch allokierten Speicher übergeben, - // da addToTree eine Kopie davon erwartet. - unsigned int *num_ptr = (unsigned int *)malloc(sizeof(unsigned int)); - if (num_ptr == NULL) { - // cleanup: Baum und bereits allokiertes Array freigeben - clearTree(root); - free(numbers); - return NULL; - } - *num_ptr = random_num; - - // Fügen in den Baum ein: - // root MUSS das Ergebnis der rekursiven addToTree-Funktion speichern! - root = addToTree(root, num_ptr, sizeof(unsigned int), compare_tree_data, &is_duplicate); + // Wir übergeben die Adresse der lokalen Variable. addToTree kopiert den Wert. + root = addToTree(root, &random_num, sizeof(unsigned int), compare_tree_data, &is_duplicate); if (root == NULL) { - // Schwerwiegender Fehler bei der Speicherallokation innerhalb von addToTree - clearTree(root); free(numbers); - free(num_ptr); // Datenpointer freigeben, falls Fehler vor der Kopie auftrat return NULL; } if (is_duplicate == 0) { - // Erfolg: Zahl war neu und wurde eingefügt (die Datenkopie liegt nun im Baum) + // Erfolg: Zahl war neu numbers[count] = random_num; count++; - // value_to_duplicate merken + // Merken für späteres Duplizieren value_to_duplicate = random_num; - - // Den lokalen num_ptr NICHT freigeben, da seine Kopie im Baum verwaltet wird. - } else { - // Fehler: Duplikat, wurde NICHT eingefügt. - // Den lokal allokierten Pointer MÜSSEN wir freigeben, da er nicht in den Baum ging. - free(num_ptr); } + // Bei Duplikat (is_duplicate == 1) einfach weitermachen -> while läuft weiter } - // 4. Duplizieren eines Eintrags - // Der duplizierte Wert wird an die letzte Stelle gesetzt. + // Duplizieren eines Eintrags an die letzte Stelle if (len > 1) { - // Wir verwenden value_to_duplicate, um sicherzustellen, dass die Zahl aus dem Array stammt. - // Wenn len sehr groß ist, wird einfach eine zufällige Zahl aus dem gefüllten Bereich gewählt. + // Fallback, falls value_to_duplicate noch 0 ist (sollte logisch nicht passieren bei len > 1) if (value_to_duplicate == 0) { value_to_duplicate = numbers[rand() % (len - 1)]; } numbers[len - 1] = value_to_duplicate; } - - // 5. Speicher des Baumes freigeben - // clearTree gibt alle Knoten und die darin enthaltenen Datenkopien frei. + // Speicher des Baumes freigeben clearTree(root); - // 6. Mischen (Shuffling) des Arrays, um die Ordnung zu randomisieren + // Mischen (Fisher-Yates Shuffle) for (unsigned int i = len - 1; i > 0; i--) { unsigned int j = rand() % (i + 1); unsigned int temp = numbers[i]; @@ -132,26 +96,18 @@ unsigned int *createNumbers(unsigned int len) { return numbers; } -// Returns only the only number in numbers which is present twice. Returns zero on errors. -/* * Sortiert das Array und erkennt das Duplikat durch Vergleich benachbarter Elemente. - * (O(N log N) wegen qsort) - */ -unsigned int getDuplicate(const unsigned int numbers[], unsigned int len) { - if (len < 2) { - return 0; // Fehler - } - // 1. Array duplizieren, da das Original const ist und sortiert werden muss +/* * Sortiert das Array und erkennt das Duplikat. */ +unsigned int getDuplicate(const unsigned int numbers[], unsigned int len) { + if (len < 2) return 0; + unsigned int *sorted_numbers = (unsigned int *)malloc(len * sizeof(unsigned int)); - if (sorted_numbers == NULL) { - return 0; - } + if (sorted_numbers == NULL) return 0; + memcpy(sorted_numbers, numbers, len * sizeof(unsigned int)); - // 2. Sortieren des Arrays qsort(sorted_numbers, len, sizeof(unsigned int), compare_unsigned_int); - // 3. Erkennen der doppelten Zahl durch Vergleich benachbarter Elemente unsigned int duplicate = 0; for (unsigned int i = 0; i < len - 1; i++) { if (sorted_numbers[i] == sorted_numbers[i+1]) { @@ -161,7 +117,5 @@ unsigned int getDuplicate(const unsigned int numbers[], unsigned int len) { } free(sorted_numbers); - - // 4. Ergebnis zurückgeben return duplicate; } \ No newline at end of file