Я пытаюсь создать простую игру памяти с Qt 5.11.1 и C++, где вы получаете несколько плиток на экране, и вам нужно щелкнуть две и попытаться сопоставить изображения, которые они показывают.
Мои плитки реализованы как QPushButtons. Каждый раз, когда вы нажимаете на один из них, отображается изображение (путем вызова метода showImage()
, который изменяет фон кнопки). При нажатии на вторую плитку, если есть совпадение, две кнопки отключаются, поэтому вы не можете нажать на них снова (и вы получите более высокий балл). Однако, если вы не получили совпадения, две плитки, которые вы только что щелкнули, вернутся в исходное состояние (отсутствие изображения) через 1 секунду (это позволяет пользователю «запомнить», какое изображение отображалось на каждой плитке) .
Всякий раз, когда вы нажимаете на «плитку» (кнопку), она отключается (button->setEnabled(false)
). Если после щелчка по второй плитке совпадения не было, то обе плитки переворачиваются назад, а затем снова setEnabled(true)
. Я использую один выстрел QTimer для вызова метода, который вернет плитки:
QTimer::singleShot(1000, this, SLOT(turnTilesBack()));
firstTile->setEnabled(true);
secondTile->setEnabled(true);
Все работает, как и ожидалось, за исключением одного: поскольку QTimer работает в своем собственном потоке (по крайней мере, я так понял из того, что я прочитал), все доступные плитки остаются включенными в течение 1000-миллисекундного промежутка времени, что позволяет пользователю продолжать нажимать на них. Однако, когда совпадений нет, я хотел бы «заморозить» кнопки до тех пор, пока не истечет время QTimer, чтобы пользователь не мог продолжать играть, пока плитки не повернутся назад.
Поэтому вместо использования QTimer я пробовал это решение, которое я видел по этому вопросу (Как создать функцию паузы/ожидания с помощью Qt?):
QTime dieTime= QTime::currentTime().addSecs(1);
while (QTime::currentTime() < dieTime)
turnTilesBack();
хотя я удалил эту строку: QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
, так как это привело бы к тому, что основной поток не зависал, а кнопки по-прежнему можно было бы нажимать.
Но при таком подходе всякий раз, когда пользователь нажимает на вторую плитку, если совпадения нет, изображение даже не отображается, даже когда мой метод showImage()
вызывается перед приведенным выше кодом, и я не уверен, почему это так. Таким образом, пользователь знает, что совпадения не было, потому что через 1 секунду плитки возвращаются в исходное состояние, но он так и не увидел изображение на второй кнопке.
В качестве другого подхода я также подумал об отключении всех кнопок, а затем, после истечения времени ожидания одиночного выстрела QTimer, повторном включении только тех, которые еще не были сопоставлены. Но это потребует дополнительной логики для отслеживания того, какие плитки были сопоставлены. Так что пока я придерживаюсь
Есть ли более чистое решение? Может быть, есть способ заставить QTimer заморозить основной поток, пока он не истечет?