From 37060ed06e5940dc4316b6d9249a99ac17f41f1d Mon Sep 17 00:00:00 2001 From: Tomila Bakeeva Date: Mon, 1 Dec 2025 13:02:48 +0100 Subject: [PATCH 1/2] Bugfix: Race Condition behoben mit GameState (State Machine) --- src/main.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 38190c8..dc271d2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,16 @@ #include #include + +enum class GameState +{ + Idle, // kein Würfel offen, Eingabe erlaubt + OneFlipped, // ein Würfel offen + CheckingMatch, // zwei Würfel vollständig aufgeklappt, Vergleich läuft + LockInput // Würfel drehen gerade – Eingabe kurz blockiert +}; + + // ----------------------------------------------------------- // 3D Memory Game – Hauptprogramm // ----------------------------------------------------------- @@ -56,6 +66,8 @@ int main() float flipSpeed = 5.0f; // Drehgeschwindigkeit bool gameWon = false; + GameState state = GameState::Idle; // Start Zustand + // ----------------------------------------------------------- // Hauptspielschleife // ----------------------------------------------------------- @@ -67,7 +79,10 @@ int main() timerStarted = true; } // Klick-Erkennung - if (!gameWon && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + if (!gameWon + && state != GameState::LockInput + && state != GameState::CheckingMatch + && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { Vector2 mouse = GetMousePosition(); @@ -78,31 +93,57 @@ int main() Vector2 screenPos = GetWorldToScreen({c.GetPosition().x, c.GetPosition().y, c.GetPosition().z}, camera); if (fabs(mouse.x - screenPos.x) < 40 && fabs(mouse.y - screenPos.y) < 40) + { c.FlipForward(); + + // ZUSTANDSUMSCHALTLOGIK + if (state == GameState::Idle) + { + // 1. Click + c.FlipForward(); + first = &c; + state = GameState::OneFlipped; + break; // wichtig!!! Wir verlassen die Schleife :) + } + else if (state == GameState::OneFlipped) + { + // 2. Click + // Lass uns überprüfen, ob es NICHT derselbe Würfel ist. + if (&c != first) + { + c.FlipForward(); + second = &c; + state = GameState::LockInput; + break; // wichtig!!! Wir verlassen die Schleife :) + } + } + } } } } // Animation aller Würfel + bool animationBusy = false; + for (auto &c : cubes) { c.Update(flipSpeed); + } - // Sobald ein Würfel vollständig umgedreht ist → merken - if (c.IsFlipped() && !c.IsMatched()) + if (state == GameState::LockInput) + { + if (first && first->IsFlipped() && second && second->IsFlipped()) { - if (!first) first = &c; - else if (!second && &c != first) second = &c; + state = GameState::CheckingMatch; } } // Matching-Logik - if (first && second) + if (state == GameState::CheckingMatch && first && second) { - Color col1 = first->GetColor(); - Color col2 = second->GetColor(); - - if (col1.r == col2.r && col1.g == col2.g && col1.b == col2.b) + if (first->GetColor().r == second->GetColor().r && + first->GetColor().g == second->GetColor().g && + first->GetColor().b == second->GetColor().b) { first->SetMatched(true); second->SetMatched(true); @@ -114,6 +155,7 @@ int main() } first = second = nullptr; + state = GameState::Idle; } // Gewinnprüfung From b13d535c27f1a3e6fcc94d3d9df51482479cd39b Mon Sep 17 00:00:00 2001 From: PapiBigSzill <04andrei22@gmail.com> Date: Mon, 15 Dec 2025 12:19:33 +0100 Subject: [PATCH 2/2] mergeconflict --- src/main.cpp | 250 +++++++-------------------------------------------- 1 file changed, 31 insertions(+), 219 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b8a62a4..2a6a2f0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,228 +1,40 @@ -#include "gamecube.h" -#include -#include -#include +#pragma once +#include "gamematrix.h" #include "raylib.h" +#include -enum GameScreen { MENU = 0, GAMEPLAY }; - -static void SetupGame(std::vector& cubes, int pairs) +struct Vec3 { - cubes.clear(); + float x, y, z; +}; - Color colors[] = { RED, GREEN, BLUE, YELLOW, ORANGE, PURPLE, WHITE, SKYBLUE }; - std::vector positions; - - const int count = pairs * 2; - int cols = 3; - int rows = 2; - - if (count > 6) { - cols = 4; - rows = 3; - } - - int index = 0; - for (int r = 0; r < rows && index < count; ++r) { - for (int c = 0; c < cols && index < count; ++c) { - positions.push_back({ (float)c * 2.0f - (cols - 1), 0.0f, (float)r * 2.0f - (rows - 1) }); - index++; - } - } - - std::vector colorPool; - colorPool.reserve(count); - - for (int i = 0; i < pairs; i++) { - colorPool.push_back(colors[i]); - colorPool.push_back(colors[i]); - } - - for (int i = (int)colorPool.size() - 1; i > 0; --i) { - int j = rand() % (i + 1); - std::swap(colorPool[i], colorPool[j]); - } - - for (int i = 0; i < count; i++) { - cubes.emplace_back(positions[i], colorPool[i]); - } -} - -int main() +class gamecube { - srand((unsigned)time(NULL)); +public: + gamecube(const Vec3 &pos, Color col); + void Update(float flipSpeed); + void FlipForward(); + void FlipBackward(); - double startTime = 0.0; - double endTime = 0.0; - bool timerStarted = false; + // Wichtig für die Zustandsmaschine (LockInput-Wartezustand) + bool IsFlipping() const { return flippingForward || flippingBackward; } - GameScreen currentScreen = MENU; - int selectedPairs = 3; + bool IsFlipped() const; + bool IsMatched() const; + void SetMatched(bool m); + void Draw() const; + Vec3 GetPosition() const; + float GetRotationY() const; - std::vector cubes; - gamecube* first = nullptr; - gamecube* second = nullptr; - float flipSpeed = 5.0f; - bool gameWon = false; + // Bereits vorhanden und inline implementiert! + Color GetColor() const { return color; } - InitWindow(800, 600, "3D Memory Game with Matrix3D Library"); - SetTargetFPS(60); - - Camera3D camera{}; - camera.position = { 6.0f, 6.0f, 6.0f }; - camera.target = { 0.0f, 0.0f, 0.0f }; - camera.up = { 0.0f, 1.0f, 0.0f }; - camera.fovy = 45.0f; - camera.projection = CAMERA_PERSPECTIVE; - - while (!WindowShouldClose()) - { - switch (currentScreen) - { - case MENU: - { - if (IsKeyPressed(KEY_THREE)) { - selectedPairs = 3; - SetupGame(cubes, selectedPairs); - gameWon = false; - first = second = nullptr; - currentScreen = GAMEPLAY; - timerStarted = false; - } - else if (IsKeyPressed(KEY_SIX)) { - selectedPairs = 6; - SetupGame(cubes, selectedPairs); - gameWon = false; - first = second = nullptr; - currentScreen = GAMEPLAY; - timerStarted = false; - } - break; - } - - case GAMEPLAY: - { - if (!timerStarted) { - startTime = GetTime(); - timerStarted = true; - } - - if (!gameWon && IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && (second == nullptr)) - { - Vector2 mouse = GetMousePosition(); - Ray ray = GetMouseRay(mouse, camera); - - gamecube* hitCube = nullptr; - float bestDist = 1e9f; - - for (auto& c : cubes) - { - if (c.IsMatched() || c.IsFlipped()) continue; - - auto p = c.GetPosition(); - - BoundingBox box; - box.min = { p.x - 0.75f, p.y - 0.75f, p.z - 0.75f }; - box.max = { p.x + 0.75f, p.y + 0.75f, p.z + 0.75f }; - - RayCollision col = GetRayCollisionBox(ray, box); - if (col.hit && col.distance < bestDist) { - bestDist = col.distance; - hitCube = &c; - } - } - - if (hitCube) - { - if (!first) { - first = hitCube; - first->FlipForward(); - } - else if (hitCube != first) { - second = hitCube; - second->FlipForward(); - } - } - } - - for (auto& c : cubes) { - c.Update(flipSpeed); - } - - if (first && second && first->IsFlipped() && second->IsFlipped()) - { - Color col1 = first->GetColor(); - Color col2 = second->GetColor(); - - if (col1.r == col2.r && col1.g == col2.g && col1.b == col2.b) { - first->SetMatched(true); - second->SetMatched(true); - } - else { - first->FlipBackward(); - second->FlipBackward(); - } - - first = nullptr; - second = nullptr; - } - - if (!gameWon) - { - gameWon = std::all_of( - cubes.begin(), - cubes.end(), - [](const gamecube& c) { return c.IsMatched(); } - ); - - if (gameWon) { - endTime = GetTime() - startTime; - } - } - break; - } - } - - BeginDrawing(); - ClearBackground(RAYWHITE); - - switch (currentScreen) - { - case MENU: - { - DrawText("3D MEMORY SPIEL", - GetScreenWidth() / 2 - MeasureText("3D MEMORY SPIEL", 50) / 2, - 80, 50, DARKGRAY); - DrawText("Waehlen Sie die Spielgroesse:", 50, 200, 25, BLACK); - DrawText("Druecken Sie [3] fuer 3 Paare (6 Wuerfel)", 50, 240, 20, BLUE); - DrawText("Druecken Sie [6] fuer 6 Paare (12 Wuerfel)", 50, 280, 20, BLUE); - break; - } - - case GAMEPLAY: - { - BeginMode3D(camera); - for (auto& c : cubes) c.Draw(); - EndMode3D(); - - if (gameWon) { - DrawText("Congrats! You found all pairs!", 150, 260, 30, DARKBLUE); - char buffer[64]; - sprintf(buffer, "Cleared in %.2f seconds", endTime); - DrawText(buffer, 150, 300, 28, DARKGREEN); - } else { - DrawText("Flip 2 cubes - find matching pairs!", 10, 10, 20, DARKGRAY); - char liveBuf[64]; - sprintf(liveBuf, "Time: %.2f", GetTime() - startTime); - DrawText(liveBuf, 10, 40, 20, DARKGRAY); - } - break; - } - } - - EndDrawing(); - } - - CloseWindow(); - return 0; -} +private: + Vec3 position; + Color color; + bool flipped = false; + bool matched = false; + bool flippingForward = false; + bool flippingBackward = false; + float rotation = 0.0f; +}; \ No newline at end of file