forked from freudenreichan/info2Praktikum-Wortsalat
Compare commits
8
Commits
3172ff8143
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c96e95db7a | ||
|
|
f6ee05cd0e | ||
|
|
74d4bd628c | ||
|
|
c0f26a5120 | ||
|
|
ee37124a05 | ||
|
|
e908fec8a3 | ||
|
|
83eb2bd50d | ||
|
|
fb2f92284e |
No files matched your search
+146
-5
@@ -6,12 +6,153 @@
|
|||||||
#define MAX_RAND_TRIES_PER_WORD 10
|
#define MAX_RAND_TRIES_PER_WORD 10
|
||||||
#define EMPTY_CHAR 0
|
#define EMPTY_CHAR 0
|
||||||
|
|
||||||
//TODO: Spiellogik implementieren:
|
// Hilfsfunktion 1: Sichere Längenermittlung mit Obergrenze
|
||||||
/* * Wörter aus der Wortliste zufällig horizontal oder vertikal platzieren
|
static size_t safeStrnlen(const char *str, size_t maxLen) //ermittelt die Wortlänge bis zur max. Grenze
|
||||||
* restliche Felder mit zufälligen Buchstaben füllen */
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
while (len < maxLen && str[len] != '\0') //ermittelt die max Länge und mit '\0' endet jedes Wort
|
||||||
|
{
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
// Creates the word salad by placing words randomly and filling empty spaces
|
// Hilfsfunktion2 : Prüft kollisionsfrei, ob ein Wort an die Position passt
|
||||||
|
// Arraygrößen (fieldLen, wordLen) werden explizit als Parameter übergeben
|
||||||
|
|
||||||
|
static int canPlaceWord(const char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN],
|
||||||
|
unsigned int fieldLen,
|
||||||
|
const char *word,
|
||||||
|
unsigned int wordLen,
|
||||||
|
unsigned int row,
|
||||||
|
unsigned int col,
|
||||||
|
int isVertical)
|
||||||
|
{
|
||||||
|
for (unsigned int k = 0; k < wordLen; k++) //Prüft ob das Wort in das 20x20 Feld passt
|
||||||
|
{
|
||||||
|
unsigned int r = isVertical ? (row + k) : row; //jeder Buchstabe berechnet wo er landet
|
||||||
|
unsigned int c = isVertical ? col : (col + k); //Reihe = row und Zeile = col bzw. coloumn
|
||||||
|
// Überlaufschutz: Innerhalb der Arraygrenzen bleiben
|
||||||
|
if (r >= fieldLen || c >= fieldLen)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
char cell = salad[r][c];
|
||||||
|
if (cell != EMPTY_CHAR && cell != word[k])
|
||||||
|
{
|
||||||
|
return 0; // Kollision mit einem anderen Buchstaben
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hilfsfunktion3: Schreibt das Wort in das Spielfeld
|
||||||
|
// Arraygrößen (fieldLen, wordLen) werden explizit als Parameter übergeben
|
||||||
|
static void placeWord(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN],
|
||||||
|
unsigned int fieldLen,
|
||||||
|
const char *word,
|
||||||
|
unsigned int wordLen,
|
||||||
|
unsigned int row,
|
||||||
|
unsigned int col,
|
||||||
|
int isVertical)
|
||||||
|
{
|
||||||
|
for (unsigned int k = 0; k < wordLen; k++) //im Endeffekt genau wie Hilfsfunktion 2
|
||||||
|
{
|
||||||
|
unsigned int r = isVertical ? (row + k) : row;
|
||||||
|
unsigned int c = isVertical ? col : (col + k);
|
||||||
|
if (r < fieldLen && c < fieldLen)
|
||||||
|
{
|
||||||
|
salad[r][c] = word[k]; //nur wird hier nicht überprüft sondern richtig geschrieben
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Erzeugt Wortsalat und platziert leere Felder mit random Buchstaben (Hauptfunktion)
|
||||||
int createWordSalad(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldLen, const char words[][MAX_WORD_LEN], unsigned int wordCount)
|
int createWordSalad(char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldLen, const char words[][MAX_WORD_LEN], unsigned int wordCount)
|
||||||
{
|
{
|
||||||
|
// Sicherheitsprüfung der übergebenen Parameter
|
||||||
|
if (salad == NULL || words == NULL || searchFieldLen == 0 || searchFieldLen > MAX_SEARCH_FIELD_LEN)
|
||||||
|
{
|
||||||
|
return -1; //falls keine Wörter übergeben, dann bricht Spiel ab
|
||||||
|
}
|
||||||
|
// Zufallsgenerator initialisieren
|
||||||
|
static int seeded = 0;
|
||||||
|
if (!seeded)
|
||||||
|
{
|
||||||
|
srand((unsigned int)time(NULL));
|
||||||
|
seeded = 1;
|
||||||
|
}
|
||||||
|
// 1. Spielfeld komplett mit EMPTY_CHAR leeren, es stehen überall danach nur noch '0'
|
||||||
|
for (unsigned int r = 0; r < searchFieldLen; r++)
|
||||||
|
{
|
||||||
|
for (unsigned int c = 0; c < searchFieldLen; c++)
|
||||||
|
{
|
||||||
|
salad[r][c] = EMPTY_CHAR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Sicherer lokaler Puffer für strncpy
|
||||||
|
char currentWord[MAX_WORD_LEN];
|
||||||
|
unsigned int placedCount = 0;
|
||||||
|
// 2. Wörter platzieren
|
||||||
|
for (unsigned int i = 0; i < wordCount; i++) //alle Wörter werden nacheinander eingearbeitet
|
||||||
|
{
|
||||||
|
// Wort sicher mit strncpy kopieren und terminieren, mit memset wird beim ersten Durchlauf genullt
|
||||||
|
memset(currentWord, 0, sizeof(currentWord));
|
||||||
|
strncpy(currentWord, words[i], MAX_WORD_LEN - 1);
|
||||||
|
currentWord[MAX_WORD_LEN - 1] = '\0'; //falls Wort zulange wieder mit '\0' Beenden erzwingen
|
||||||
|
unsigned int wordLen = (unsigned int)safeStrnlen(currentWord, MAX_WORD_LEN);
|
||||||
|
if (wordLen == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Falls das Wort länger als das Spielfeld ist, abbrechen
|
||||||
|
if (wordLen > searchFieldLen)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int placed = 0;
|
||||||
|
for (int attempt = 0; attempt < MAX_RAND_TRIES_PER_WORD; attempt++) //10 Versuche das Wort zu platzieren
|
||||||
|
{
|
||||||
|
// Richtung würfeln: 0 = Horizontal, 1 = Vertikal
|
||||||
|
int isVertical = rand() % 2; //hier entscheidet der Zufall ob row oder col
|
||||||
|
unsigned int row = 0;
|
||||||
|
unsigned int col = 0;
|
||||||
|
if (isVertical)
|
||||||
|
{
|
||||||
|
row = rand() % (searchFieldLen - wordLen + 1);
|
||||||
|
col = rand() % searchFieldLen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
row = rand() % searchFieldLen;
|
||||||
|
col = rand() % (searchFieldLen - wordLen + 1);
|
||||||
|
}
|
||||||
|
// Prüfen, ob das Wort passt, und platzieren
|
||||||
|
if (canPlaceWord(salad, searchFieldLen, currentWord, wordLen, row, col, isVertical))
|
||||||
|
{
|
||||||
|
placeWord(salad, searchFieldLen, currentWord, wordLen, row, col, isVertical);
|
||||||
|
placed = 1;
|
||||||
|
placedCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Wenn das Wort nach MAX_RAND_TRIES_PER_WORD Versuchen nicht platziert werden konnte
|
||||||
|
/*if (!placed) //ohne ! macht er 30 Wörter. Mit ! macht er 15 Wörter aber würde auch ohne platzierung aller Wörter starten
|
||||||
|
//lässt man das if ganz weg, geht es auch
|
||||||
|
{
|
||||||
|
placedCount++;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
// 3. Restliche Felder mit zufälligen Großbuchstaben ('A'-'Z') füllen
|
||||||
|
for (unsigned int r = 0; r < searchFieldLen; r++)
|
||||||
|
{
|
||||||
|
for (unsigned int c = 0; c < searchFieldLen; c++)
|
||||||
|
{
|
||||||
|
if (salad[r][c] == EMPTY_CHAR)
|
||||||
|
{
|
||||||
|
salad[r][c] = (char)('A' + (rand() % 26));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (int)placedCount; // Erfolg
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,51 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#define SPLIT " ,;\t\n\r" // \r ist Windows Zeilenende
|
||||||
|
|
||||||
|
int readWords(FILE *file, char words[][MAX_WORD_LEN], unsigned int maxWordCount)
|
||||||
|
{
|
||||||
|
char line[MAX_LINE_LEN];
|
||||||
|
int wordCount = 0; // als unsigned ausfuehren wegen maxWordCount vergleich??
|
||||||
|
|
||||||
|
if(file == NULL || words == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// zeilenweise lesen bis ende oder array voll
|
||||||
|
while(wordCount < maxWordCount && fgets(line, sizeof(line), file) != NULL)
|
||||||
|
{
|
||||||
|
// an trennzeichen zerlegen
|
||||||
|
char *token = strtok(line, SPLIT); // strtok: zerlegt string in tokens; *token zeigt auf anfangsadresse von einem wort
|
||||||
|
|
||||||
|
while(token != NULL && wordCount < maxWordCount)
|
||||||
|
{
|
||||||
|
// wort kopieren (max. MAX_WORD_LEN - 1 zeichen)
|
||||||
|
strncpy(words[wordCount], token, MAX_WORD_LEN - 1); // strncpy: kopiert alles wenn quelle kuerzer als MAX-WORD_LEN - 1 und haengt \0 an
|
||||||
|
|
||||||
|
// aller letztes Zeichen auf \0 setzen, falls dieses durch buchstaben belegt
|
||||||
|
words[wordCount][MAX_WORD_LEN - 1] = '\0';
|
||||||
|
|
||||||
|
// wort in grossbuchstaben umwandeln
|
||||||
|
for(int i = 0; words[wordCount][i] != '\0'; i++)
|
||||||
|
{
|
||||||
|
words[wordCount][i] = (char)toupper((unsigned char)words[wordCount][i]); // unsigned char, weil umlaute über 127 gehen können und dann negativ werden wuerden
|
||||||
|
}
|
||||||
|
|
||||||
|
wordCount++;
|
||||||
|
|
||||||
|
// naechstes wort derselben zeile
|
||||||
|
token = strtok(NULL, SPLIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return wordCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
// Trennzeichen zwischen Woertern (inkl. \r fuer Windows-Zeilenenden)
|
// Trennzeichen zwischen Woertern (inkl. \r fuer Windows-Zeilenenden)
|
||||||
#define DELIMITERS " ,;\t\r\n"
|
#define DELIMITERS " ,;\t\r\n"
|
||||||
|
|
||||||
@@ -56,3 +101,4 @@ int readWords(FILE *file, char words[][MAX_WORD_LEN], unsigned int maxWordCount)
|
|||||||
|
|
||||||
return (int)wordCount;
|
return (int)wordCount;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|||||||
Reference in new issue
Block a user