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.
This commit is contained in:
parent
b209fbc94b
commit
88cdf28cfc
|
@ -1,9 +1,9 @@
|
|||
#include "gamestate.h"
|
||||
#include <QDebug>
|
||||
#include <QQueue>
|
||||
#include <QSet>
|
||||
#include <qlist.h>
|
||||
#include <qqmllist.h>
|
||||
#include <queue>
|
||||
#include <random>
|
||||
|
||||
GameState::GameState(QObject* parent, bool preDealCards) : QObject{parent}, m_columns(7), m_foundation(4), m_gameWon(false) {
|
||||
|
@ -623,22 +623,22 @@ std::pair<std::optional<bool>, int> GameState::canWinThroughSimulation(QSet<QStr
|
|||
|
||||
// Go over all possible moves using BFS
|
||||
|
||||
QQueue<std::pair<GameState*, int>> stateQueue; // BFS queue (game state, depth)
|
||||
std::queue<std::pair<std::unique_ptr<GameState>, 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<GameState>(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<std::optional<bool>, int> GameState::canWinThroughSimulation(QSet<QStr
|
|||
if (!currentState->isFoundationMoveValid(*topSlot->card(), foundationId))
|
||||
continue;
|
||||
|
||||
GameState* newState = currentState->clone();
|
||||
auto newState = std::unique_ptr<GameState>(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<std::optional<bool>, int> GameState::canWinThroughSimulation(QSet<QStr
|
|||
if (!currentState->isFoundationMoveValid(*topCard, foundationId))
|
||||
continue;
|
||||
|
||||
GameState* newState = currentState->clone();
|
||||
auto newState = std::unique_ptr<GameState>(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<std::optional<bool>, int> GameState::canWinThroughSimulation(QSet<QStr
|
|||
if (!currentState->isColumnMoveValid(*topCard, toColumnId))
|
||||
continue;
|
||||
|
||||
GameState* newState = currentState->clone();
|
||||
auto newState = std::unique_ptr<GameState>(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<std::optional<bool>, int> GameState::canWinThroughSimulation(QSet<QStr
|
|||
// (The condition also handles the case where there's only one card in the throwaway pile,
|
||||
// which means drawing would just result in flipping and re-drawing the same card.)
|
||||
if (!(currentState->m_drawPile.isEmpty() && currentState->m_throwawayPile.size() <= 1)) {
|
||||
GameState* newState = currentState->clone();
|
||||
auto newState = std::unique_ptr<GameState>(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<std::optional<bool>, int> GameState::canWinThroughSimulation(QSet<QStr
|
|||
if (!currentState->isColumnMoveValid(*fromSlot->card(), toColumnId))
|
||||
continue;
|
||||
|
||||
GameState* newState = currentState->clone();
|
||||
auto newState = std::unique_ptr<GameState>(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
|
||||
|
|
Loading…
Reference in a new issue