From 88cdf28cfcba9a29fe0e5b856c44c9adc90d422f Mon Sep 17 00:00:00 2001 From: ItsDrike Date: Sat, 7 Dec 2024 21:03:34 +0100 Subject: [PATCH] Use unique ptr for nicer memory freeing in win simulation func This also switches from using `QQueue` here to `std::queue` as `QQueue` doesn't seem to play well with holding unique pointers. --- src/gamestate.cpp | 58 +++++++++++++++-------------------------------- 1 file changed, 18 insertions(+), 40 deletions(-) diff --git a/src/gamestate.cpp b/src/gamestate.cpp index 1ce3811..b579603 100644 --- a/src/gamestate.cpp +++ b/src/gamestate.cpp @@ -1,9 +1,9 @@ #include "gamestate.h" #include -#include #include #include #include +#include #include GameState::GameState(QObject* parent, bool preDealCards) : QObject{parent}, m_columns(7), m_foundation(4), m_gameWon(false) { @@ -623,22 +623,22 @@ std::pair, int> GameState::canWinThroughSimulation(QSet> stateQueue; // BFS queue (game state, depth) + std::queue, int>> stateQueue; // BFS queue (game state, depth) // Clone the current state as the root of BFS - GameState* initialState = this->clone(); - stateQueue.enqueue({initialState, 0}); - visitedStates.insert(initialState->generateStateHash()); + auto initialState = std::unique_ptr(this->clone()); + stateQueue.emplace(std::move(initialState), 0); + visitedStates.insert(stateQueue.front().first->generateStateHash()); int lastDepth = 0; - while (!stateQueue.isEmpty()) { - auto [currentState, depth] = stateQueue.dequeue(); + while (!stateQueue.empty()) { + auto [currentState, depth] = std::move(stateQueue.front()); + stateQueue.pop(); auto currentHash = currentState->generateStateHash(); lastDepth = depth; // Limit evaluation time (ensures this doesn't block the game) if (timer.hasExpired(MAX_EVAL_TIME)) { - delete currentState; return std::make_pair(std::nullopt, depth); } @@ -653,22 +653,18 @@ std::pair, int> GameState::canWinThroughSimulation(QSetisFoundationMoveValid(*topSlot->card(), foundationId)) continue; - GameState* newState = currentState->clone(); + auto newState = std::unique_ptr(currentState->clone()); assert(newState->moveColumnCardToFoundation(columnId, foundationId)); QString stateHash = newState->generateStateHash(); assert(currentHash != stateHash); if (newState->m_gameWon) { - delete newState; - delete currentState; return std::make_pair(true, depth + 1); // Return depth if game won } if (!visitedStates.contains(stateHash)) { visitedStates.insert(stateHash); - stateQueue.enqueue({newState, depth + 1}); - } else { - delete newState; + stateQueue.push({std::move(newState), depth + 1}); } } } @@ -682,22 +678,18 @@ std::pair, int> GameState::canWinThroughSimulation(QSetisFoundationMoveValid(*topCard, foundationId)) continue; - GameState* newState = currentState->clone(); + auto newState = std::unique_ptr(currentState->clone()); assert(newState->moveThrownCardToFoundation(foundationId)); QString stateHash = newState->generateStateHash(); assert(currentHash != stateHash); if (newState->m_gameWon) { - delete newState; - delete currentState; return std::make_pair(true, depth + 1); } if (!visitedStates.contains(stateHash)) { visitedStates.insert(stateHash); - stateQueue.enqueue({newState, depth + 1}); - } else { - delete newState; + stateQueue.push({std::move(newState), depth + 1}); } } @@ -706,22 +698,18 @@ std::pair, int> GameState::canWinThroughSimulation(QSetisColumnMoveValid(*topCard, toColumnId)) continue; - GameState* newState = currentState->clone(); + auto newState = std::unique_ptr(currentState->clone()); assert(newState->moveThrownCardToColumn(toColumnId)); QString stateHash = newState->generateStateHash(); assert(currentHash != stateHash); if (newState->m_gameWon) { - delete newState; - delete currentState; return std::make_pair(true, depth + 1); } if (!visitedStates.contains(stateHash)) { visitedStates.insert(stateHash); - stateQueue.enqueue({newState, depth + 1}); - } else { - delete newState; + stateQueue.push({std::move(newState), depth + 1}); } } } @@ -730,22 +718,18 @@ std::pair, int> GameState::canWinThroughSimulation(QSetm_drawPile.isEmpty() && currentState->m_throwawayPile.size() <= 1)) { - GameState* newState = currentState->clone(); + auto newState = std::unique_ptr(currentState->clone()); assert(newState->drawNextCard()); QString stateHash = newState->generateStateHash(); assert(currentHash != stateHash); if (newState->m_gameWon) { - delete newState; - delete currentState; return std::make_pair(true, depth + 1); } if (!visitedStates.contains(stateHash)) { visitedStates.insert(stateHash); - stateQueue.enqueue({newState, depth + 1}); - } else { - delete newState; + stateQueue.push({std::move(newState), depth + 1}); } } @@ -766,28 +750,22 @@ std::pair, int> GameState::canWinThroughSimulation(QSetisColumnMoveValid(*fromSlot->card(), toColumnId)) continue; - GameState* newState = currentState->clone(); + auto newState = std::unique_ptr(currentState->clone()); assert(newState->moveColumnCardToColumn(fromColumnId, toColumnId, fromCardIndex)); QString stateHash = newState->generateStateHash(); assert(currentHash != stateHash); if (newState->m_gameWon) { - delete newState; - delete currentState; return std::make_pair(true, depth + 1); } if (!visitedStates.contains(stateHash)) { visitedStates.insert(stateHash); - stateQueue.enqueue({newState, depth + 1}); - } else { - delete newState; + stateQueue.push({std::move(newState), depth + 1}); } } } } - - delete currentState; // Cleanup current state } return std::make_pair(false, lastDepth); // No solution