numbers.c bintree.c änderungen
This commit is contained in:
parent
d9222b83b4
commit
799667ed1c
72
bintree.c
72
bintree.c
@ -13,34 +13,50 @@
|
||||
// ordering. Accepts duplicates if isDuplicate is NULL, otherwise ignores
|
||||
// duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added).
|
||||
|
||||
TreeNode *createTreeNode(const void *data, size_t dataSize) {
|
||||
TreeNode *node =
|
||||
malloc(sizeof(TreeNode)); // Speicher für neuen Knoten reservieren
|
||||
if (node == NULL)
|
||||
return NULL; // Abbrechen bei Fehler
|
||||
|
||||
node->data = malloc(dataSize); // Speicher für Daten reservieren
|
||||
if (node->data == NULL) {
|
||||
free(node);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(node->data, data, dataSize); // Standardfunktion string.h, kopiert
|
||||
// size bytes von data nach node->data,
|
||||
// daten dürfen sich nicht überschneiden
|
||||
// speichern der Daten in node->data
|
||||
node->left = NULL; // Kinder sind NULL
|
||||
node->right = NULL;
|
||||
return node;
|
||||
}
|
||||
|
||||
TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize,
|
||||
CompareFctType compareFct, int *isDuplicate) {
|
||||
|
||||
// isDuplicate initialisieren (auf 0 setzen)
|
||||
// isDuplicate initialisieren (auf 0 setzen), verhindert Änderung am Baum
|
||||
if (isDuplicate) {
|
||||
*isDuplicate = 0;
|
||||
}
|
||||
} // bei 0: neuer Wert wurde eingefügt, bei 1: Wert war bereits im Baum
|
||||
|
||||
// leerer Baum
|
||||
if (root == NULL) {
|
||||
TreeNode *node = malloc(sizeof(TreeNode));
|
||||
node->data = malloc(dataSize);
|
||||
memcpy(node->data, data, dataSize);
|
||||
node->left = NULL;
|
||||
node->right = NULL;
|
||||
return node;
|
||||
return createTreeNode(data, dataSize);
|
||||
}
|
||||
|
||||
// mit compareFct <0 links >0 rechts =0 Duplikat
|
||||
int cmp = compareFct(data, root->data);
|
||||
int compare = compareFct(data, root->data);
|
||||
|
||||
if (cmp < 0) {
|
||||
if (compare < 0) { // Eintrag links
|
||||
root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate);
|
||||
} else if (cmp > 0) {
|
||||
} else if (compare > 0) { // Eintrag rechts
|
||||
root->right =
|
||||
addToTree(root->right, data, dataSize, compareFct, isDuplicate);
|
||||
} else {
|
||||
// isDuplicate auf 1 setzen
|
||||
} else { // Duplikat
|
||||
// isDuplicate auf 1 setzen, keine Änderung am Baum
|
||||
if (isDuplicate) {
|
||||
*isDuplicate = 1;
|
||||
}
|
||||
@ -54,40 +70,42 @@ TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize,
|
||||
// the root node and all left nodes first. On returning the next element, push
|
||||
// the top node and push all its left nodes.
|
||||
void *nextTreeData(TreeNode *root) {
|
||||
static StackNode *stack = NULL;
|
||||
static StackNode *stack = NULL; // static -> behält Wert bei mehreren Aufrufen
|
||||
|
||||
// Neue Iteration starten
|
||||
if (root != NULL) {
|
||||
clearStack(&stack);
|
||||
clearStack(&stack); // alte Stack-Inhalte werden gelöscht
|
||||
|
||||
TreeNode *curr = root;
|
||||
while (curr != NULL) {
|
||||
TreeNode *currentNode = root;
|
||||
while (currentNode !=
|
||||
NULL) { // alle linken Knoten werden vom root an auf den Stack gelegt
|
||||
StackNode *oldStack = stack;
|
||||
StackNode *newStack = push(stack, curr);
|
||||
StackNode *newStack = push(stack, currentNode);
|
||||
if (newStack == oldStack)
|
||||
return NULL; // push fehlgeschlagen
|
||||
stack = newStack;
|
||||
curr = curr->left;
|
||||
currentNode = currentNode->left;
|
||||
}
|
||||
}
|
||||
if (stack == NULL)
|
||||
return NULL; // alles durchlaufen
|
||||
return NULL; // wenn Stack leer ist sind keine Elemente mehr vorhanden,
|
||||
// Iteration beendet
|
||||
|
||||
// Oberstes Element abrufen
|
||||
TreeNode *node = (TreeNode *)top(stack);
|
||||
// oberster Knoten vom Stack
|
||||
TreeNode *node = top(stack);
|
||||
stack = pop(stack);
|
||||
|
||||
// Rechten Teilbaum pushen
|
||||
TreeNode *curr = node->right;
|
||||
while (curr != NULL) {
|
||||
TreeNode *currentNode = node->right;
|
||||
while (currentNode != NULL) {
|
||||
StackNode *oldStack = stack;
|
||||
StackNode *newStack = push(stack, curr);
|
||||
StackNode *newStack = push(stack, currentNode);
|
||||
if (newStack == oldStack)
|
||||
return NULL; // push fehlgeschlagen
|
||||
stack = newStack;
|
||||
curr = curr->left;
|
||||
currentNode = currentNode->left;
|
||||
}
|
||||
return node->data;
|
||||
return node->data; // Pointer auf Daten
|
||||
}
|
||||
|
||||
// Releases all memory resources (including data copies).
|
||||
|
||||
@ -11,6 +11,8 @@ typedef struct node {
|
||||
struct node *right;
|
||||
} TreeNode;
|
||||
|
||||
TreeNode *createTreeNode(const void *data, size_t dataSize);
|
||||
|
||||
// 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).
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
Kristin;49209
|
||||
Kristin;9959
|
||||
Kristin;9944
|
||||
Kristin;7947
|
||||
Kristin;6962
|
||||
Kristin;5987
|
||||
Kristin;5975
|
||||
krisp;4986
|
||||
krisp;4985
|
||||
Kristin;4972
|
||||
krisp;29797
|
||||
krisp;29792
|
||||
Kristin;29782
|
||||
Kristin;19943
|
||||
krisp;19934
|
||||
krisp;19916
|
||||
kristin;19861
|
||||
Kristin;19858
|
||||
krisp;19460
|
||||
|
||||
132
main.c
132
main.c
@ -1,90 +1,88 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "highscore.h"
|
||||
#include "numbers.h"
|
||||
#include "timer.h"
|
||||
#include "highscore.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
// Read an unsigned integer from stdin with prompt (retries until valid).
|
||||
int inputNumber(const char *promptText)
|
||||
{
|
||||
unsigned int number;
|
||||
int numberOfInputs = 0;
|
||||
int inputNumber(const char *promptText) {
|
||||
unsigned int number;
|
||||
int numberOfInputs = 0;
|
||||
|
||||
while(numberOfInputs != 1)
|
||||
{
|
||||
printf("%s", promptText);
|
||||
numberOfInputs = scanf("%u", &number);
|
||||
while(getchar() != '\n') {} // clear input buffer
|
||||
}
|
||||
while (numberOfInputs != 1) {
|
||||
printf("%s", promptText);
|
||||
numberOfInputs = scanf("%u", &number);
|
||||
while (getchar() != '\n') {
|
||||
} // clear input buffer
|
||||
}
|
||||
|
||||
return number;
|
||||
return number;
|
||||
}
|
||||
|
||||
// Print an array of numbers.
|
||||
void showNumbers(const unsigned int *numbers, unsigned int len)
|
||||
{
|
||||
if(numbers != NULL)
|
||||
{
|
||||
printf("Numbers:");
|
||||
void showNumbers(const unsigned int *numbers, unsigned int len) {
|
||||
if (numbers != NULL) {
|
||||
printf("Numbers:");
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
printf(" %5d", numbers[i]);
|
||||
for (int i = 0; i < len; i++)
|
||||
printf(" %5d", numbers[i]);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Main game loop: generate numbers, ask user for duplicate, measure time, update highscores.
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int exitCode = EXIT_FAILURE;
|
||||
// Main game loop: generate numbers, ask user for duplicate, measure time,
|
||||
// update highscores.
|
||||
int main(int argc, char *argv[]) {
|
||||
srand(time(NULL)); // seed für srand
|
||||
int exitCode = EXIT_FAILURE;
|
||||
|
||||
if(argc != 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <player name>\n", argv[0]);
|
||||
exitCode = EXIT_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *highscorePath = "highscores.txt";
|
||||
const char *playerName = argv[1];
|
||||
unsigned int *numbers = NULL;
|
||||
unsigned int duplicate = 0;
|
||||
double measuredSeconds;
|
||||
unsigned int userInput;
|
||||
unsigned int numberOfElements = 0;
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s <player name>\n", argv[0]);
|
||||
exitCode = EXIT_FAILURE;
|
||||
} else {
|
||||
const char *highscorePath = "highscores.txt";
|
||||
const char *playerName = argv[1];
|
||||
unsigned int *numbers = NULL;
|
||||
unsigned int duplicate = 0;
|
||||
double measuredSeconds;
|
||||
unsigned int userInput;
|
||||
unsigned int numberOfElements = 0;
|
||||
|
||||
// ask until valid number of elements (3..1000)
|
||||
while(numberOfElements < 3 || numberOfElements > 1000)
|
||||
numberOfElements = inputNumber("Wie viele Zahlen sollen gezeigt werden: ");
|
||||
// ask until valid number of elements (3..1000)
|
||||
while (numberOfElements < 3 || numberOfElements > 1000)
|
||||
numberOfElements =
|
||||
inputNumber("Wie viele Zahlen sollen gezeigt werden: ");
|
||||
|
||||
// create numbers and show them
|
||||
numbers = createNumbers(numberOfElements);
|
||||
showNumbers(numbers, numberOfElements);
|
||||
// create numbers and show them
|
||||
numbers = createNumbers(numberOfElements);
|
||||
showNumbers(numbers, numberOfElements);
|
||||
|
||||
// measure time while user guesses the duplicate
|
||||
startTimer();
|
||||
userInput = inputNumber("Welche Zahl kommt doppelt vor: ");
|
||||
measuredSeconds = stopTimer();
|
||||
// measure time while user guesses the duplicate
|
||||
startTimer();
|
||||
userInput = inputNumber("Welche Zahl kommt doppelt vor: ");
|
||||
measuredSeconds = stopTimer();
|
||||
|
||||
duplicate = getDuplicate(numbers, numberOfElements);
|
||||
duplicate = getDuplicate(numbers, numberOfElements);
|
||||
|
||||
// check result and update highscores
|
||||
if(userInput == duplicate)
|
||||
{
|
||||
int score = addHighscore(playerName, measuredSeconds, numberOfElements);
|
||||
printf("Sie haben die korrekte Zahl in %.6lf Sekunde(n) gefunden und %u Punkte erzielt.\n", measuredSeconds, score);
|
||||
}
|
||||
else
|
||||
printf("Leider ist %u nicht korrekt. Richtig waere %u gewesen.\n", userInput, duplicate);
|
||||
// check result and update highscores
|
||||
if (userInput == duplicate) {
|
||||
int score = addHighscore(playerName, measuredSeconds, numberOfElements);
|
||||
printf("Sie haben die korrekte Zahl in %.6lf Sekunde(n) gefunden und %u "
|
||||
"Punkte erzielt.\n",
|
||||
measuredSeconds, score);
|
||||
} else
|
||||
printf("Leider ist %u nicht korrekt. Richtig waere %u gewesen.\n",
|
||||
userInput, duplicate);
|
||||
|
||||
loadHighscores(highscorePath);
|
||||
showHighscores();
|
||||
saveHighscores(highscorePath);
|
||||
clearHighscores();
|
||||
loadHighscores(highscorePath);
|
||||
showHighscores();
|
||||
saveHighscores(highscorePath);
|
||||
clearHighscores();
|
||||
|
||||
exitCode = EXIT_SUCCESS;
|
||||
}
|
||||
exitCode = EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
return exitCode;
|
||||
}
|
||||
102
numbers.c
102
numbers.c
@ -3,18 +3,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
int compareUnsignedInt(const void *a, const void *b) {
|
||||
unsigned int x = *(unsigned int *)a;
|
||||
unsigned int y = *(unsigned int *)b;
|
||||
|
||||
if (x < y)
|
||||
return -1;
|
||||
if (x > y)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: getDuplicate und createNumbers implementieren
|
||||
/**Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an
|
||||
@ -27,65 +15,77 @@ int compareUnsignedInt(const void *a, const void *b) {
|
||||
// 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.
|
||||
|
||||
// vergleicht zwei Werte: a<b: -1 a>b: 1 a=b: 0
|
||||
int compareUnsignedInt(const void *a, const void *b) {
|
||||
unsigned int x = *(unsigned int *)a;
|
||||
unsigned int y = *(unsigned int *)b;
|
||||
return (x < y) ? -1 : (x > y);
|
||||
}
|
||||
|
||||
unsigned int *createNumbers(unsigned int len) {
|
||||
if (len < 2)
|
||||
if (len < 2) // Duplikat bei zwei Einträgen sinnlos
|
||||
return NULL;
|
||||
|
||||
unsigned int *arr = malloc(sizeof(unsigned int) * len);
|
||||
if (!arr)
|
||||
unsigned int *numbersArray = malloc(
|
||||
sizeof(unsigned int) * len); // Speicher für das Ausgabearray reservieren:
|
||||
// Größe eines Eintrags * Größe des Arrays
|
||||
if (!numbersArray) // Speicher konnte nicht reserviert werden
|
||||
return NULL;
|
||||
|
||||
TreeNode *root = NULL;
|
||||
srand((unsigned int)time(NULL));
|
||||
TreeNode *root =
|
||||
NULL; // Binärbaum zum Generieren der Zufallszahlen ohne Duplikate
|
||||
|
||||
for (unsigned int i = 0; i < len - 1; i++) {
|
||||
unsigned int num;
|
||||
for (unsigned int i = 0; i < len; i++) {
|
||||
unsigned int currentNumber;
|
||||
int isDuplicate;
|
||||
|
||||
do {
|
||||
num = (rand() % (2 * len)) + 1;
|
||||
do { // mindestens eine Zufallszahl erzeugen
|
||||
currentNumber = (rand() % (2 * len)) + 1; // Zahlenbereich 1 bis 2*len
|
||||
isDuplicate = 0;
|
||||
|
||||
root = addToTree(root, &num, sizeof(unsigned int), compareUnsignedInt,
|
||||
&isDuplicate);
|
||||
|
||||
} while (isDuplicate); // nur akzeptieren, wenn eindeutig
|
||||
|
||||
arr[i] = num;
|
||||
root = addToTree(root, ¤tNumber, sizeof(unsigned int),
|
||||
compareUnsignedInt,
|
||||
&isDuplicate); // compareUnsignedInt wird zum Verwenden
|
||||
// bei Vergleichen übergeben
|
||||
} while (isDuplicate); // wenn isDuplicate gesetzt wird, muss eine neue Zahl
|
||||
// erzeugt werden, die Schleife wird wiederholt
|
||||
numbersArray[i] = currentNumber;
|
||||
}
|
||||
|
||||
// Jetzt gezielt EIN Duplikat erzeugen
|
||||
unsigned int duplicateIndex = rand() % (len - 1);
|
||||
arr[len - 1] = arr[duplicateIndex];
|
||||
// Ein zufälliges Duplikat erzeugen
|
||||
unsigned int duplicateIndex =
|
||||
rand() % len; // Index des Duplikats per Zufall bestimmen
|
||||
unsigned int newIndex;
|
||||
do {
|
||||
newIndex = rand() % len;
|
||||
} while (newIndex == duplicateIndex); // zweiten Index bestimmen, der nicht
|
||||
// mit dem ersten übereinstimmt
|
||||
|
||||
clearTree(root);
|
||||
return arr;
|
||||
numbersArray[newIndex] =
|
||||
numbersArray[duplicateIndex]; // Wert vom ersten Index kopieren
|
||||
|
||||
clearTree(root); // Speicher wieder freigeben, wird nicht mehr benötigt
|
||||
return numbersArray;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (!numbers || len < 2)
|
||||
return 0;
|
||||
return NULL; // Fehlerhaftes Array
|
||||
|
||||
unsigned int *copy = malloc(sizeof(unsigned int) * len);
|
||||
if (!copy)
|
||||
return 0;
|
||||
TreeNode *root = NULL; // neuer Baum
|
||||
unsigned int duplicateValue = 0;
|
||||
|
||||
memcpy(copy, numbers, sizeof(unsigned int) * len);
|
||||
|
||||
// Sortierung
|
||||
qsort(copy, len, sizeof(unsigned int), compareUnsignedInt);
|
||||
|
||||
// Duplikat finden: zwei gleiche nebeneinander
|
||||
unsigned int duplicate = 0;
|
||||
for (unsigned int i = 0; i < len - 1; i++) {
|
||||
if (copy[i] == copy[i + 1]) {
|
||||
duplicate = copy[i];
|
||||
for (unsigned int i = 0; i < len; i++) {
|
||||
int isDuplicate = 0;
|
||||
root = addToTree(root, &numbers[i], sizeof(unsigned int),
|
||||
compareUnsignedInt, &isDuplicate);
|
||||
if (isDuplicate) {
|
||||
duplicateValue = numbers[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(copy);
|
||||
return duplicate;
|
||||
clearTree(root);
|
||||
return duplicateValue;
|
||||
}
|
||||
|
||||
12
numbers.h
12
numbers.h
@ -1,12 +1,16 @@
|
||||
#ifndef NUMBERS_H
|
||||
#define NUMBERS_H
|
||||
|
||||
// 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.
|
||||
int compareUnsignedInt(const void *a, const void *b);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
#endif
|
||||
@ -4,6 +4,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "bintree.h"
|
||||
|
||||
int compareUnsignedInt(const void *a, const void *b) {
|
||||
unsigned int x = *(unsigned int *)a;
|
||||
unsigned int y = *(unsigned int *)b;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user