Eigenes Target erstellen, Wörter können noch nicht geplaced werden

This commit is contained in:
Kristin Hofmann 2025-10-24 16:13:46 +02:00
parent 6d28593862
commit f3aa848a06
7 changed files with 485 additions and 449 deletions

View File

@ -1,104 +1,105 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "unity.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "input.h"
#include "game.h"
#include "input.h"
// ANSI Escape Codes für Farben
// Hinweis: damit das in CLion mit der integrierten Konsole/Output funktioniert, muss man auf die Run-Config gehen und
// das Häkchen bei 'emulate terminal in the output console' setzen
// (s. auch: https://stackoverflow.com/questions/32742850/how-to-show-colored-console-output-in-clion)
#define RESET "\033[0m"
#define GREEN "\033[32m"
#define RED "\033[31m"
#define YELLOW "\033[33m"
#define CYAN "\033[36m"
#define BOLD "\033[1m"
// Hinweis: damit das in CLion mit der integrierten Konsole/Output funktioniert,
// muss man auf die Run-Config gehen und das Häkchen bei 'emulate terminal in
// the output console' setzen (s. auch:
// https://stackoverflow.com/questions/32742850/how-to-show-colored-console-output-in-clion)
#define RESET "\033[0m"
#define GREEN "\033[32m"
#define RED "\033[31m"
#define YELLOW "\033[33m"
#define CYAN "\033[36m"
#define BOLD "\033[1m"
// Eine Funktion, um die Test-Ergebnisse zu färben
void print_test_result(int result) {
if (result == 0) {
// Test war erfolgreich
printf(GREEN "OK\n" RESET);
} else {
// Test ist fehlgeschlagen
printf(RED "FAILED\n" RESET);
}
if (result == 0) {
// Test war erfolgreich
printf(GREEN "OK\n" RESET);
} else {
// Test ist fehlgeschlagen
printf(RED "FAILED\n" RESET);
}
}
// ---------- Tests für input.c ----------
void test_readWords_simple(void) {
FILE *f = fopen("testwords_simple.txt", "r");
FILE *f = fopen("testwords_simple.txt", "r");
char words[10][MAX_WORD_LEN];
int count = readWords(f, words, 10);
fclose(f);
char words[10][MAX_WORD_LEN];
int count = readWords(f, words, 10);
fclose(f);
TEST_ASSERT_EQUAL_INT(3, count);
TEST_ASSERT_EQUAL_STRING("APFEL", words[0]);
TEST_ASSERT_EQUAL_STRING("BANANE", words[1]);
TEST_ASSERT_EQUAL_STRING("KIWI", words[2]);
TEST_ASSERT_EQUAL_INT(3, count);
TEST_ASSERT_EQUAL_STRING("APFEL", words[0]);
TEST_ASSERT_EQUAL_STRING("BANANE", words[1]);
TEST_ASSERT_EQUAL_STRING("KIWI", words[2]);
}
void test_readWords_with_delimiters(void) {
FILE *f = fopen("testwords_delims.txt", "r");
FILE *f = fopen("testwords_delims.txt", "r");
char words[10][MAX_WORD_LEN];
int count = readWords(f, words, 10);
fclose(f);
char words[10][MAX_WORD_LEN];
int count = readWords(f, words, 10);
fclose(f);
TEST_ASSERT_EQUAL_INT(3, count);
TEST_ASSERT_EQUAL_STRING("HUND", words[0]);
TEST_ASSERT_EQUAL_STRING("KATZE", words[1]);
TEST_ASSERT_EQUAL_STRING("MAUS", words[2]);
TEST_ASSERT_EQUAL_INT(3, count);
TEST_ASSERT_EQUAL_STRING("HUND", words[0]);
TEST_ASSERT_EQUAL_STRING("KATZE", words[1]);
TEST_ASSERT_EQUAL_STRING("MAUS", words[2]);
}
void test_readWords_empty_file(void) {
FILE *f = fopen("testwords_empty.txt", "r");
FILE *f = fopen("testwords_empty.txt", "r");
char words[10][MAX_WORD_LEN];
int count = readWords(f, words, 10);
fclose(f);
char words[10][MAX_WORD_LEN];
int count = readWords(f, words, 10);
fclose(f);
TEST_ASSERT_EQUAL_INT(0, count);
TEST_ASSERT_EQUAL_INT(0, count);
}
// ---------- Tests für game.c ----------
void test_createWordSalad_all_fit(void) {
char words[3][MAX_WORD_LEN] = {"CAT", "DOG", "MOUSE"};
char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN];
char words[3][MAX_WORD_LEN] = {"CAT", "DOG", "MOUSE"};
char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN];
int placed = createWordSalad(salad, 20, words, 3);
int placed = createWordSalad(salad, 20, words, 3);
TEST_ASSERT_EQUAL_INT(3, placed);
TEST_ASSERT_EQUAL_INT(3, placed);
// Sicherstellen, dass alle Felder gefüllt sind
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 20; j++) {
TEST_ASSERT_GREATER_OR_EQUAL('A', salad[i][j]);
TEST_ASSERT_LESS_OR_EQUAL('Z', salad[i][j]);
}
// Sicherstellen, dass alle Felder gefüllt sind
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 20; j++) {
TEST_ASSERT_GREATER_OR_EQUAL('A', salad[i][j]);
TEST_ASSERT_LESS_OR_EQUAL('Z', salad[i][j]);
}
}
}
void test_createWordSalad_too_small(void) {
char words[2][MAX_WORD_LEN] = {"ELEPHANT", "GIRAFFE"};
char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN];
char words[2][MAX_WORD_LEN] = {"ELEPHANT", "GIRAFFE"};
char salad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN];
int placed = createWordSalad(salad, 5, words, 2);
int placed = createWordSalad(salad, 5, words, 2);
TEST_ASSERT_GREATER_OR_EQUAL(0, placed);
TEST_ASSERT_LESS_OR_EQUAL(2, placed);
TEST_ASSERT_GREATER_OR_EQUAL(0, placed);
TEST_ASSERT_LESS_OR_EQUAL(2, placed);
// Feld muss vollständig gefüllt sein
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
TEST_ASSERT_GREATER_OR_EQUAL('A', salad[i][j]);
TEST_ASSERT_LESS_OR_EQUAL('Z', salad[i][j]);
}
// Feld muss vollständig gefüllt sein
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
TEST_ASSERT_GREATER_OR_EQUAL('A', salad[i][j]);
TEST_ASSERT_LESS_OR_EQUAL('Z', salad[i][j]);
}
}
}
// ---------- Test Setup und TearDown Funktionen ----------
@ -106,37 +107,37 @@ void test_createWordSalad_too_small(void) {
// falls Vor- und Nachbereitungen für die Tests benötigt.
void setUp(void) {
FILE *f = fopen("testwords_delims.txt", "w");
fprintf(f, "Hund,Katze; Maus\n");
fclose(f);
FILE *f = fopen("testwords_delims.txt", "w");
fprintf(f, "Hund,Katze; Maus\n");
fclose(f);
f = fopen("testwords_simple.txt", "w");
fprintf(f, "Apfel\nBanane\nKiwi");
fclose(f);
f = fopen("testwords_simple.txt", "w");
fprintf(f, "Apfel\nBanane\nKiwi");
fclose(f);
f = fopen("testwords_empty.txt", "w");
fclose(f);
f = fopen("testwords_empty.txt", "w");
fclose(f);
}
void tearDown(void) {
remove("testwords_delims.txt");
remove("testwords_simple.txt");
remove("testwords_empty.txt");
remove("testwords_delims.txt");
remove("testwords_simple.txt");
remove("testwords_empty.txt");
}
// ---------- Test Runner ----------
int main(void) {
UNITY_BEGIN();
UNITY_BEGIN();
RUN_TEST(test_readWords_simple);
RUN_TEST(test_readWords_with_delimiters);
RUN_TEST(test_readWords_empty_file);
RUN_TEST(test_createWordSalad_all_fit);
RUN_TEST(test_createWordSalad_too_small);
RUN_TEST(test_readWords_simple);
RUN_TEST(test_readWords_with_delimiters);
RUN_TEST(test_readWords_empty_file);
RUN_TEST(test_createWordSalad_all_fit);
RUN_TEST(test_createWordSalad_too_small);
int result = UNITY_END(); // Test-Ergebnisse
print_test_result(result);
int result = UNITY_END(); // Test-Ergebnisse
print_test_result(result);
return result;
return result;
}

View File

@ -7,449 +7,467 @@
#define MAX_MESSAGE_LEN 256
#define MAX_SOLUTION_WORD_LEN 16
typedef struct
{
Vector2 startPosition;
Vector2 endPosition;
int isSelected;
typedef struct {
Vector2 startPosition;
Vector2 endPosition;
int isSelected;
} MouseSelection;
typedef struct
{
Vector2 position;
char character[2];
int isMarked;
typedef struct {
Vector2 position;
char character[2];
int isMarked;
} CharSquare;
typedef struct
{
CharSquare *squares;
unsigned int count;
unsigned int squareSize;
unsigned int fontSize;
Vector2 position;
Vector2 size;
typedef struct {
CharSquare *squares;
unsigned int count;
unsigned int squareSize;
unsigned int fontSize;
Vector2 position;
Vector2 size;
} CharSquarePanel;
typedef struct
{
char content[MAX_WORD_LEN];
char *solution;
Vector2 position;
int wasFound;
typedef struct {
char content[MAX_WORD_LEN];
char *solution;
Vector2 position;
int wasFound;
} SearchWord;
typedef struct
{
SearchWord *words;
unsigned int count;
int fontSize;
Vector2 position;
Vector2 size;
typedef struct {
SearchWord *words;
unsigned int count;
int fontSize;
Vector2 position;
Vector2 size;
} SearchWordPanel;
typedef struct
{
char content[MAX_MESSAGE_LEN];
Vector2 position;
unsigned int size;
typedef struct {
char content[MAX_MESSAGE_LEN];
Vector2 position;
unsigned int size;
} WinMessage;
typedef struct
{
char text[MAX_MESSAGE_LEN];
Vector2 position;
Vector2 size;
unsigned int fontSize;
typedef struct {
char text[MAX_MESSAGE_LEN];
Vector2 position;
Vector2 size;
unsigned int fontSize;
} HelperMessage;
// Creates a helper message to guide the user
static HelperMessage createHelperMessage(unsigned int screenWidth)
{
const char *text = "Please search below for the words located at the bottom \nand draw a line exactly on the desired characters ...";
HelperMessage msg = {"", {0, 0}, {screenWidth, 0}, 18};
static HelperMessage createHelperMessage(unsigned int screenWidth) {
const char *text = "Please search below for the words located at the bottom "
"\nand draw a line exactly on the desired characters ...";
HelperMessage msg = {"", {0, 0}, {screenWidth, 0}, 18};
// Copy text into msg, ensuring does not exceed max length
strncpy(msg.text, text, MAX_MESSAGE_LEN);
msg.text[MAX_MESSAGE_LEN-1] = '\0';
// Copy text into msg, ensuring does not exceed max length
strncpy(msg.text, text, MAX_MESSAGE_LEN);
msg.text[MAX_MESSAGE_LEN - 1] = '\0';
// Set the vertical size based on font size
msg.size.y = 3 * msg.fontSize;
// Set the vertical size based on font size
msg.size.y = 3 * msg.fontSize;
return msg;
return msg;
}
// Creates a winning message when the user wins
static WinMessage createWinMessage(unsigned int screenSize)
{
WinMessage winMsg;
char *text = "Congratulations! You won!";
static WinMessage createWinMessage(unsigned int screenSize) {
WinMessage winMsg;
char *text = "Congratulations! You won!";
strncpy(winMsg.content, text, MAX_MESSAGE_LEN);
winMsg.content[MAX_MESSAGE_LEN-1] = '\0';
winMsg.size = 30; // Set font size
strncpy(winMsg.content, text, MAX_MESSAGE_LEN);
winMsg.content[MAX_MESSAGE_LEN - 1] = '\0';
winMsg.size = 30; // Set font size
// Calculate x and y positions for centering the message
winMsg.position.x = (screenSize - strlen(winMsg.content)*winMsg.size*0.52) / 2;
winMsg.position.y = screenSize / 2;
// Calculate x and y positions for centering the message
winMsg.position.x =
(screenSize - strlen(winMsg.content) * winMsg.size * 0.52) / 2;
winMsg.position.y = screenSize / 2;
return winMsg;
return winMsg;
}
// Frees memory associated with a search word panel
static void freeSearchWordPanel(SearchWordPanel *panel)
{
for(int i = 0; panel->words != NULL && i < panel->count; i++)
free(panel->words[i].solution); // Free solution strings
free(panel->words); // Free word array
panel->words = NULL;
panel->count = 0;
panel->size.x = 0;
panel->size.y = 0;
static void freeSearchWordPanel(SearchWordPanel *panel) {
for (int i = 0; panel->words != NULL && i < panel->count; i++)
free(panel->words[i].solution); // Free solution strings
free(panel->words); // Free word array
panel->words = NULL;
panel->count = 0;
panel->size.x = 0;
panel->size.y = 0;
}
// Creates a panel to display a list of search words
static SearchWordPanel createSearchWordPanel(const char words[][MAX_WORD_LEN], unsigned int numberOfWords, unsigned int windowOffset)
{
const int maxStringLenInPx = 200; // Max width of each word
const int fontSize = 18; // Font size for displaying words
const int rowHeight = fontSize * 1.2 + 5; // Height of each row of words
static SearchWordPanel createSearchWordPanel(const char words[][MAX_WORD_LEN],
unsigned int numberOfWords,
unsigned int windowOffset) {
const int maxStringLenInPx = 200; // Max width of each word
const int fontSize = 18; // Font size for displaying words
const int rowHeight = fontSize * 1.2 + 5; // Height of each row of words
SearchWordPanel panel = {NULL, 0, fontSize, {0, windowOffset}, {windowOffset, 0}};
SearchWordPanel panel = {
NULL, 0, fontSize, {0, windowOffset}, {windowOffset, 0}};
unsigned int xOffset = 5;
unsigned int yOffset = 15;
unsigned int xOffset = 5;
unsigned int yOffset = 15;
// Allocate memory for words if any are present
if(numberOfWords > 0)
panel.words = (SearchWord *)malloc(sizeof(SearchWord) * numberOfWords);
// Allocate memory for words if any are present
if (numberOfWords > 0)
panel.words = (SearchWord *)malloc(sizeof(SearchWord) * numberOfWords);
// If memory allocation is successful
if(panel.words != NULL)
{
// Loop through and set up the words and their positions
for(int i = 0; i < numberOfWords; i++)
{
strncpy(panel.words[i].content, words[i], MAX_SOLUTION_WORD_LEN);
panel.words[i].content[MAX_SOLUTION_WORD_LEN-1] = '\0';
// If memory allocation is successful
if (panel.words != NULL) {
// Loop through and set up the words and their positions
for (int i = 0; i < numberOfWords; i++) {
strncpy(panel.words[i].content, words[i], MAX_SOLUTION_WORD_LEN);
panel.words[i].content[MAX_SOLUTION_WORD_LEN - 1] = '\0';
// Truncate word if exceeds max length
if(strlen(words[i]) > MAX_SOLUTION_WORD_LEN-1)
strncpy(panel.words[i].content+MAX_SOLUTION_WORD_LEN-4, "...", 4);
// Truncate word if exceeds max length
if (strlen(words[i]) > MAX_SOLUTION_WORD_LEN - 1)
strncpy(panel.words[i].content + MAX_SOLUTION_WORD_LEN - 4, "...", 4);
// Allocate memory for solution word
panel.words[i].solution = (char *)malloc(sizeof(char) * (strlen(words[i]) + 1));
// Allocate memory for solution word
panel.words[i].solution =
(char *)malloc(sizeof(char) * (strlen(words[i]) + 1));
if(panel.words[i].solution != NULL)
strcpy(panel.words[i].solution, words[i]);
else
{
freeSearchWordPanel(&panel); // Free memory in case of failure
numberOfWords = 0;
break;
}
if (panel.words[i].solution != NULL)
strcpy(panel.words[i].solution, words[i]);
else {
freeSearchWordPanel(&panel); // Free memory in case of failure
numberOfWords = 0;
break;
}
panel.words[i].wasFound = 0; // Initialize "found" flag
panel.words[i].position.x = xOffset;
panel.words[i].position.y = yOffset;
panel.words[i].wasFound = 0; // Initialize "found" flag
panel.words[i].position.x = xOffset;
panel.words[i].position.y = yOffset;
// Move to next position for next word
xOffset += maxStringLenInPx + 5;
// Move to next position for next word
xOffset += maxStringLenInPx + 5;
// Move to next row if needed
if(xOffset > windowOffset)
{
xOffset = 5;
yOffset += rowHeight;
}
}
panel.count = numberOfWords; // Sets total word count
// Adjust panel size based on last word's position
if(numberOfWords > 0)
panel.size.y = panel.words[numberOfWords - 1].position.y + rowHeight;
// Move to next row if needed
if (xOffset > windowOffset) {
xOffset = 5;
yOffset += rowHeight;
}
}
panel.count = numberOfWords; // Sets total word count
return panel;
// Adjust panel size based on last word's position
if (numberOfWords > 0)
panel.size.y = panel.words[numberOfWords - 1].position.y + rowHeight;
}
return panel;
}
// Creates a square for a character in the search grid
static CharSquare createSquare(unsigned int rowIdx, unsigned int colIdx, char character, unsigned int squareSize)
{
CharSquare square;
square.position.x = colIdx * squareSize;
square.position.y = rowIdx * squareSize;
square.character[0] = character;
square.character[1] = '\0';
square.isMarked = 0; // Mark as unmarked initially
static CharSquare createSquare(unsigned int rowIdx, unsigned int colIdx,
char character, unsigned int squareSize) {
CharSquare square;
square.position.x = colIdx * squareSize;
square.position.y = rowIdx * squareSize;
square.character[0] = character;
square.character[1] = '\0';
square.isMarked = 0; // Mark as unmarked initially
return square;
return square;
}
// Creates a panel of character squares (the search grid)
static CharSquarePanel createCharSquarePanel(const char wordSalad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldSizeInChars, int panelSizeInPx)
{
CharSquarePanel squarePanel;
squarePanel.squares = (CharSquare *)malloc(sizeof(CharSquare) * searchFieldSizeInChars * searchFieldSizeInChars);
squarePanel.count = 0;
squarePanel.squareSize = (double)panelSizeInPx / searchFieldSizeInChars; // Calculate the square size
squarePanel.fontSize = squarePanel.squareSize * 0.75; // Set font size relative to square size
squarePanel.position.x = 0;
squarePanel.position.y = 0;
squarePanel.size.x = panelSizeInPx;
squarePanel.size.y = panelSizeInPx;
static CharSquarePanel createCharSquarePanel(
const char wordSalad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN],
unsigned int searchFieldSizeInChars, int panelSizeInPx) {
CharSquarePanel squarePanel;
squarePanel.squares = (CharSquare *)malloc(
sizeof(CharSquare) * searchFieldSizeInChars * searchFieldSizeInChars);
squarePanel.count = 0;
squarePanel.squareSize = (double)panelSizeInPx /
searchFieldSizeInChars; // Calculate the square size
squarePanel.fontSize =
squarePanel.squareSize * 0.75; // Set font size relative to square size
squarePanel.position.x = 0;
squarePanel.position.y = 0;
squarePanel.size.x = panelSizeInPx;
squarePanel.size.y = panelSizeInPx;
// If memory for squares is allocated successfully loop through grid and create squares for each character
if(squarePanel.squares != NULL)
{
for(int i = 0; i < searchFieldSizeInChars; i++)
{
for(int j = 0; j < searchFieldSizeInChars; j++)
{
squarePanel.squares[squarePanel.count] = createSquare(i, j, wordSalad[i][j], squarePanel.squareSize);
squarePanel.count++;
}
}
// If memory for squares is allocated successfully loop through grid and
// create squares for each character
if (squarePanel.squares != NULL) {
for (int i = 0; i < searchFieldSizeInChars; i++) {
for (int j = 0; j < searchFieldSizeInChars; j++) {
squarePanel.squares[squarePanel.count] =
createSquare(i, j, wordSalad[i][j], squarePanel.squareSize);
squarePanel.count++;
}
}
}
return squarePanel;
return squarePanel;
}
// Frees memory associated with CharSquarePanel
static void freeCharSquarePanel(CharSquarePanel *squarePanel)
{
free(squarePanel->squares); // Free squares array
squarePanel->squares = NULL;
squarePanel->count = 0; // Reset count
static void freeCharSquarePanel(CharSquarePanel *squarePanel) {
free(squarePanel->squares); // Free squares array
squarePanel->squares = NULL;
squarePanel->count = 0; // Reset count
}
// Draws all squares of CharSquarePanel
static void drawSquares(const CharSquarePanel squarePanel)
{
float fontOffset = squarePanel.squareSize / 4; // Offset for font positioning
static void drawSquares(const CharSquarePanel squarePanel) {
float fontOffset = squarePanel.squareSize / 4; // Offset for font positioning
// Loop through all squares and draw them
for(int i = 0; i < squarePanel.count; i++)
{
CharSquare square = squarePanel.squares[i];
// Loop through all squares and draw them
for (int i = 0; i < squarePanel.count; i++) {
CharSquare square = squarePanel.squares[i];
Vector2 squareScreenCoord = {squarePanel.position.x + square.position.x, squarePanel.position.y + square.position.y};
Color squareColor = DARKBLUE;
Color fontColor = LIGHTGRAY;
Vector2 squareScreenCoord = {squarePanel.position.x + square.position.x,
squarePanel.position.y + square.position.y};
Color squareColor = DARKBLUE;
Color fontColor = LIGHTGRAY;
// Change colors if is marked
if(square.isMarked)
{
squareColor = GREEN;
fontColor = BLACK;
}
// Draw square and its border
DrawRectangle(squareScreenCoord.x, squareScreenCoord.y, squarePanel.squareSize, squarePanel.squareSize, squareColor);
for(int i = 1; i <= 3; i++)
DrawRectangleLines(squareScreenCoord.x, squareScreenCoord.y, squarePanel.squareSize-i, squarePanel.squareSize-i, LIGHTGRAY);
// Draw character inside the square
DrawText(square.character, squareScreenCoord.x + fontOffset, squareScreenCoord.y + fontOffset, squarePanel.fontSize, fontColor);
// Change colors if is marked
if (square.isMarked) {
squareColor = GREEN;
fontColor = BLACK;
}
// Draw square and its border
DrawRectangle(squareScreenCoord.x, squareScreenCoord.y,
squarePanel.squareSize, squarePanel.squareSize, squareColor);
for (int i = 1; i <= 3; i++)
DrawRectangleLines(squareScreenCoord.x, squareScreenCoord.y,
squarePanel.squareSize - i, squarePanel.squareSize - i,
LIGHTGRAY);
// Draw character inside the square
DrawText(square.character, squareScreenCoord.x + fontOffset,
squareScreenCoord.y + fontOffset, squarePanel.fontSize, fontColor);
}
}
// Checks if selected word is valid solution
static int isSolution(const char *solution, SearchWordPanel searchWordPanel)
{
for(int i = 0; i < searchWordPanel.count; i++)
if(strcmp(solution, searchWordPanel.words[i].solution) == 0)
{
// Mark word as found and return true if solution matches
searchWordPanel.words[i].wasFound = 1;
return 1;
}
static int isSolution(const char *solution, SearchWordPanel searchWordPanel) {
for (int i = 0; i < searchWordPanel.count; i++)
if (strcmp(solution, searchWordPanel.words[i].solution) == 0) {
// Mark word as found and return true if solution matches
searchWordPanel.words[i].wasFound = 1;
return 1;
}
return 0; // false if not found
return 0; // false if not found
}
// Updates the marked squares based on user selection
static void updateSelectedSquares(const MouseSelection selection, CharSquarePanel squarePanel, SearchWordPanel searchWordPanel)
{
unsigned int wordIdx = 0;
char selectedWord[MAX_WORD_LEN];
unsigned int selectedIdx[squarePanel.count];
float radius = squarePanel.squareSize / 2;
static void updateSelectedSquares(const MouseSelection selection,
CharSquarePanel squarePanel,
SearchWordPanel searchWordPanel) {
unsigned int wordIdx = 0;
char selectedWord[MAX_WORD_LEN];
unsigned int selectedIdx[squarePanel.count];
float radius = squarePanel.squareSize / 2;
// Loop through all squares and check if selected
for(int i = 0; i < squarePanel.count && wordIdx < MAX_WORD_LEN-1; i++)
{
Vector2 center = {squarePanel.squares[i].position.x + squarePanel.position.x, squarePanel.squares[i].position.y + squarePanel.position.y};
center.x += radius;
center.y += radius;
// Loop through all squares and check if selected
for (int i = 0; i < squarePanel.count && wordIdx < MAX_WORD_LEN - 1; i++) {
Vector2 center = {
squarePanel.squares[i].position.x + squarePanel.position.x,
squarePanel.squares[i].position.y + squarePanel.position.y};
center.x += radius;
center.y += radius;
// Check if square is selected by mouse
if(CheckCollisionCircleLine(center, radius, selection.startPosition, selection.endPosition))
{
selectedWord[wordIdx] = squarePanel.squares[i].character[0];
selectedIdx[wordIdx] = i;
wordIdx++;
}
// Check if square is selected by mouse
if (CheckCollisionCircleLine(center, radius, selection.startPosition,
selection.endPosition)) {
selectedWord[wordIdx] = squarePanel.squares[i].character[0];
selectedIdx[wordIdx] = i;
wordIdx++;
}
selectedWord[wordIdx] = '\0';
}
selectedWord[wordIdx] = '\0';
// If selected word is a solution, mark it
if(isSolution(selectedWord, searchWordPanel))
{
for(int i = 0; i < wordIdx; i++)
squarePanel.squares[selectedIdx[i]].isMarked = 1;
}
// If selected word is a solution, mark it
if (isSolution(selectedWord, searchWordPanel)) {
for (int i = 0; i < wordIdx; i++)
squarePanel.squares[selectedIdx[i]].isMarked = 1;
}
}
// Handles mouse input for selecting words in grid
static void handleMouseInput(MouseSelection *selection, CharSquarePanel squarePanel, SearchWordPanel searchWordPanel)
{
if(IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) // Start new selection
{
selection->startPosition = GetMousePosition();
selection->endPosition = selection->startPosition;
selection->isSelected = 1;
}
else if(IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) // End selection
{
updateSelectedSquares(*selection, squarePanel, searchWordPanel);
static void handleMouseInput(MouseSelection *selection,
CharSquarePanel squarePanel,
SearchWordPanel searchWordPanel) {
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) // Start new selection
{
selection->startPosition = GetMousePosition();
selection->endPosition = selection->startPosition;
selection->isSelected = 1;
} else if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) // End selection
{
updateSelectedSquares(*selection, squarePanel, searchWordPanel);
selection->isSelected = 0;
}
else if(IsMouseButtonDown(MOUSE_BUTTON_LEFT)) // Update end position while selecting
{
selection->endPosition = GetMousePosition();
}
selection->isSelected = 0;
} else if (IsMouseButtonDown(
MOUSE_BUTTON_LEFT)) // Update end position while selecting
{
selection->endPosition = GetMousePosition();
}
}
// Draws selection line on screen if selection is active
static void drawSelection(const MouseSelection selection)
{
if(selection.isSelected)
{
DrawLine(selection.startPosition.x, selection.startPosition.y, selection.endPosition.x, selection.endPosition.y, WHITE);
}
static void drawSelection(const MouseSelection selection) {
if (selection.isSelected) {
DrawLine(selection.startPosition.x, selection.startPosition.y,
selection.endPosition.x, selection.endPosition.y, WHITE);
}
}
// Draws search word panel (list of words to be found)
static void drawSearchWordPanel(SearchWordPanel searchWordPanel)
{
for(int i = 0; i < searchWordPanel.count; i++)
{
Vector2 wordScreenCoord = {searchWordPanel.words[i].position.x + searchWordPanel.position.x, searchWordPanel.words[i].position.y + searchWordPanel.position.y};
DrawText(searchWordPanel.words[i].content, wordScreenCoord.x, wordScreenCoord.y, searchWordPanel.fontSize, WHITE);
static void drawSearchWordPanel(SearchWordPanel searchWordPanel) {
for (int i = 0; i < searchWordPanel.count; i++) {
Vector2 wordScreenCoord = {
searchWordPanel.words[i].position.x + searchWordPanel.position.x,
searchWordPanel.words[i].position.y + searchWordPanel.position.y};
DrawText(searchWordPanel.words[i].content, wordScreenCoord.x,
wordScreenCoord.y, searchWordPanel.fontSize, WHITE);
// If word has been found, highlight it
if(searchWordPanel.words[i].wasFound)
{
int xOffset = MeasureText(searchWordPanel.words[i].content, searchWordPanel.fontSize);
for(int i = 0; i <= 3; i++)
DrawLine(wordScreenCoord.x - 3, wordScreenCoord.y + 5 + i, wordScreenCoord.x + xOffset + 3, wordScreenCoord.y + 5 + i, GREEN);
}
// If word has been found, highlight it
if (searchWordPanel.words[i].wasFound) {
int xOffset = MeasureText(searchWordPanel.words[i].content,
searchWordPanel.fontSize);
for (int i = 0; i <= 3; i++)
DrawLine(wordScreenCoord.x - 3, wordScreenCoord.y + 5 + i,
wordScreenCoord.x + xOffset + 3, wordScreenCoord.y + 5 + i,
GREEN);
}
}
}
// Draws helper message (instructions or tips for user)
static void drawHelperMessage(const HelperMessage msg)
{
DrawRectangle(msg.position.x, msg.position.y, msg.size.x, msg.size.y, BLACK); // Background for message
DrawText(msg.text, msg.position.x + 5, msg.position.y + 5, msg.fontSize, WHITE); // Display message text
static void drawHelperMessage(const HelperMessage msg) {
DrawRectangle(msg.position.x, msg.position.y, msg.size.x, msg.size.y,
BLACK); // Background for message
DrawText(msg.text, msg.position.x + 5, msg.position.y + 5, msg.fontSize,
WHITE); // Display message text
}
// Draws the entire game content, including helper message, squares, and search words
static void drawGameContent(const HelperMessage helperMsg, const CharSquarePanel squarePanel, const MouseSelection selection, const SearchWordPanel searchWordPanel)
{
drawHelperMessage(helperMsg);
drawSquares(squarePanel);
drawSearchWordPanel(searchWordPanel);
drawSelection(selection);
// Draws the entire game content, including helper message, squares, and search
// words
static void drawGameContent(const HelperMessage helperMsg,
const CharSquarePanel squarePanel,
const MouseSelection selection,
const SearchWordPanel searchWordPanel) {
drawHelperMessage(helperMsg);
drawSquares(squarePanel);
drawSearchWordPanel(searchWordPanel);
drawSelection(selection);
}
// Draws success message when player wins
static void drawSuccessContent(WinMessage msg)
{
unsigned int textWidth = MeasureText(msg.content, msg.size);
DrawRectangle(msg.position.x-20, msg.position.y-20, textWidth+40, msg.size+40, GREEN); // Background for success message
static void drawSuccessContent(WinMessage msg) {
unsigned int textWidth = MeasureText(msg.content, msg.size);
DrawRectangle(msg.position.x - 20, msg.position.y - 20, textWidth + 40,
msg.size + 40, GREEN); // Background for success message
for(int i = 0; i < 5; i++) // Draw borders around success message
DrawRectangleLines(msg.position.x-20+i, msg.position.y-20+i, textWidth+40-i*2, msg.size+40-i*2, WHITE);
for (int i = 0; i < 5; i++) // Draw borders around success message
DrawRectangleLines(msg.position.x - 20 + i, msg.position.y - 20 + i,
textWidth + 40 - i * 2, msg.size + 40 - i * 2, WHITE);
DrawText(msg.content, msg.position.x, msg.position.y, msg.size, WHITE); // Display success text
DrawText(msg.content, msg.position.x, msg.position.y, msg.size,
WHITE); // Display success text
}
// Draws entire game screen, including game content and success message if applicable
static void drawAll(const CharSquarePanel squarePanel, const MouseSelection selection, const SearchWordPanel searchWordPanel, const HelperMessage helperMsg, const WinMessage msg, int hasWon)
{
BeginDrawing();
ClearBackground(BLACK); // Clear screen with a black background
drawGameContent(helperMsg, squarePanel, selection, searchWordPanel); // Draw game content
// Draws entire game screen, including game content and success message if
// applicable
static void drawAll(const CharSquarePanel squarePanel,
const MouseSelection selection,
const SearchWordPanel searchWordPanel,
const HelperMessage helperMsg, const WinMessage msg,
int hasWon) {
BeginDrawing();
ClearBackground(BLACK); // Clear screen with a black background
drawGameContent(helperMsg, squarePanel, selection,
searchWordPanel); // Draw game content
if(hasWon) // If player has won, draw success message
drawSuccessContent(msg);
if (hasWon) // If player has won, draw success message
drawSuccessContent(msg);
EndDrawing();
EndDrawing();
}
// Checks if all words in the search word panel have been found
static int allWordsFound(SearchWordPanel searchWordPanel)
{
// Loop through all words and check if any is not found
for(int i = 0; i < searchWordPanel.count; i++)
if(!searchWordPanel.words[i].wasFound)
return 0; // Return false if any word is not found
return 1; // Return true if all words are found
static int allWordsFound(SearchWordPanel searchWordPanel) {
// Loop through all words and check if any is not found
for (int i = 0; i < searchWordPanel.count; i++)
if (!searchWordPanel.words[i].wasFound)
return 0; // Return false if any word is not found
return 1; // Return true if all words are found
}
// Main game loop where game is run and updated
static void gameLoop(const Vector2 screenSize, MouseSelection mouseSelection, CharSquarePanel squarePanel, SearchWordPanel searchWordPanel, const HelperMessage helperMsg, const WinMessage winMsg)
{
InitWindow(screenSize.x, screenSize.y, "Word Salad"); // Initialize game window
static void gameLoop(const Vector2 screenSize, MouseSelection mouseSelection,
CharSquarePanel squarePanel,
SearchWordPanel searchWordPanel,
const HelperMessage helperMsg, const WinMessage winMsg) {
InitWindow(screenSize.x, screenSize.y,
"Word Salad"); // Initialize game window
SetTargetFPS(60);
SetTargetFPS(60);
while (!WindowShouldClose()) // Keep running until window is closed
{
handleMouseInput(&mouseSelection, squarePanel, searchWordPanel); // Handle mouse input (selection)
while (!WindowShouldClose()) // Keep running until window is closed
{
handleMouseInput(&mouseSelection, squarePanel,
searchWordPanel); // Handle mouse input (selection)
// Draw all game content including helper message, squares, and search word panel
drawAll(squarePanel, mouseSelection, searchWordPanel, helperMsg, winMsg, allWordsFound(searchWordPanel));
}
// Draw all game content including helper message, squares, and search word
// panel
drawAll(squarePanel, mouseSelection, searchWordPanel, helperMsg, winMsg,
allWordsFound(searchWordPanel));
}
CloseWindow();
CloseWindow();
}
// Initializes and starts game, setting up necessary elements and entering game loop
void startGame(const char wordSalad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN], unsigned int searchFieldSize, char words[][MAX_WORD_LEN], unsigned int numberOfWords, unsigned int windowSize)
{
const int windowWidth = windowSize;
// Initializes and starts game, setting up necessary elements and entering game
// loop
void startGame(const char wordSalad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN],
unsigned int searchFieldSize, char words[][MAX_WORD_LEN],
unsigned int numberOfWords, unsigned int windowSize) {
const int windowWidth = windowSize;
Vector2 screenSize;
Vector2 screenSize;
// Create necessary game elements like helper message, square panel, and search word panel
HelperMessage helperMsg = createHelperMessage(windowWidth);
CharSquarePanel squarePanel = createCharSquarePanel(wordSalad, searchFieldSize, windowWidth);
SearchWordPanel searchWordPanel = createSearchWordPanel(words, numberOfWords, windowWidth);
WinMessage winMsg = createWinMessage(windowWidth);
// Create necessary game elements like helper message, square panel, and
// search word panel
HelperMessage helperMsg = createHelperMessage(windowWidth);
CharSquarePanel squarePanel =
createCharSquarePanel(wordSalad, searchFieldSize, windowWidth);
SearchWordPanel searchWordPanel =
createSearchWordPanel(words, numberOfWords, windowWidth);
WinMessage winMsg = createWinMessage(windowWidth);
MouseSelection mouseSelection;
MouseSelection mouseSelection;
mouseSelection.isSelected = 0; // Initialize mouse selection to not be active
mouseSelection.isSelected = 0; // Initialize mouse selection to not be active
// Adjust panel positions
squarePanel.position.y = helperMsg.size.y;
searchWordPanel.position.y = helperMsg.size.y + squarePanel.size.y;
// Adjust panel positions
squarePanel.position.y = helperMsg.size.y;
searchWordPanel.position.y = helperMsg.size.y + squarePanel.size.y;
// Set screen size based on the panels' sizes
screenSize.x = squarePanel.size.x;
screenSize.y = helperMsg.size.y + squarePanel.size.y + searchWordPanel.size.y;
// Set screen size based on the panels' sizes
screenSize.x = squarePanel.size.x;
screenSize.y = helperMsg.size.y + squarePanel.size.y + searchWordPanel.size.y;
// Start game loop
gameLoop(screenSize, mouseSelection, squarePanel, searchWordPanel, helperMsg, winMsg);
// Start game loop
gameLoop(screenSize, mouseSelection, squarePanel, searchWordPanel, helperMsg,
winMsg);
// Free up allocated memory when game is done
freeCharSquarePanel(&squarePanel);
freeSearchWordPanel(&searchWordPanel);
// Free up allocated memory when game is done
freeCharSquarePanel(&squarePanel);
freeSearchWordPanel(&searchWordPanel);
}
/*gcc -fPIC -c input.c game.c graphicalGame.c main.c
gcc -shared -o libwortsalat.a input.o game.o graphicalGame.o main.o*/
gcc -shared -o libwordsalad.a input.o game.o graphicalGame.o main.o*/

View File

@ -1,54 +1,63 @@
#include <stdlib.h>
#include <stdio.h>
#include "input.h"
#include "game.h"
#include "graphicalGame.h"
#include "input.h"
#include <stdio.h>
#include <stdlib.h>
#define MAX_NUMBER_OF_WORDS 100
#define SALAD_SIZE 20
int main(int argc, char *argv[])
{
int exitCode = EXIT_SUCCESS;
int main(int argc, char *argv[]) {
int exitCode = EXIT_SUCCESS;
// Check if the correct number of arguments is provided
if(argc != 2)
{
fprintf(stderr, "Usage: %s <path to file with search words>\n", argv[0]);
// Check if the correct number of arguments is provided
if (argc != 2) {
fprintf(stderr, "Usage: %s <path to file with search words>\n", argv[0]);
exitCode = EXIT_FAILURE;
} else {
char words[MAX_NUMBER_OF_WORDS]
[MAX_WORD_LEN]; // Array to hold the words to be used in the game
unsigned int wordCount = 0;
FILE *file = fopen(argv[1], "r");
if (file != NULL) {
unsigned int placedWords = 0;
char wordSalad[MAX_SEARCH_FIELD_LEN]
[MAX_SEARCH_FIELD_LEN]; // 2D array to store the word salad
// Read words from file and store in 'words' array
wordCount = readWords(file, words, MAX_NUMBER_OF_WORDS);
fclose(file);
// Create the word salad by placing words into grid
placedWords = createWordSalad(wordSalad, SALAD_SIZE, words, wordCount);
// TODO:
// Check if all words were successfully placed
// Start the game if successful
// error message if some words couldn't be placed
if (placedWords == wordCount) {
startGame(wordSalad, SALAD_SIZE, words, wordCount,
MAX_SEARCH_FIELD_LEN);
}
else
{
// Print error message if words couldn't be placed
// evtl noch richtigen error code einfügen
fprintf(stderr, "Could not place words...\n");
exitCode = EXIT_FAILURE;
}
} else {
// Print error message if file couldn't be opened
fprintf(stderr, "Could not open file %s for reading ...\n", argv[1]);
exitCode = EXIT_FAILURE;
}
else
{
char words[MAX_NUMBER_OF_WORDS][MAX_WORD_LEN]; // Array to hold the words to be used in the game
unsigned int wordCount = 0;
}
FILE *file = fopen(argv[1], "r");
if(file != NULL)
{
unsigned int placedWords = 0;
char wordSalad[MAX_SEARCH_FIELD_LEN][MAX_SEARCH_FIELD_LEN]; // 2D array to store the word salad
// Read words from file and store in 'words' array
wordCount = readWords(file, words, MAX_NUMBER_OF_WORDS);
fclose(file);
// Create the word salad by placing words into grid
placedWords = createWordSalad(wordSalad, SALAD_SIZE, words, wordCount);
// TODO:
// Check if all words were successfully placed
// Start the game if successful
// error message if some words couldn't be placed
}
else
{
// Print error message if file couldn't be opened
fprintf(stderr, "Could not open file %s for reading ...\n", argv[1]);
exitCode = EXIT_FAILURE;
}
}
return exitCode;
return exitCode;
}

View File

@ -12,6 +12,14 @@ unityfolder = ./unity
wordsalad_initial:
$(CC) -o wordsalad_initial $(BINARIES)/libwordsalad_complete.a $(BINARIES)/libraylib.a $(LDFLAGS)
#---------------------------
# eigenes Target bauen
#---------------------------
wordsalad_myversion:
$(CC) -o wordsalad_myversion main.o $(BINARIES)/libwordsalad.a $(BINARIES)/libraylib.a $(LDFLAGS)
# --------------------------
# Normales Spiel bauen

Binary file not shown.

0
test.c
View File