DobleSpiel/numbers.c

121 lines
3.6 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "numbers.h"
#include "bintree.h"
// --- Vergleichsfunktionen ---
// 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;
if (arg1 < arg2) return -1;
if (arg1 > arg2) return 1;
return 0;
}
// 2. Vergleichsfunktion für den Binärbaum
int compare_tree_data(const void *arg1, const void *arg2) {
unsigned int val1 = *(const unsigned int*)arg1;
unsigned int val2 = *(const unsigned int*)arg2;
if (val1 < val2) return -1;
if (val1 > val2) return 1;
return 0;
}
/* * Erzeugt ein Array mit (len - 1) eindeutigen Zufallszahlen und einem Duplikat. */
unsigned int *createNumbers(unsigned int len) {
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;
}
// ---------------------------------------------
TreeNode *root = NULL;
unsigned int *numbers = (unsigned int *)malloc(len * sizeof(unsigned int));
if (numbers == NULL) return NULL;
unsigned int count = 0;
unsigned int max_val = 2 * len;
unsigned int value_to_duplicate = 0;
// Erzeugen von len - 1 eindeutigen Zufallszahlen
while (count < len - 1) {
unsigned int random_num = (rand() % max_val) + 1;
int is_duplicate = 0;
// 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) {
free(numbers);
return NULL;
}
if (is_duplicate == 0) {
// Erfolg: Zahl war neu
numbers[count] = random_num;
count++;
// Merken für späteres Duplizieren
value_to_duplicate = random_num;
}
// Bei Duplikat (is_duplicate == 1) einfach weitermachen -> while läuft weiter
}
// Duplizieren eines Eintrags an die letzte Stelle
if (len > 1) {
// 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;
}
// Speicher des Baumes freigeben
clearTree(root);
// Mischen (Fisher-Yates Shuffle)
for (unsigned int i = len - 1; i > 0; i--) {
unsigned int j = rand() % (i + 1);
unsigned int temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
}
return numbers;
}
/* * 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;
memcpy(sorted_numbers, numbers, len * sizeof(unsigned int));
qsort(sorted_numbers, len, sizeof(unsigned int), compare_unsigned_int);
unsigned int duplicate = 0;
for (unsigned int i = 0; i < len - 1; i++) {
if (sorted_numbers[i] == sorted_numbers[i+1]) {
duplicate = sorted_numbers[i];
break;
}
}
free(sorted_numbers);
return duplicate;
}