Compare commits

..

9 Commits
main ... main

Author SHA1 Message Date
93a20fb4da Unit Test bintree 2025-12-16 12:56:57 +01:00
9c0db0ff31 Shuffle Funktion in numbers.c 2025-12-16 12:43:36 +01:00
be3cb9e2fc Bintree, Numbers angepasst 2025-12-16 11:45:12 +01:00
Tubui
b8d48df702 code done 2025-12-16 00:29:39 +01:00
Tubui
f0085da7fe code completion 2025-12-16 00:21:43 +01:00
Tubui
291c8a93e7 First commit 2025-12-16 00:21:43 +01:00
bc923cca9f Unit Test für numbers.c 2025-12-15 20:51:15 +01:00
25c5a9ea5f Kommentare eingefügt 2025-12-15 20:41:41 +01:00
5ed4a367c8 Bintree 2025-12-15 13:18:13 +01:00
31 changed files with 428 additions and 121 deletions

Binary file not shown.

140
bintree.c
View File

@ -1,36 +1,144 @@
#include <stdlib.h>
#include <string.h>
#include "stack.h"
#include "bintree.h"
#include "stack.h"
//TODO: binären Suchbaum implementieren
/* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv),
* `clearTree`: gibt den gesamten Baum frei (rekursiv),
* `treeSize`: zählt die Knoten im Baum (rekursiv),
* `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. */
// Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates
// if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added).
/* Fügt eine Kopie der Daten in den Baum ein, geordnet nach compareFct. Akzeptiert Duplikate,
wenn isDuplicate NULL ist, andernfalls ignoriert Duplikate und setzt isDuplicate auf 1 (oder auf 0 bei neuem Eintrag). */
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate)
{
// Überprüfe ungültige Eingabeparameter
if (compareFct == NULL || data == NULL || dataSize == 0)
return root; // ungültige Eingabe: nichts tun
// Wenn der Baum leer ist, erstelle einen neuen Wurzelknoten
if (root == NULL)
{
TreeNode *node = (TreeNode *)malloc(sizeof(TreeNode));
if (node == NULL)
return NULL; // Speicherallokation fehlgeschlagen
node->data = malloc(dataSize);
if (node->data == NULL)
{
free(node);
return NULL;
}
memcpy(node->data, data, dataSize);
node->left = NULL;
node->right = NULL;
if (isDuplicate != NULL)
*isDuplicate = 0;
return node;
}
// Vergleiche neue Daten mit aktueller Wurzel
int cmp = compareFct(data, root->data);
// Wenn neue Daten kleiner sind, füge in linken Unterbaum ein
if (cmp < 0)
{
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
}
// Wenn neue Daten größer sind, füge in rechten Unterbaum ein
else if (cmp > 0)
{
root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate);
}
// Wenn gleich (Duplikat)
else
{
// Wenn Duplikate erkannt werden sollen, setze Flag und ignoriere
if (isDuplicate != NULL)
{
*isDuplicate = 1;
}
// Andernfalls erlaube Duplikate durch Einfügen in rechten Unterbaum
else
{
root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate);
}
}
return root;
}
// Iterates over the tree given by root. Follows the usage of strtok. If tree is NULL, the next entry of the last tree given is returned in ordering direction.
// Use your implementation of a stack to organize the iterator. Push the root node and all left nodes first. On returning the next element,
// push the top node and push all its left nodes.
/* Iteriert über den Baum in aufsteigender Reihenfolge (in-order).
Verwendet die Logik von strtok: Wenn root != NULL, initialisiere/reset Iterator für diesen Baum.
Wenn root == NULL, setze Iteration von letzter Position fort.
Verwendet Stack zur Verwaltung des Traversierungs-Zustands. */
void *nextTreeData(TreeNode *root)
{
// Statischer Stack zur Aufrechterhaltung des Iterator-Zustands zwischen Aufrufen
static StackNode *iterStack = NULL;
// Wenn ein neuer Baum bereitgestellt wird, initialisiere den Iterator
if (root != NULL)
{
// Lösche vorherigen Iterator-Zustand
clearStack(iterStack);
iterStack = NULL;
// Pushe die Wurzel und alle linken Nachfahren auf den Stack
TreeNode *cur = root;
while (cur != NULL)
{
iterStack = push(iterStack, cur);
cur = cur->left;
}
}
else
{
// Wenn Iteration fortgesetzt wird, aber kein Stack initialisiert, gib NULL zurück
if (iterStack == NULL)
return NULL;
}
// Wenn Stack leer ist, keine weiteren Elemente
if (iterStack == NULL)
return NULL;
// Poppe den nächsten Knoten vom Stack (in-order-Traversierung)
TreeNode *node = (TreeNode *)top(iterStack);
iterStack = pop(iterStack);
// Pushe den rechten Unterbaum des aktuellen Knotens und seine linken Nachfahren
TreeNode *r = node->right;
while (r != NULL)
{
iterStack = push(iterStack, r);
r = r->left;
}
return node->data;
}
// Releases all memory resources (including data copies).
/* Gibt alle Speicherressourcen frei (einschließlich Datenkopien). */
void clearTree(TreeNode *root)
{
// Basisfall: wenn Baum leer, nichts tun
if (root == NULL)
return;
// Rekursiv linken und rechten Unterbaum löschen
if (root->left != NULL)
clearTree(root->left);
if (root->right != NULL)
clearTree(root->right);
// Daten und Knoten selbst freigeben
free(root->data);
root->data = NULL;
free(root);
}
// Returns the number of entries in the tree given by root.
/* Gibt die Anzahl der Einträge im Baum zurück. */
unsigned int treeSize(const TreeNode *root)
{
}
// Basisfall: leerer Baum hat Größe 0
if (root == NULL)
return 0;
// Größe ist 1 (aktueller Knoten) plus Größen der Unterbäume
return 1 + treeSize(root->left) + treeSize(root->right);
}

BIN
bintree.o Normal file

Binary file not shown.

BIN
doble.exe Normal file

Binary file not shown.

BIN
doble_initial.exe Normal file

Binary file not shown.

BIN
highscore.o Normal file

Binary file not shown.

View File

@ -1 +0,0 @@
player1;3999

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
main.o Normal file

Binary file not shown.

View File

@ -1,19 +1,9 @@
CC = gcc
FLAGS = -g -Wall -lm
BINARIES = ./windows
ifeq ($(OS),Windows_NT)
include makefile_windows.variables
else
UNAME = $(shell uname)
ifeq ($(UNAME),Linux)
include makefile_linux.variables
else
include makefile_mac.variables
endif
endif
raylibfolder = ./raylib
unityfolder = ./unity
program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o
# --------------------------
# Initiales Programm bauen (zum ausprobieren)
@ -24,12 +14,10 @@ doble_initial:
# --------------------------
# Selbst implementiertes Programm bauen
# --------------------------
program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o
doble : main.o $(program_obj_files)
$(CC) $(FLAGS) $^ -o doble
$(program_obj_files): %.o: %.c
$(program_obj_filesobj_files): %.o: %.c
$(CC) -c $(FLAGS) $^ -o $@
# --------------------------
@ -42,8 +30,4 @@ unitTests:
# Clean
# --------------------------
clean:
ifeq ($(OS),Windows_NT)
del /f *.o doble
else
rm -f *.o doble
endif
rm -f *.o doble

View File

@ -1,2 +0,0 @@
LDFLAGS = -lGL -lX11 -lm
BINARIES = ./linux

View File

@ -1,3 +0,0 @@
LDFLAGS = -framework OpenGL -framework CoreFoundation -framework CoreGraphics -framework IOKit -framework Cocoa -framework CoreVideo
ARCH := $(shell uname -m)
BINARIES = ./macos-$(ARCH)

View File

@ -1,2 +0,0 @@
LDFLAGS = -lopengl32 -lgdi32 -lwinmm
BINARIES = ./windows

117
numbers.c
View File

@ -5,22 +5,115 @@
#include "numbers.h"
#include "bintree.h"
//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.
unsigned int *createNumbers(unsigned int len)
// --- Hilfsfunktion: Vergleich von unsigned int ------------------
static int compareUInt(const void *a, const void *b)
{
unsigned int ua = *(const unsigned int *)a;
unsigned int ub = *(const unsigned int *)b;
if (ua < ub) return -1;
if (ua > ub) return 1;
return 0;
}
// Returns only the only number in numbers which is present twice. Returns zero on errors.
// --- Hilfsfunktion: Shuffle des Arrays (Fisher-Yates) ------------------
static void shuffle(unsigned int *array, unsigned int len)
{
for (unsigned int i = len - 1; i > 0; i--)
{
unsigned int j = rand() % (i + 1);
unsigned int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
// Gibt ein Array mit len zufälligen Zahlen zwischen 1 und 2*len zurück, die alle unterschiedlich sind,
// außer zwei Einträgen (ein Duplikat). Verwendet den Binärbaum, um Duplikate zu vermeiden.
unsigned int *createNumbers(unsigned int len)
{
// Überprüfe ungültige Länge
if (len < 2)
return NULL;
// Allokiere Speicher für das Array
unsigned int *arr = malloc(sizeof(unsigned int) * len);
if (!arr)
return NULL;
// Initialisiere Zufallszahlengenerator
srand((unsigned int)time(NULL));
TreeNode *root = NULL;
unsigned int count = 0;
// Generiere len-1 eindeutige Zahlen
while (count < len - 1)
{
unsigned int val = (rand() % (2 * len)) + 1;
int isDup = 0;
// Füge in Baum ein und prüfe auf Duplikat
root = addToTree(root, &val, sizeof(unsigned int), compareUInt, &isDup);
if (!isDup)
{
arr[count++] = val;
}
}
// Wähle einen zufälligen bestehenden Wert als Duplikat
unsigned int duplicateIndex = rand() % (len - 1);
arr[len - 1] = arr[duplicateIndex];
// Shuffle das Array, damit das Duplikat nicht immer am Ende steht
shuffle(arr, len);
// Baum freigeben
clearTree(root);
return arr;
}
// Gibt die einzige Zahl im Array zurück, die zweimal vorkommt.
unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
{
// Überprüfe ungültige Eingaben
if (!numbers || len < 2)
return 0;
}
// Kopiere Array
unsigned int *copy = malloc(sizeof(unsigned int) * len);
if (!copy)
return 0;
memcpy(copy, numbers, sizeof(unsigned int) * len);
// Sortiere das Array (einfache Bubble-Sort)
for (unsigned int i = 0; i < len - 1; i++)
{
for (unsigned int j = i + 1; j < len; j++)
{
if (copy[j] < copy[i])
{
unsigned int t = copy[i];
copy[i] = copy[j];
copy[j] = t;
}
}
}
// Finde angrenzendes Duplikat
unsigned int duplicate = 0;
for (unsigned int i = 0; i < len - 1; i++)
{
if (copy[i] == copy[i + 1])
{
duplicate = copy[i];
break;
}
}
// Speicher freigeben
free(copy);
return duplicate;
}

BIN
numbers.o Normal file

Binary file not shown.

30
stack.c
View File

@ -1,33 +1,45 @@
#include <stdlib.h>
#include "stack.h"
//TODO: grundlegende Stackfunktionen implementieren:
/* * `push`: legt ein Element oben auf den Stack,
* `pop`: entfernt das oberste Element,
* `top`: liefert das oberste Element zurück,
* `clearStack`: gibt den gesamten Speicher frei. */
// Pushes data as pointer onto the stack.
StackNode *push(StackNode *stack, void *data)
{
StackNode *newNode = (StackNode *)malloc(sizeof(StackNode));
if (newNode == NULL)
return stack; // allocation failed: return unchanged stack
newNode->data = data;
newNode->next = stack;
return newNode;
}
// Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be
// freed by caller.)
StackNode *pop(StackNode *stack)
{
if (stack == NULL)
return NULL;
StackNode *next = stack->next;
free(stack);
return next;
}
// Returns the data of the top element.
void *top(StackNode *stack)
{
if (stack == NULL)
return NULL;
return stack->data;
}
// Clears stack and releases all memory.
void clearStack(StackNode *stack)
{
}
while (stack != NULL)
{
StackNode *next = stack->next;
free(stack);
stack = next;
}
}

View File

@ -8,6 +8,10 @@ The latest element is taken from the stack. */
#include <stdlib.h>
//TODO: passenden Datentyp als struct anlegen
typedef struct StackNode {
void *data;
struct StackNode *next;
} StackNode;
// Pushes data as pointer onto the stack.
StackNode *push(StackNode *stack, void *data);

BIN
stack.o Normal file

Binary file not shown.

68
test_bintree.c Normal file
View File

@ -0,0 +1,68 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bintree.h"
// Hilfsfunktion: Vergleich von int
static int compareInt(const void *a, const void *b) {
int ia = *(const int *)a;
int ib = *(const int *)b;
if (ia < ib) return -1;
if (ia > ib) return 1;
return 0;
}
int main() {
printf("===== TEST BINTREE =====\n");
TreeNode *root = NULL;
int isDup;
// Test 1: addToTree - Einfügen eindeutiger Werte
int val1 = 10, val2 = 5, val3 = 15;
root = addToTree(root, &val1, sizeof(int), compareInt, &isDup);
if (isDup != 0) { printf("FAIL: Erstes Einfügen sollte kein Duplikat sein\n"); return 1; }
root = addToTree(root, &val2, sizeof(int), compareInt, &isDup);
if (isDup != 0) { printf("FAIL: Zweites Einfügen sollte kein Duplikat sein\n"); return 1; }
root = addToTree(root, &val3, sizeof(int), compareInt, &isDup);
if (isDup != 0) { printf("FAIL: Drittes Einfügen sollte kein Duplikat sein\n"); return 1; }
printf("PASS: addToTree - eindeutige Werte\n");
// Test 2: addToTree - Duplikat hinzufügen
int dup = 10;
root = addToTree(root, &dup, sizeof(int), compareInt, &isDup);
if (isDup != 1) { printf("FAIL: Duplikat sollte erkannt werden\n"); return 1; }
printf("PASS: addToTree - Duplikat erkannt\n");
// Test 3: treeSize
unsigned int size = treeSize(root);
if (size != 3) { printf("FAIL: treeSize sollte 3 sein, ist %u\n", size); return 1; }
printf("PASS: treeSize\n");
// Test 4: nextTreeData - Iteration (in-order: 5, 10, 15)
void *data = nextTreeData(root);
if (data == NULL || *(int*)data != 5) { printf("FAIL: Erstes Element sollte 5 sein\n"); return 1; }
data = nextTreeData(NULL);
if (data == NULL || *(int*)data != 10) { printf("FAIL: Zweites Element sollte 10 sein\n"); return 1; }
data = nextTreeData(NULL);
if (data == NULL || *(int*)data != 15) { printf("FAIL: Drittes Element sollte 15 sein\n"); return 1; }
data = nextTreeData(NULL);
if (data != NULL) { printf("FAIL: Nach dem letzten Element sollte NULL kommen\n"); return 1; }
printf("PASS: nextTreeData - Iteration\n");
// Test 5: clearTree
clearTree(root);
root = NULL;
// Nach clearTree sollte treeSize 0 sein (aber da root NULL, testen wir indirekt)
printf("PASS: clearTree (no crash)\n");
// Test 6: Leerer Baum
size = treeSize(NULL);
if (size != 0) { printf("FAIL: Leerer Baum sollte Größe 0 haben\n"); return 1; }
data = nextTreeData(NULL);
if (data != NULL) { printf("FAIL: Leerer Baum sollte NULL zurückgeben\n"); return 1; }
printf("PASS: Leerer Baum\n");
printf("ALL BINTREE TESTS PASSED\n");
return 0;
}

BIN
test_bintree.exe Normal file

Binary file not shown.

60
test_numbers.c Normal file
View File

@ -0,0 +1,60 @@
#include <stdio.h>
#include <stdlib.h>
#include "numbers.h"
// Einfache Funktion, um zu zählen, wie oft eine Zahl im Array vorkommt
int countOccurrences(const unsigned int *arr, unsigned int len, unsigned int value) {
int count = 0;
for (unsigned int i = 0; i < len; i++) {
if (arr[i] == value) count++;
}
return count;
}
// Testfunktion für createNumbers und getDuplicate
void testNumbers(unsigned int len) {
printf("Teste mit Laenge %u:\n", len);
// Erstelle Zahlenarray
unsigned int *numbers = createNumbers(len);
if (numbers == NULL) {
printf("Fehler: Konnte Array nicht erstellen.\n");
return;
}
// Gib Array aus
printf("Generierte Zahlen: ");
for (unsigned int i = 0; i < len; i++) {
printf("%u ", numbers[i]);
}
printf("\n");
// Finde Duplikat
unsigned int duplicate = getDuplicate(numbers, len);
printf("Gefundenes Duplikat: %u\n", duplicate);
// Überprüfe, ob es genau zweimal vorkommt
int occ = countOccurrences(numbers, len, duplicate);
if (occ == 2) {
printf("Korrekte Überprüfung: %u kommt genau zweimal vor.\n", duplicate);
} else {
printf("Fehler: %u kommt %d mal vor (sollte 2 sein).\n", duplicate, occ);
}
// Speicher freigeben
free(numbers);
printf("\n");
}
int main() {
printf("Testprogramm für numbers.c\n");
printf("=========================\n\n");
// Teste mit verschiedenen Längen
testNumbers(5);
testNumbers(10);
testNumbers(20);
printf("Tests abgeschlossen.\n");
return 0;
}

BIN
test_numbers.exe Normal file

Binary file not shown.

36
test_stack.c Normal file
View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
int main() {
printf("===== TEST STACK =====\n");
StackNode *s = NULL;
// Test push
int a = 10, b = 20, c = 30;
s = push(s, &a);
s = push(s, &b);
s = push(s, &c);
if (*(int*)top(s) != 30) {
printf("FAIL: top() should return 30\n");
return 1;
}
printf("PASS: push + top\n");
// Test pop
s = pop(s);
if (*(int*)top(s) != 20) {
printf("FAIL: pop() should remove 30\n");
return 1;
}
printf("PASS: pop\n");
// Clear
clearStack(s);
printf("PASS: clearStack (no crash)\n");
printf("ALL STACK TESTS PASSED\n");
return 0;
}

BIN
test_stack.exe Normal file

Binary file not shown.

38
timer.c
View File

@ -1,37 +1,6 @@
#include <time.h>
#include "timer.h"
#if __APPLE__
#include <sys/time.h>
static struct timespec start = {0, 0};
// Starts the timer.
void startTimer()
{
clock_gettime(CLOCK_MONOTONIC, &start);
}
// Returns the time in seconds since startTimer() was called.
double stopTimer()
{
struct timespec end;
clock_gettime(CLOCK_MONOTONIC, &end);
unsigned long long delta_us = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_nsec - start.tv_nsec) / 1000;
double measuredSeconds = (double)delta_us / 1000000.;
if(start.tv_nsec > 0) {
start.tv_nsec = 0;
start.tv_sec = 0;
}
else
measuredSeconds = -1;
return measuredSeconds;
}
#else
#include <time.h>
static clock_t startClocks = 0;
// Starts the timer.
@ -49,7 +18,6 @@ double stopTimer()
startClocks = 0;
else
measuredSeconds = -1;
return measuredSeconds;
}
#endif
}

BIN
timer.o Normal file

Binary file not shown.

View File

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

3
unity/makefile Normal file
View File

@ -0,0 +1,3 @@
unity: unity.c unity.h
gcc -c -Wall -o unity.o unity.c
ar rcs libunity.a unity.o

Binary file not shown.