From c5ec33cce1091ed018f688f9f7adedd09d4daf1c Mon Sep 17 00:00:00 2001 From: ce-amtic Date: Wed, 7 Jun 2023 23:12:10 +0800 Subject: [PATCH] refined GameWidget --- DialogBox/messagebox.cpp | 2 +- DialogBox/messagebox.h | 2 +- Object/bot.cpp | 6 +- Object/bot.h | 1 + Object/judge.cpp | 1 + Widget/gamewidget.cpp | 120 ++++++++++++++++++--------------------- Widget/gamewidget.h | 4 +- Widget/startwidget.cpp | 2 +- main.cpp | 2 +- 9 files changed, 66 insertions(+), 74 deletions(-) diff --git a/DialogBox/messagebox.cpp b/DialogBox/messagebox.cpp index c043b39..e31da29 100644 --- a/DialogBox/messagebox.cpp +++ b/DialogBox/messagebox.cpp @@ -34,7 +34,7 @@ void MessageBox::mousePressEvent(QMouseEvent *event) {clickToClose();} bool MessageBox::clickToClose() { - if(pendingClose && clock() - baseTime <= 3000) return false; + if(pendingClose && clock() - baseTime <= 5000) return false; timeUpClose(); return true; } diff --git a/DialogBox/messagebox.h b/DialogBox/messagebox.h index 0bb75df..762630b 100644 --- a/DialogBox/messagebox.h +++ b/DialogBox/messagebox.h @@ -19,7 +19,7 @@ * > void set(QString text, int tim, bool pendingClos) * > text : 显示的文字 * > tim : 超时自动关闭,设置为 0 时, 必须要手动点击消息框才可关闭 -* > pendingClos : 强制 3s 内不能被关闭 +* > pendingClos : 强制 5s 内不能被关闭 * > bool clickToClose() * > 模拟鼠标点击关闭,受 pendingClose 影响 * > void timeUpClose() diff --git a/Object/bot.cpp b/Object/bot.cpp index ccc0e7e..012627a 100644 --- a/Object/bot.cpp +++ b/Object/bot.cpp @@ -23,6 +23,7 @@ Bot::~Bot() void Bot::init() { + searchStartTime = 0; ItemVector().swap(chooseVec); dfsBoardTime = 0; eps = 0.03; @@ -281,4 +282,7 @@ void Bot::makeRandomMove() while(!judge->CheckVaild(x, y)); judge->PlaceAPiece(x, y); } - +qint64 Bot::getStartTime() +{ + return searchStartTime; +} diff --git a/Object/bot.h b/Object/bot.h index efbc47c..e5bc8c2 100644 --- a/Object/bot.h +++ b/Object/bot.h @@ -24,6 +24,7 @@ class Bot : public QThread ~Bot(); void init(); void run(); // run 函数是 bot 作为独立线程的入口, 通过 bot->start() 来启动这个独立线程, run 函数本身相当于 makeAMove + qint64 getStartTime(); signals: void timeout(); diff --git a/Object/judge.cpp b/Object/judge.cpp index 80394a5..993f3e6 100644 --- a/Object/judge.cpp +++ b/Object/judge.cpp @@ -64,6 +64,7 @@ void Judge::init() ItemVector().swap(savedStep); blockCnt = 0; curPlayer = 0; + playerRole = 0; loadState = 0; hasSentREA = hasSentTIM = hasSentGIV = hasSentSUI = false; log(Level::Debug, "Judge initialized"); diff --git a/Widget/gamewidget.cpp b/Widget/gamewidget.cpp index 564e4c7..0353594 100644 --- a/Widget/gamewidget.cpp +++ b/Widget/gamewidget.cpp @@ -94,11 +94,9 @@ GameWidget::GameWidget(Judge *j, QWidget *parent) : connect(timerForPlayer,&QTimer::timeout, this, &GameWidget::playerTimeout_OFFL); connect(timerForBar,&QTimer::timeout,this,&GameWidget::updateBar); connect(judge, &Judge::GIVEUP_OP, this, &GameWidget::remoteResign); - connect(judge, &Judge::TIMEOUT_END_OP, this, [&](){gameLose(1);}); connect(judge, &Judge::SUICIDE_END_OP, this, [&](){ - gameWin(1); - clickToCloseMB(true); sendMessage(3); + endGame('W'); }); connect(judge, &Judge::CHAT_OP, this, [&](NetworkData d){ QString s = "<" + judge->oppoOL + "> : \n" + d.data1; @@ -107,9 +105,27 @@ GameWidget::GameWidget(Judge *j, QWidget *parent) : connect(judge, &Judge::MOVE_OP, this, [&](){ if(autoControl->isToggled()) autoPlayer->start(); }); + connect(judge, &Judge::TIMEOUT_END_OP, this, [&](){ + if(autoPlayer->getStartTime() == 0) + { + judge->log(Level::Error, "auto player haven't been started yet!"); + return; + } + if(QDateTime::currentMSecsSinceEpoch() - autoPlayer->getStartTime() > BOT_TIMEOUT * 1000) + { + playerTimeout_OL(); + judge->log(Level::Info, "auto player run for "+QString::number(QDateTime::currentMSecsSinceEpoch()-autoPlayer->getStartTime()) + +"ms, TIMEOUT_END confirmed"); + } + else + { + judge->log(Level::Error, "auto player run for "+QString::number(QDateTime::currentMSecsSinceEpoch()-autoPlayer->getStartTime()) + +"ms but opponent claims TIMEOUT_END"); + } + }); connect(autoControl, &SwitchControl::toggled, this, [&](bool checked){ if(checked && judge->curPlayer == 1) autoPlayer->start(); - if(!checked) autoPlayer->terminate(); + if(!checked && autoPlayer->isRunning()) autoPlayer->terminate(); }); connect(autoPlayer, &QThread::finished, this, [&](){ if(!autoControl->isToggled()) return; @@ -122,7 +138,7 @@ GameWidget::GameWidget(Judge *j, QWidget *parent) : if(autoControl->isToggled()){ autoControl->setDisabled(true); autoControl->setToggled(false); - autoPlayer->terminate(); + if(autoPlayer->isRunning()) autoPlayer->terminate(); } }); connect(bot, &Bot::timeout, this, &GameWidget::botTimeout); @@ -158,7 +174,6 @@ void GameWidget::mousePressEvent(QMouseEvent *event) return ; } - emit mousePress(); if(judge->curPlayer == -1) return; // 判断游戏结束 if(!judge->runMode && bot->isRunning()) return; // 等待 bot 落子 @@ -216,6 +231,18 @@ void GameWidget::firstMove(int player) if(judge->runMode == 1) judge->curPlayer ^= 1; } } +void GameWidget::endGame(char loadState) +{ + stopTimer(); + + autoControl->setToggled(false); + if(autoPlayer->isRunning()) autoPlayer->terminate(); + if(bot->isRunning()) bot->terminate(); + + judge->curPlayerBak = judge->curPlayer; + judge->curPlayer = -1; + judge->loadState = loadState; +} void GameWidget::closeEvent(QCloseEvent* event) { stopTimer(); @@ -227,10 +254,8 @@ void GameWidget::closeEvent(QCloseEvent* event) mouse_disabled = 0; autoControl->setToggled(false); - autoPlayer->terminate(); - bot->terminate(); - bot->init(); - autoPlayer->init(); + if(autoPlayer->isRunning()) autoPlayer->terminate(); + if(bot->isRunning()) bot->terminate(); judge->init(); } @@ -471,34 +496,6 @@ void GameWidget::drawDemo(QPainter &painter) // 绘画 FYH } // 判胜负与计时器相关 -void GameWidget::gameLose(int type) -{ - stopTimer(); - if(type) sendMessage(1); - else sendMessage(3); - - autoControl->setToggled(false); - autoPlayer->terminate(); - bot->terminate(); - - judge->curPlayerBak = judge->curPlayer; - judge->curPlayer = -1; - judge->loadState = 'T'; -} -void GameWidget::gameWin(int type) -{ - stopTimer(); - if(type) sendMessage(0); - else sendMessage(4); - - autoControl->setToggled(false); - autoPlayer->terminate(); - bot->terminate(); - - judge->curPlayerBak = judge->curPlayer; - judge->curPlayer = -1; - judge->loadState = 'W'; -} void GameWidget::stopTimer() { timerForPlayer->stop(); timerForBar->stop(); @@ -513,15 +510,29 @@ void GameWidget::startTimer() { basetime=clock(); } } -void GameWidget::botTimeout() {if(judge->curPlayer >= 0) gameWin(0);} -void GameWidget::playerTimeout_OFFL() {if(judge->curPlayer >= 0) gameLose(0);} +void GameWidget::botTimeout() +{ + sendMessage(4); + endGame('W'); +} +void GameWidget::playerTimeout_OFFL() +{ + sendMessage(3); + endGame('T'); +} void GameWidget::playerTimeout_OL() { // 发送 TIMEOUT_END_OP if(!judge->curPlayer) // 当前是等待响应的一方,那么对手超时己方胜利 { judge->send(NetworkData(OPCODE::TIMEOUT_END_OP, judge->usrnameOL, "Sorry you timeout!")); - gameWin(1); + sendMessage(0); + endGame('W'); + } + else + { + sendMessage(1); + endGame('T'); } } @@ -695,16 +706,8 @@ void GameWidget::goOFFL() } void GameWidget::remoteResign() { - stopTimer(); sendMessage(6); - - autoControl->setToggled(false); - autoPlayer->terminate(); - bot->terminate(); - - judge->curPlayerBak = judge->curPlayer; - judge->curPlayer = -1; - judge->loadState = 'W'; + endGame('W'); } void GameWidget::on_try() @@ -739,17 +742,8 @@ void GameWidget::on_restartButton_clicked_OFFL() void GameWidget::on_resignButton_clicked_OFFL() { if(judge->curPlayer == -1) return; - - stopTimer(); sendMessage(5); - - autoControl->setToggled(false); - autoPlayer->terminate(); - bot->terminate(); - - judge->curPlayerBak = judge->curPlayer; - judge->curPlayer = -1; - judge->loadState = 'G'; + endGame('G'); } void GameWidget::on_restartButton_clicked_OL() { @@ -849,12 +843,6 @@ void GameWidget::on_loadButton_clicked() if(strState) // 是否为终局 { -// if(judge->loadState == 'W') -// gameWin(judge->runMode); -// if(judge->loadState == 'L') -// gameLose(judge->runMode); -// if(judge->loadState == 'G') -// on_resignButton_clicked_OFFL(); judge->init(); ui->saveButton->setEnabled(0); turn_on_review(); diff --git a/Widget/gamewidget.h b/Widget/gamewidget.h index afd94fb..2e8a6bb 100644 --- a/Widget/gamewidget.h +++ b/Widget/gamewidget.h @@ -46,6 +46,7 @@ class GameWidget : public QWidget public slots: void startGame(int player); // 进入 gameWidget 时首先调用 startGame void firstMove(int player); + void endGame(char loadState); void startTimer(); // 当对局开始时,无论谁先手(机器下第一个棋子认为不需要时间),都打开玩家的计时器 void stopTimer(); void updateCB(); // 更新棋盘 @@ -66,7 +67,6 @@ private slots: void botTimeout(); // bot超时的槽函数,用于链接计时器 void clickToCloseMB(bool force = false); // 再次点击棋盘时关闭消息弹窗 void updateBar(); // 更新倒计时进度条 - void remoteResign(); // 联机认输 void on_try(); @@ -83,8 +83,6 @@ private slots: void setColorForBar(); // 计时器的颜色与当前执棋颜色一致 void mousePressEvent(QMouseEvent *event) override; // 监听鼠标坐标 - void gameLose(int type = 0); // 输掉游戏(0->PVE 1->PVP) - void gameWin(int type = 0); // 赢了游戏(0->PVE 1->PVP) void dataToString(); // 编码 (playerRole:0->w/2->b) (runMode:0->PVE/PVP/server/client) void stringToData(); // 解码 diff --git a/Widget/startwidget.cpp b/Widget/startwidget.cpp index 46e0e2a..0b04874 100644 --- a/Widget/startwidget.cpp +++ b/Widget/startwidget.cpp @@ -46,7 +46,7 @@ StartWidget::StartWidget(Judge *j, QWidget *parent) : connect(ui->startAsBlack, &QPushButton::clicked, this, &StartWidget::on_startAsBlack_clicked_OFFL); connect(ui->startAsWhite, &QPushButton::clicked, this, &StartWidget::on_startAsWhite_clicked_OFFL); connect(confirmD, &OptionDialog::OK, this, [&](){ - if(judge->curPlayer == -1) // on GameWidget + if(judge->playerRole != 0) // on GameWidget emit switchLayer(0); if(oppoRole == 1) {sendStartAsWhite(true); on_startAsWhite_clicked_OFFL();} else {sendStartAsBlack(true); on_startAsBlack_clicked_OFFL();} diff --git a/main.cpp b/main.cpp index 399d98d..4967954 100644 --- a/main.cpp +++ b/main.cpp @@ -22,7 +22,7 @@ int main(int argc, char *argv[]) // 信号槽 QObject::connect(startWidget, &StartWidget::switchLayer, stackLayout, &QStackedLayout::setCurrentIndex); - QObject::connect(startWidget, &StartWidget::switchLayer, gameWidget, [&](int layer){if(layer == 0) gameWidget->close();}); + QObject::connect(startWidget, &StartWidget::switchLayer, gameWidget, [&](int layer){if(layer == 0){gameWidget->close();}}); QObject::connect(startWidget, &StartWidget::startAs, judge, &Judge::setPlayerRole); QObject::connect(startWidget, &StartWidget::startAs, gameWidget, &GameWidget::startGame); QObject::connect(startWidget->settingDialog, &SettingDialog::goOL, gameWidget, &GameWidget::goOL);