I'm trying to build a simple memory game with Qt 5.11.1 and C++, where you get a few tiles on screen and you have to click on two and try to match the images they show.
My tiles are implemented as QPushButtons. Each time you click on one an image is displayed (by calling a showImage()
method that changes the button background). When a second tile is clicked, if there is a match the two buttons are disabled so you can't click on them again (and you get a higher score). However, if you didn't get a match, the two tiles you just clicked will go back to their initial state (showing no image) after 1 second (this allows the user to "memorize" which image was showing up on each tile).
Whenever you click on a "tile" (button) it becomes disabled (button->setEnabled(false)
). If after clicking a second tile there was no match, then both tiles are turned back and then setEnabled(true)
again. I'm using a single shot QTimer to call the method that will turn back the tiles:
QTimer::singleShot(1000, this, SLOT(turnTilesBack()));
firstTile->setEnabled(true);
secondTile->setEnabled(true);
Everything is working as expected, except for one thing: as QTimer runs in its own thread (or so I understand from what I read) all of the available tiles remain enabled during the 1000 milisecond lapse, allowing the user to continue clicking on them. However, when there is no match, I'd like to "freeze" the buttons until the QTimer has timed out so the user can't continue playing until the tiles have turned back.
So instead of using the QTimer I've trying this solution which I saw on this question (How do I create a pause/wait function using Qt?):
QTime dieTime= QTime::currentTime().addSecs(1);
while (QTime::currentTime() < dieTime)
turnTilesBack();
although I removed this line: QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
as this would cause the main thread not to freeze and buttons would still be clickable.
But with this approach, whenever the user clicks on the second tile, if there is no match the image is not even displayed, even when my showImage()
method is called before the code above, and I'm not sure why this is. So the user knows there was no match because after 1 second the tiles go back to their initial state, but they never got to see the image on the second button.
As another approach, I also though of disabling all buttons and then after the single shot QTimer times out, re-enabling back only the ones that have not been matched yet. But this would require additional logic to keep track of which tiles have been matched. So for now I'm sticking to the
Is there a cleaner solution? Maybe there's a way to make the QTimer freeze the main thread until it times out?