Compare commits

...

19 Commits

Author SHA1 Message Date
Simon May
6b3294d40b Merge branch 'simons_weg' of https://git.efi.th-nuernberg.de/gitea/hallerni98888/info2Praktikum-DobleSpiel into simons_weg 2025-12-09 17:04:14 +01:00
Simon May
a018971c04 sync 2025-12-09 17:02:55 +01:00
35b09294bc fixed filling the array 2025-12-09 15:30:54 +01:00
Simon May
fc3508140a simons wirre gedanken 2025-12-02 17:06:00 +01:00
Simon May
a3b951d0a9 aufräumen 2025-12-02 14:53:46 +01:00
f8c297f84d test_bintree edited 2025-12-02 14:47:52 +01:00
5b576589e3 Merge branch 'main' into temp 2025-12-02 14:16:05 +01:00
bf0a0b3f40 ??? 2025-12-02 13:51:42 +01:00
d54dd3eb6f added test_bintree 2025-12-02 13:43:25 +01:00
Simon May
8051686a37 tests added 2025-12-02 13:09:44 +01:00
Simon
39965a95c4 numbers done/ test missing 2025-12-01 17:50:00 +01:00
Simon May
8b0fa4601a Merge branch 'main' of https://git.efi.th-nuernberg.de/gitea/hallerni98888/info2Praktikum-DobleSpiel 2025-11-25 14:12:31 +01:00
Simon May
f59489779b destroy everythingMerge branch 'nick_branch' 2025-11-25 14:03:44 +01:00
31a76162ee Merge pull request 'simons_zweig' (#1) from simons_zweig into main
Reviewed-on: hallerni98888/info2Praktikum-DobleSpiel#1
2025-11-25 12:55:32 +00:00
b76ffa054a added clear top top test 2025-11-24 18:49:39 +01:00
Simon
4cfe6d9c50 added test_push and fixed stack cast 2025-11-24 17:53:43 +01:00
Simon
82c72eaf81 first tests 2025-11-24 16:05:31 +01:00
Simon May
a027c070d2 funktionen ergänzt 2025-11-18 17:13:44 +01:00
Simon May
94517bf236 gitignore 2025-11-18 15:32:49 +01:00
11 changed files with 602 additions and 88 deletions

11
.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
doble_initial.exe
highscores.txt
runStackTest.exe
stack.o
runNumbersTest.exe
numbers.o
.vscode/launch.json
.vscode/settings.json
*.o
*.exe
runBintreeTest

View File

@ -2,17 +2,35 @@
#include "stack.h" #include "stack.h"
#include "bintree.h" #include "bintree.h"
//TODO: binären Suchbaum implementieren static StackNode *stack;
// TODO: binären Suchbaum implementieren
/* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv), /* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv),
* `clearTree`: gibt den gesamten Baum frei (rekursiv), * `clearTree`: gibt den gesamten Baum frei (rekursiv),
* `treeSize`: zählt die Knoten im Baum (rekursiv), * `treeSize`: zählt die Knoten im Baum (rekursiv),
* `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. */ * `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 // 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). // if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added).
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate) TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate)
{ {
if (root == NULL)
{
TreeNode *newNode = malloc(sizeof(TreeNode));
newNode->data = malloc(dataSize);
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
if (compareFct(root->data, data) < 0)
{
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
}
else if (compareFct(root->data, data) > 0)
{
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. // 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.
@ -20,17 +38,36 @@ TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFc
// push the top node and push all its left nodes. // push the top node and push all its left nodes.
void *nextTreeData(TreeNode *root) void *nextTreeData(TreeNode *root)
{ {
return NULL;
} }
// Releases all memory resources (including data copies). // Releases all memory resources (including data copies).
void clearTree(TreeNode *root) void clearTree(TreeNode *root)
{ {
if (root == NULL)
{
return;
}
if (root->left != NULL)
{
clearTree(root->left);
free(root->left);
root->left = NULL;
}
if (root->right != NULL)
{
clearTree(root->right);
free(root->right);
root->right = NULL;
}
root = NULL;
} }
// Returns the number of entries in the tree given by root. // Returns the number of entries in the tree given by root.
unsigned int treeSize(const TreeNode *root) unsigned int treeSize(const TreeNode *root)
{ {
return root == NULL ? 0 : treeSize(root->left) + treeSize(root->right) + 1;
} }

View File

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

108
makefile
View File

@ -1,49 +1,61 @@
CC = gcc CC = gcc
FLAGS = -g -Wall -lm FLAGS = -g -Wall -lm
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
include makefile_windows.variables include makefile_windows.variables
else else
UNAME = $(shell uname) UNAME = $(shell uname)
ifeq ($(UNAME),Linux) ifeq ($(UNAME),Linux)
include makefile_linux.variables include makefile_linux.variables
else else
include makefile_mac.variables include makefile_mac.variables
endif endif
endif endif
raylibfolder = ./raylib raylibfolder = ./raylib
unityfolder = ./unity unityfolder = ./unity
# -------------------------- # --------------------------
# Initiales Programm bauen (zum ausprobieren) # Initiales Programm bauen (zum ausprobieren)
# -------------------------- # --------------------------
doble_initial: doble_initial:
$(CC) -o doble_initial $(BINARIES)/libdoble_complete.a $(CC) -o doble_initial $(BINARIES)/libdoble_complete.a
# -------------------------- # --------------------------
# Selbst implementiertes Programm bauen # Selbst implementiertes Programm bauen
# -------------------------- # --------------------------
program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o
doble : main.o $(program_obj_files) doble : main.o $(program_obj_files)
$(CC) $(FLAGS) $^ -o doble $(CC) $(FLAGS) $^ -o doble
$(program_obj_filesobj_files): %.o: %.c $(program_obj_filesobj_files): %.o: %.c
$(CC) -c $(FLAGS) $^ -o $@ $(CC) -c $(FLAGS) $^ -o $@
# -------------------------- # --------------------------
# Unit Tests # Unit Tests
# -------------------------- # --------------------------
unitTests: unitTests: stack.o test_stack.c $(unityfolder)/unity.c
echo "needs to be implemented" $(CC) $(FLAGS) -I$(unityfolder) -o runStackTest test_stack.c stack.o $(unityfolder)/unity.c
# -------------------------- # --------------------------
# Clean # numbers.c Tests
# -------------------------- # --------------------------
clean: numbersTests: numbers.o test_numbers.c $(unityfolder)/unity.c
ifeq ($(OS),Windows_NT) $(CC) $(FLAGS) -I$(unityfolder) -o runNumbersTest test_numbers.c numbers.o $(unityfolder)/unity.c
del /f *.o doble
else # --------------------------
rm -f *.o doble # bintree.c Tests
# --------------------------
bintreeTests: bintree.o test_bintree.c $(unityfolder)/unity.c
$(CC) $(FLAGS) -I$(unityfolder) -o runBintreeTest test_bintree.c bintree.o $(unityfolder)/unity.c
# --------------------------
# Clean
# --------------------------
clean:
ifeq ($(OS),Windows_NT)
del /f *.o doble
else
rm -f *.o doble
endif endif

152
numbers.c
View File

@ -5,22 +5,166 @@
#include "numbers.h" #include "numbers.h"
#include "bintree.h" #include "bintree.h"
//TODO: getDuplicate und createNumbers implementieren // TODO: getDuplicate und createNumbers implementieren
/* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen. /* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen.
* Sicherstellen, dass beim Befüllen keine Duplikate entstehen. * Sicherstellen, dass beim Befüllen keine Duplikate entstehen.
* Duplizieren eines zufälligen Eintrags im Array. * Duplizieren eines zufälligen Eintrags im Array.
* in `getDuplicate()`: Sortieren des Arrays und Erkennen der doppelten Zahl durch Vergleich benachbarter Elemente. */ * 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 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 // Returns NULL on errors. Use your implementation of the binary search tree to check for possible duplicates while
// creating random numbers. // creating random numbers.
unsigned int checkArray(unsigned int *array, unsigned int len, unsigned int number)
{
int free = 1;
for (int i = 0; i < len; i++)
{
if (array[i] == number)
{
free = 0;
break;
}
}
return free;
}
unsigned int *createNumbers(unsigned int len) unsigned int *createNumbers(unsigned int len)
{ {
srand(time(NULL));
unsigned int *array = (unsigned int *)malloc(len * sizeof(unsigned int));
int randomNr, randomPos, filler;
if (array == NULL)
{
return NULL; // Fehler
}
for (int i = 0; i < len; i++)
{
array[i] = 0;
}
for (int i = 0; i < len; i++)
{
do
{
array[i] = (rand() % (2 * len))+ 1;
} while (!checkArray(array, i, array[i]));
}
randomPos = rand() % len;
randomNr = array[randomPos];
filler = randomPos;
while(filler == randomPos)
{
filler = rand() % len;
}
array[filler] = randomNr;
return array;
}
void merge(unsigned int arr[], unsigned int left, unsigned int mid, unsigned int right)
{
unsigned int i, j, k;
unsigned int n1 = mid - left + 1;
unsigned int n2 = right - mid;
// Create temporary arrays
unsigned int leftArr[n1], rightArr[n2];
// Copy data to temporary arrays
for (i = 0; i < n1; i++)
leftArr[i] = arr[left + i];
for (j = 0; j < n2; j++)
rightArr[j] = arr[mid + 1 + j];
// Merge the temporary arrays back into arr[left..right]
i = 0;
j = 0;
k = left;
while (i < n1 && j < n2)
{
if (leftArr[i] <= rightArr[j])
{
arr[k] = leftArr[i];
i++;
}
else
{
arr[k] = rightArr[j];
j++;
}
k++;
}
// Copy the remaining elements of leftArr[], if any
while (i < n1)
{
arr[k] = leftArr[i];
i++;
k++;
}
// Copy the remaining elements of rightArr[], if any
while (j < n2)
{
arr[k] = rightArr[j];
j++;
k++;
}
}
void mergeSort(unsigned int arr[], unsigned int left, unsigned int right)
{
if (left < right)
{
// Calculate the midpoint
unsigned int mid = left + (right - left) / 2;
// Sort first and second halves
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
// Merge the sorted halves
merge(arr, left, mid, right);
}
} }
// Returns only the only number in numbers which is present twice. Returns zero on errors. // Returns only the only number in numbers which is present twice. Returns zero on errors.
unsigned int getDuplicate(const unsigned int numbers[], unsigned int len) unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
{ {
unsigned int temp[len];
unsigned int duplicate = 0;
/*if(numbers == NULL || (sizeof(numbers) / sizeof(typeof(numbers)) != len))
{
return 0;S
}*/
for (int i = 0; i < len; i++)
{
temp[i] = numbers[i];
}
// Sorting arr using mergesort
mergeSort(temp, 0, len - 1);
for (int i = 0; i < len - 1; i++)
{
duplicate = temp[i];
if (duplicate == temp[i + 1])
{
break;
}
}
return duplicate;
} }

66
stack.c
View File

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

54
stack.h
View File

@ -1,25 +1,29 @@
#ifndef STACK_H #ifndef STACK_H
#define STACK_H #define STACK_H
/* A stack is a special type of queue which uses the LIFO (last in, first out) principle. /* A stack is a special type of queue which uses the LIFO (last in, first out) principle.
This means that with each new element all other elements are pushed deeper into the stack. This means that with each new element all other elements are pushed deeper into the stack.
The latest element is taken from the stack. */ The latest element is taken from the stack. */
#include <stdlib.h> #include <stdlib.h>
//TODO: passenden Datentyp als struct anlegen //TODO: passenden Datentyp als struct anlegen
typedef struct Node {
// Pushes data as pointer onto the stack. void *value;
StackNode *push(StackNode *stack, void *data); struct Node* next;
} StackNode;
// Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be
// freed by caller.) // Pushes data as pointer onto the stack.
StackNode *pop(StackNode *stack); StackNode *push(StackNode *stack, void *data);
// Returns the data of the top element. // Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be
void *top(StackNode *stack); // freed by caller.)
StackNode *pop(StackNode *stack);
// Clears stack and releases all memory.
void clearStack(StackNode *stack); // Returns the data of the top element.
void *top(StackNode *stack);
#endif
// Clears stack and releases all memory.
void clearStack(StackNode *stack);
#endif

80
test_bintree.c Normal file
View File

@ -0,0 +1,80 @@
#include <stdio.h>
#include <stdlib.h>
#include "bintree.h"
#include "unity.h"
void sizeTest()
{
TreeNode *root = (TreeNode *)malloc(sizeof(TreeNode));
TreeNode *node1 = (TreeNode *)malloc(sizeof(TreeNode));
TreeNode *node2 = (TreeNode *)malloc(sizeof(TreeNode));
int dataRoot = 2;
int dataNode1 = 1;
int dataNode2 = 3;
root->data = &dataRoot;
root->left = (TreeNode *)node1;
root->right = (TreeNode *)node2;
node1->data = &dataNode1;
node1->left = NULL;
node1->right = NULL;
node2->data = &dataNode2;
node2->left = NULL;
node2->right = NULL;
TEST_ASSERT_EQUAL_INT(3,treeSize(root));
}
void clearTest()
{
TreeNode *root = (TreeNode *)malloc(sizeof(TreeNode));
TreeNode *node1 = (TreeNode *)malloc(sizeof(TreeNode));
TreeNode *node2 = (TreeNode *)malloc(sizeof(TreeNode));
int dataRoot = 2;
int dataNode1 = 1;
int dataNode2 = 3;
root->data = &dataRoot;
root->left = (TreeNode *)node1;
root->right = (TreeNode *)node2;
node1->data = &dataNode1;
node1->left = NULL;
node1->right = NULL;
node2->data = &dataNode2;
node2->left = NULL;
node2->right = NULL;
TreeNode *ptr = root;
clearTree(ptr);
TEST_ASSERT_EQUAL_INT(0,treeSize(root));
}
void setUp(void)
{
// Falls notwendig, kann hier Vorbereitungsarbeit gemacht werden
}
void tearDown(void)
{
// Hier kann Bereinigungsarbeit nach jedem Test durchgeführt werden
}
int main()
{
UNITY_BEGIN();
printf("============================\nNumbers tests\n============================\n");
RUN_TEST(sizeTest);
RUN_TEST(clearTest);
return UNITY_END();
}

47
test_numbers.c Normal file
View File

@ -0,0 +1,47 @@
#include <stdio.h>
#include <stdlib.h>
#include "numbers.h"
#include "unity.h"
void createNumbersTest()
{
unsigned int *array;
unsigned int len = 6;
array = createNumbers(len);
for (int i = 0; i < len; i++)
{
printf("%u ", array[i]);
}
printf("\n");
TEST_ASSERT_NOT_NULL(array);
}
void duplicateTest()
{
unsigned int array[6] = {1, 4, 5, 2, 3, 1};
unsigned int len = 6;
TEST_ASSERT_EQUAL_INT(1, getDuplicate(array, len));
}
void setUp(void)
{
// Falls notwendig, kann hier Vorbereitungsarbeit gemacht werden
}
void tearDown(void)
{
// Hier kann Bereinigungsarbeit nach jedem Test durchgeführt werden
}
int main()
{
UNITY_BEGIN();
printf("============================\nNumbers tests\n============================\n");
RUN_TEST(createNumbersTest);
RUN_TEST(duplicateTest);
return UNITY_END();
}

112
test_stack.c Normal file
View File

@ -0,0 +1,112 @@
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
#include "unity.h"
void test_push(void)
{
StackNode *testNode;
int data = 1;
// Test für leeren Stack
testNode = push(NULL, &data);
TEST_ASSERT_NOT_NULL(&testNode);
TEST_ASSERT_NULL(testNode->next);
TEST_ASSERT_EQUAL_INT(1, testNode->value);
data = 2;
// Test für nicht leeren Stack
testNode = push(testNode, &data);
TEST_ASSERT_NOT_NULL(&testNode);
TEST_ASSERT_NOT_NULL(testNode->next);
TEST_ASSERT_NULL(testNode->next->next);
TEST_ASSERT_EQUAL_INT(1, testNode->value);
TEST_ASSERT_EQUAL_INT(2, testNode->next->value);
}
StackNode* setup(void *value, StackNode* next) {
StackNode* node = malloc(sizeof(StackNode)); // allocate memory on heap
if (node == NULL) {
perror("malloc failed");
exit(EXIT_FAILURE); // or handle the error differently
}
node->value = value;
node->next = next;
return node;
}
void test_pop(void)
{
StackNode* node2 = setup(3, NULL);
StackNode* node1 = setup(2, node2);
StackNode* header = setup(1, node1);
StackNode* temp;
temp = pop(header);
int after = 0;
while(temp)
{
after++;
temp = temp->next;
}
TEST_ASSERT_EQUAL_INT(2, after);
TEST_ASSERT_NULL(node1->next);
}
void test_top(void)
{
StackNode* node2 = setup(3, NULL);
StackNode* node1 = setup(2, node2);
StackNode* header = setup(1, node1);
int data = *(int *)top(header);
TEST_ASSERT_EQUAL_INT(node2->value, data);
}
void test_clear()
{
StackNode* node2 = setup(3, NULL);
StackNode* node1 = setup(2, node2);
StackNode* header = setup(1, node1);
StackNode* temp;
clearStack(header);
temp = header;
int after = 0;
while(temp)
{
after++;
temp = temp->next;
}
TEST_ASSERT_NULL(after);
}
void setUp(void)
{
// Falls notwendig, kann hier Vorbereitungsarbeit gemacht werden
}
void tearDown(void)
{
// Hier kann Bereinigungsarbeit nach jedem Test durchgeführt werden
}
int main()
{
UNITY_BEGIN();
printf("============================\nStack tests\n============================\n");
RUN_TEST(test_push);
RUN_TEST(test_pop);
RUN_TEST(test_top);
RUN_TEST(test_clear);
return UNITY_END();
}

10
unittest.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef UNITTTESTS_H
#define UNITTTESTS_H
#include <stdio.h>
typedef int (*UnitTestType)(void);
#define RUN_UNIT_TEST(fct) printf("%80s: %d\n", #fct, fct())
#endif