AI与GUI交互逻辑优化

This commit is contained in:
liuweilhy 2018-12-09 04:09:17 +08:00
parent 76da5d3527
commit 3d36cefa8d
7 changed files with 330 additions and 342 deletions

View File

@ -48,7 +48,7 @@ void AiThread::run()
mutex.unlock();
}
ai_ab.alphaBetaPruning(3);
ai_ab.alphaBetaPruning(6);
const char * str = ai_ab.bestMove();
qDebug() << str;
if (strcmp(str, "error!"))

View File

@ -334,89 +334,22 @@ void GameController::timerEvent(QTimerEvent *event)
*/
}
bool GameController::command(const QString &cmd, bool update /*= true*/)
{
// 防止接收滞后结束的线程发送的指令
if (sender() == &ai1 && !isEngine1)
return false;
if (sender() == &ai2 && !isEngine2)
return false;
if (!chess.command(cmd.toStdString().c_str()))
return false;
if (chess.getPhase() == NineChess::GAME_NOTSTARTED) {
gameReset();
gameStart();
}
if (update)
updateScence(chess);
// 将新增的棋谱行插入到ListModel
currentRow = manualListModel.rowCount() - 1;
int k = 0;
// 输出命令行
for (auto i = (chess.getCmdList())->begin(); i != (chess.getCmdList())->end(); ++i) {
// 跳过已添加的因标准list容器没有下标
if (k++ <= currentRow)
continue;
manualListModel.insertRow(++currentRow);
manualListModel.setData(manualListModel.index(currentRow), (*i).c_str());
}
// AI设置
if (&chess == &(this->chess)) {
// 如果还未决出胜负
if (chess.whoWin() == NineChess::NOBODY) {
if (chess.whosTurn() == NineChess::PLAYER1) {
if (isEngine1)
ai1.resume();
}
else {
if (isEngine2)
ai2.resume();
}
}
// 如果已经决出胜负
else {
ai1.stop();
ai2.stop();
}
}
return true;
}
// 历史局面
bool GameController::phaseChange(int row)
{
// 如果row是当前浏览的棋谱行则不需要刷新
if (currentRow == row)
return false;
// 需要刷新
currentRow = row;
int rows = manualListModel.rowCount();
QStringList mlist = manualListModel.stringList();
qDebug() << "rows:" << rows << " current:" << row;
for (int i = 0; i <= row; i++)
{
qDebug() << mlist.at(i);
chessTemp.command(mlist.at(i).toStdString().c_str());
}
// 下面这步关键,会让悔棋者承担时间损失
chessTemp.setStartTimeb(chess.getStartTimeb());
// 刷新棋局场景
updateScence(chessTemp);
return true;
}
// 槽函数根据QGraphicsScene的信号和状态来执行选子、落子或去子
bool GameController::actionPiece(QPointF pos)
{
bool result = false;
// 点击非落子点,不执行
int c, p;
if (!scene.pos2cp(pos, c, p)) {
return false;
}
// 是否在浏览历史记录
// 电脑走棋时,点击无效
if (chess.whosTurn() == NineChess::PLAYER1 && isEngine1)
return false;
if (chess.whosTurn() == NineChess::PLAYER2 && isEngine2)
return false;
// 在浏览历史记录时点击棋盘,则认为是悔棋
if (currentRow != manualListModel.rowCount() - 1)
{
// 定义新对话框
@ -444,39 +377,60 @@ bool GameController::actionPiece(QPointF pos)
}
}
else
{
return result;
}
return false;
}
switch (chess.getPhase()) {
case NineChess::GAME_NOTSTARTED:
// 如果未开局则开局这里还要继续判断不可break
// 如果未开局则开局
if (chess.getPhase() == NineChess::GAME_NOTSTARTED)
gameStart();
case NineChess::GAME_OPENING:
// 如果是开局阶段(轮流落下新子),落子
if (chess.getAction() == NineChess::ACTION_PLACE) {
result = placePiece(pos);
}// 去子
else if (chess.getAction() == NineChess::ACTION_CAPTURE) {
result = capturePiece(pos);
// 判断执行选子、落子或去子
bool result = false;
PieceItem *piece = nullptr;
QGraphicsItem *item = scene.itemAt(pos, QTransform());
switch (chess.getAction())
{
case NineChess::ACTION_PLACE:
if (chess.place(c, p))
{
if (chess.getAction() == NineChess::ACTION_CAPTURE) {
// 播放成三音效
playSound(":/sound/resources/sound/capture.wav");
}
else {
// 播放移动棋子音效
playSound(":/sound/resources/sound/drog.wav");
}
result = true;
break;
}
// 如果移子不成功尝试重新选子这里不break
case NineChess::ACTION_CHOOSE:
piece = qgraphicsitem_cast<PieceItem *>(item);
if (!piece)
break;
if (chess.choose(c, p)) {
// 播放选子音效
playSound(":/sound/resources/sound/choose.wav");
result = true;
}
else {
// 播放禁止音效
playSound(":/sound/resources/sound/forbidden.wav");
}
break;
case NineChess::GAME_MID:
// 如果是中局阶段(轮流移子)
// 选子
if (chess.getAction() == NineChess::ACTION_CHOOSE) {
result = choosePiece(pos);
}// 移子
else if (chess.getAction() == NineChess::ACTION_PLACE) {
// 如果移子不成功,尝试重新选子
result = movePiece(pos);
}// 去子
else if (chess.getAction() == NineChess::ACTION_CAPTURE) {
result = capturePiece(pos);
case NineChess::ACTION_CAPTURE:
if (chess.capture(c, p)) {
// 播放音效
playSound(":/sound/resources/sound/remove.wav");
result = true;
}
else {
// 播放禁止音效
playSound(":/sound/resources/sound/forbidden.wav");
}
break;
@ -487,6 +441,10 @@ bool GameController::actionPiece(QPointF pos)
if (result)
{
// 发信号更新状态栏
message = QString::fromStdString(chess.getTip());
emit statusBarChanged(message);
// 将新增的棋谱行插入到ListModel
currentRow = manualListModel.rowCount() - 1;
int k = 0;
@ -498,116 +456,142 @@ bool GameController::actionPiece(QPointF pos)
manualListModel.insertRow(++currentRow);
manualListModel.setData(manualListModel.index(currentRow), (*i).c_str());
}
if (chess.whoWin() != NineChess::NOBODY &&
(manualListModel.data(manualListModel.index(currentRow-1))).toString().contains("Time over."))
if (chess.whoWin() != NineChess::NOBODY &&
(manualListModel.data(manualListModel.index(currentRow - 1))).toString().contains("Time over."))
playSound(":/sound/resources/sound/win.wav");
// AI设置
if (&chess == &(this->chess)) {
// 如果还未决出胜负
if (chess.whoWin() == NineChess::NOBODY) {
if (chess.whosTurn() == NineChess::PLAYER1) {
if (isEngine1)
ai1.resume();
if (isEngine2)
ai2.pause();
}
else {
if (isEngine1)
ai1.pause();
if (isEngine2)
ai2.resume();
}
}
// 如果已经决出胜负
else {
ai1.stop();
ai2.stop();
}
}
}
updateScence();
return result;
}
// 选子
bool GameController::choosePiece(QPointF pos)
// 棋谱的命令行执行
bool GameController::command(const QString &cmd, bool update /*= true*/)
{
int c, p;
if (!scene.pos2cp(pos, c, p)) {
return false;
}
PieceItem *piece = nullptr;
QGraphicsItem *item = scene.itemAt(pos, QTransform());
piece = qgraphicsitem_cast<PieceItem *>(item);
if (!piece) {
return false;
}
if (chess.choose(c, p)) {
// 发信号更新状态栏
message = QString::fromStdString(chess.getTip());
emit statusBarChanged(message);
// 播放选子音效
playSound(":/sound/resources/sound/choose.wav");
return true;
}
else {
// 播放禁止音效
playSound(":/sound/resources/sound/forbidden.wav");
return false;
}
}
Q_UNUSED(hasSound)
// 落下新子
bool GameController::placePiece(QPointF pos)
{
int c, p;
if (!scene.pos2cp(pos, c, p)) {
// 防止接收滞后结束的线程发送的指令
if (sender() == &ai1 && !isEngine1)
return false;
}
if (!chess.place(c, p)) {
// 播放禁止音效
playSound(":/sound/resources/sound/forbidden.wav");
if (sender() == &ai2 && !isEngine2)
return false;
// 声音
QString sound;
switch (chess.getAction())
{
case NineChess::ACTION_CHOOSE:
case NineChess::ACTION_PLACE:
sound = ":/sound/resources/sound/drog.wav";
break;
case NineChess::ACTION_CAPTURE:
sound = ":/sound/resources/sound/remove.wav";
break;
default:
break;
}
if (!chess.command(cmd.toStdString().c_str()))
return false;
if (sound == ":/sound/resources/sound/drog.wav" && chess.getAction() == NineChess::ACTION_CAPTURE)
{
sound = ":/sound/resources/sound/capture.wav";
}
if (chess.getPhase() == NineChess::GAME_NOTSTARTED) {
gameReset();
gameStart();
}
if (update) {
playSound(sound);
updateScence(chess);
}
// 将新增的棋谱行插入到ListModel
currentRow = manualListModel.rowCount() - 1;
int k = 0;
// 输出命令行
for (auto i = (chess.getCmdList())->begin(); i != (chess.getCmdList())->end(); ++i) {
// 跳过已添加的因标准list容器没有下标
if (k++ <= currentRow)
continue;
manualListModel.insertRow(++currentRow);
manualListModel.setData(manualListModel.index(currentRow), (*i).c_str());
}
// AI设置
if (&chess == &(this->chess)) {
// 如果还未决出胜负
if (chess.whoWin() == NineChess::NOBODY) {
if (chess.whosTurn() == NineChess::PLAYER1) {
if (isEngine1)
ai1.resume();
if (isEngine2)
ai2.pause();
}
else {
if (isEngine1)
ai1.pause();
if (isEngine2)
ai2.resume();
}
}
// 如果已经决出胜负
else {
ai1.stop();
ai2.stop();
}
}
// 发信号更新状态栏
message = QString::fromStdString(chess.getTip());
emit statusBarChanged(message);
// 播放成三音效
if (chess.getAction() == NineChess::ACTION_CAPTURE)
playSound(":/sound/resources/sound/capture.wav");
// 播放落下棋子音效
else
playSound(":/sound/resources/sound/drog.wav");
return true;
}
// 移动旧子
bool GameController::movePiece(QPointF pos)
// 浏览历史局面通过command函数刷新局面显示
bool GameController::phaseChange(int row)
{
if (!currentPiece) {
// 如果row是当前浏览的棋谱行则不需要刷新
if (currentRow == row)
return false;
}
int c, p;
if (!scene.pos2cp(pos, c, p)) {
return false;
}
if (chess.place(c, p))
// 需要刷新
currentRow = row;
int rows = manualListModel.rowCount();
QStringList mlist = manualListModel.stringList();
qDebug() << "rows:" << rows << " current:" << row;
for (int i = 0; i <= row; i++)
{
// 发信号更新状态栏
message = QString::fromStdString(chess.getTip());
emit statusBarChanged(message);
// 播放成三音效
if (chess.getAction() == NineChess::ACTION_CAPTURE)
playSound(":/sound/resources/sound/capture.wav");
// 播放移动棋子音效
else
playSound(":/sound/resources/sound/move.wav");
return true;
qDebug() << mlist.at(i);
chessTemp.command(mlist.at(i).toStdString().c_str());
}
// 如果移子不成功,尝试重新选子
else
{
return choosePiece(pos);
}
}
// 去子
bool GameController::capturePiece(QPointF pos)
{
int c, p;
if (!scene.pos2cp(pos, c, p)) {
return false;
}
if (!chess.capture(c, p)) {
// 播放禁止音效
playSound(":/sound/resources/sound/forbidden.wav");
return false;
}
// 发信号更新状态栏
message = QString::fromStdString(chess.getTip());
emit statusBarChanged(message);
// 播放音效
playSound(":/sound/resources/sound/remove.wav");
// 下面这步关键,会让悔棋者承担时间损失
chessTemp.setStartTimeb(chess.getStartTimeb());
// 刷新棋局场景
updateScence(chessTemp);
return true;
}

View File

@ -75,7 +75,7 @@ public slots:
bool command(const QString &cmd, bool update = true);
// 历史局面及局面改变
bool phaseChange(int row);
// 更新棋局显示,每步后必须执行
// 更新棋局显示,每步后执行才能刷新局面
bool updateScence();
bool updateScence(NineChess &chess);
@ -83,14 +83,6 @@ protected:
//bool eventFilter(QObject * watched, QEvent * event);
// 定时器
void timerEvent(QTimerEvent * event);
// 选子
bool choosePiece(QPointF pos);
// 落下新子
bool placePiece(QPointF pos);
// 移动旧子
bool movePiece(QPointF pos);
// 去子
bool capturePiece(QPointF pos);
private:
// 棋对象的数据模型

View File

@ -7,7 +7,6 @@
#include "ninechessai_ab.h"
#include <cmath>
#include <time.h>
#include <qdebug.h>
NineChessAi_ab::NineChessAi_ab():
rootNode(nullptr),
@ -156,28 +155,6 @@ void NineChessAi_ab::setChess(const NineChess &chess)
rootNode->parent = nullptr;
requiredQuit = false;
// 生成棋子价值表
for (int j = 0; j < NineChess::SEAT; j++)
{
// 对于0、2、4、6位偶数位
if (!(j & 1)) {
boardScore[1 * NineChess::SEAT + j] = 90;
boardScore[2 * NineChess::SEAT + j] = 100;
boardScore[3 * NineChess::SEAT + j] = 90;
}
// 对于有斜线情况下的1、3、5、7位奇数位
else if(chessTemp.rule.hasObliqueLine) {
boardScore[1 * NineChess::SEAT + j] = 85;
boardScore[2 * NineChess::SEAT + j] = 95;
boardScore[3 * NineChess::SEAT + j] = 85;
}
// 对于无斜线情况下的1、3、5、7位奇数位
else {
boardScore[1 * NineChess::SEAT + j] = 80;
boardScore[2 * NineChess::SEAT + j] = 85;
boardScore[3 * NineChess::SEAT + j] = 80;
}
}
}
int NineChessAi_ab::evaluate(Node *node)
@ -189,27 +166,38 @@ int NineChessAi_ab::evaluate(Node *node)
case NineChess::GAME_NOTSTARTED:
break;
// 开局和中局阶段用同样的评价方法
case NineChess::GAME_OPENING:
case NineChess::GAME_MID:
// 按手棋数目计分每子50分
value += (chessData->player1_InHand) * 50 - (chessData->player2_InHand) * 50;
// 按手中的棋子计分不要break;
value += chessData->player1_InHand * 50 - chessData->player2_InHand * 50;
// 按场上棋子计分
for (int i = 1*NineChess::SEAT; i < NineChess::SEAT*(NineChess::RING+1); i++) {
if (chessData->board[i] & 0x10)
value += boardScore[i];
else if (chessData->board[i] & 0x20)
value -= boardScore[i];
value += chessData->player1_Remain * 100 - chessData->player2_Remain * 100;
switch (chessData->action)
{
// 选子和落子使用相同的评价方法
case NineChess::ACTION_CHOOSE:
case NineChess::ACTION_PLACE:
break;
// 如果形成去子状态每有一个可去的子算100分
case NineChess::ACTION_CAPTURE:
value += (chessData->turn == NineChess::PLAYER1) ? (chessData->num_NeedRemove) * 100 : -(chessData->num_NeedRemove) * 100;
break;
default:
break;
}
break;
case NineChess::GAME_MID:
// 按场上棋子计分
value += chessData->player1_Remain * 100 - chessData->player2_Remain * 100;
switch (chessData->action)
{
// 选子和落子使用相同的评价方法
case NineChess::ACTION_CHOOSE:
case NineChess::ACTION_PLACE:
break;
// 如果形成去子状态每有一个可去的子算1000分
// 如果形成去子状态每有一个可去的子算100
case NineChess::ACTION_CAPTURE:
value += (chessData->turn == NineChess::PLAYER1) ? chessData->num_NeedRemove * 1000 : -chessData->num_NeedRemove * 1000;
value += (chessData->turn == NineChess::PLAYER1) ? (chessData->num_NeedRemove) * 100 : -(chessData->num_NeedRemove) * 100;
break;
default:
break;
@ -242,6 +230,9 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
{
// 评价值
int value;
// 当前节点的MinMax值最终赋值给节点value与alpha和Beta不同
int minMax;
if (!depth || chessTemp.data.phase == NineChess::GAME_OVER) {
node->value = evaluate(node);
return node->value;
@ -255,45 +246,45 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
// 根据演算模型执行MiniMax检索
// 对先手搜索Max
if (chessTemp.whosTurn() == NineChess::PLAYER1) {
minMax = -infinity;
for (auto child : node->children) {
dataStack.push(chessTemp.data);
if(!chessTemp.command(child->move))
qDebug() << child->move;
chessTemp.command(child->move);
value = alphaBetaPruning(depth - 1, alpha, beta, child);
chessTemp.data = dataStack.top();
dataStack.pop();
// 取最大值
if (value > minMax)
minMax = value;
if (value > alpha)
alpha = value;
// 剪枝返回
if (alpha >= beta) {
node->value = alpha;
return value;
}
if (alpha >= beta)
break;
}
// 取最大值
node->value = alpha;
node->value = minMax;
}
// 对后手搜索Min
else {
minMax = infinity;
for (auto child : node->children) {
dataStack.push(chessTemp.data);
if(!chessTemp.command(child->move))
qDebug() << child->move;
chessTemp.command(child->move);
value = alphaBetaPruning(depth - 1, alpha, beta, child);
chessTemp.data = dataStack.top();
dataStack.pop();
// 取最小值
if (value < minMax)
minMax = value;
if (value < beta)
beta = value;
// 剪枝返回
if (alpha >= beta) {
node->value = beta;
return value;
}
if (alpha >= beta)
break;
}
// 取最小值
node->value = beta;
node->value = minMax;
}
// 返回
return node->value;
@ -303,18 +294,11 @@ const char *NineChessAi_ab::bestMove()
{
if ((rootNode->children).size() == 0)
return "error!";
// 在最好的招法中随机挑一个
int16_t moves[12] = {0};
int n = 0;
for (auto child : rootNode->children) {
if (child->value == rootNode->value)
moves[n++] = child->move;
if (n >= 12)
break;
return move2string(child->move);
}
srand((unsigned)time(0));
int i = rand() % n;
return move2string(moves[i]);
return "error!";
}
const char *NineChessAi_ab::move2string(int16_t move)

View File

@ -97,8 +97,6 @@ private:
static const int infinity = INT32_MAX;
private:
// 棋子价值表
char boardScore[(NineChess::RING + 2)*NineChess::SEAT];
// 命令行
char cmdline[32];
};

View File

@ -27,7 +27,8 @@ NineChessWindow::NineChessWindow(QWidget *parent)
: QMainWindow(parent),
scene(nullptr),
game(nullptr),
ruleNo(-1)
ruleNo(-1),
autoRunTimer(this)
{
ui.setupUi(this);
//去掉标题栏
@ -73,10 +74,14 @@ NineChessWindow::NineChessWindow(QWidget *parent)
// 初始化游戏规则菜单
ui.menu_R->installEventFilter(this);
// 关联自动运行定时器
connect(&autoRunTimer, SIGNAL(timeout()),
this, SLOT(onAutoRunTimeOut()));
// 主窗口居中显示
QRect deskTopRect = qApp->desktop()->availableGeometry();
int unitw=(deskTopRect.width() - width())/2;
int unith=(deskTopRect.height() - height())/2;
int unitw = (deskTopRect.width() - width())/2;
int unith = (deskTopRect.height() - height())/2;
this->move(unitw,unith);
// 游戏初始化
@ -96,6 +101,8 @@ void NineChessWindow::closeEvent(QCloseEvent *event)
{
if (file.isOpen())
file.close();
// 取消自动运行
ui.actionAutoRun_A->setChecked(false);
//qDebug() << "closed";
QMainWindow::closeEvent(event);
}
@ -310,9 +317,13 @@ void NineChessWindow::on_actionLimited_T_triggered()
void NineChessWindow::actionRules_triggered()
{
// 取消自动运行
ui.actionAutoRun_A->setChecked(false);
// 取消其它规则的选择
for(QAction *action: ruleActionList)
action->setChecked(false);
// 选择当前规则
QAction *action = dynamic_cast<QAction *>(sender());
action->setChecked(true);
@ -336,6 +347,8 @@ void NineChessWindow::on_actionNew_N_triggered()
{
if (file.isOpen())
file.close();
// 取消自动运行
ui.actionAutoRun_A->setChecked(false);
// 取消AI设定
ui.actionEngine1_T->setChecked(false);
ui.actionEngine2_R->setChecked(false);
@ -525,6 +538,10 @@ void NineChessWindow::on_actionRowChange()
}
}
// 更新局面
game->phaseChange(currentRow);
/* 下面的代码全部取消改用QTimer的方式实现
// 更新局面
bool changed = game->phaseChange(currentRow);
// 处理自动播放时的动画
@ -542,70 +559,77 @@ void NineChessWindow::on_actionRowChange()
QTimer::singleShot(waitTime, &loop, SLOT(quit()));
loop.exec();
}
*/
}
void NineChessWindow::onAutoRunTimeOut(QPrivateSignal signal)
{
int rows = ui.listView->model()->rowCount();
int currentRow = ui.listView->currentIndex().row();
if (rows <= 1) {
ui.actionAutoRun_A->setChecked(false);
return;
}
// 执行“下一招”
if (currentRow < rows - 1)
{
if (currentRow < rows - 1)
{
ui.listView->setCurrentIndex(ui.listView->model()->index(currentRow + 1, 0));
}
currentRow = ui.listView->currentIndex().row();
// 更新动作状态
if (currentRow <= 0) {
ui.actionBegin_S->setEnabled(false);
ui.actionPrevious_B->setEnabled(false);
ui.actionNext_F->setEnabled(true);
ui.actionEnd_E->setEnabled(true);
ui.actionAutoRun_A->setEnabled(true);
}
else if (currentRow >= rows - 1)
{
ui.actionBegin_S->setEnabled(true);
ui.actionPrevious_B->setEnabled(true);
ui.actionNext_F->setEnabled(false);
ui.actionEnd_E->setEnabled(false);
ui.actionAutoRun_A->setEnabled(false);
}
else
{
ui.actionBegin_S->setEnabled(true);
ui.actionPrevious_B->setEnabled(true);
ui.actionNext_F->setEnabled(true);
ui.actionEnd_E->setEnabled(true);
ui.actionAutoRun_A->setEnabled(true);
}
// 更新局面
game->phaseChange(currentRow);
}
else {
ui.actionAutoRun_A->setChecked(false);
}
}
// 自动运行
void NineChessWindow::on_actionAutoRun_A_toggled(bool arg1)
{
if (!arg1)
return;
int rows = ui.listView->model()->rowCount();
int currentRow = ui.listView->currentIndex().row();
if (rows <= 1)
return;
// 自动运行前禁用所有控件
ui.menuBar->setEnabled(false);
ui.mainToolBar->setEnabled(false);
ui.dockWidget->setEnabled(false);
ui.gameView->setEnabled(false);
// 反复执行“下一招”
while (currentRow < rows - 1)
{
if (currentRow < rows - 1)
{
ui.listView->setCurrentIndex(ui.listView->model()->index(currentRow + 1, 0));
}
currentRow = ui.listView->currentIndex().row();
// 更新动作状态
if (currentRow <= 0) {
ui.actionBegin_S->setEnabled(false);
ui.actionPrevious_B->setEnabled(false);
ui.actionNext_F->setEnabled(true);
ui.actionEnd_E->setEnabled(true);
ui.actionAutoRun_A->setEnabled(true);
}
else if (currentRow >= rows - 1)
{
ui.actionBegin_S->setEnabled(true);
ui.actionPrevious_B->setEnabled(true);
ui.actionNext_F->setEnabled(false);
ui.actionEnd_E->setEnabled(false);
ui.actionAutoRun_A->setEnabled(false);
}
else
{
ui.actionBegin_S->setEnabled(true);
ui.actionPrevious_B->setEnabled(true);
ui.actionNext_F->setEnabled(true);
ui.actionEnd_E->setEnabled(true);
ui.actionAutoRun_A->setEnabled(true);
}
// 更新局面
game->phaseChange(currentRow);
}
// 自动运行结束后启用所有控件
ui.menuBar->setEnabled(true);
ui.mainToolBar->setEnabled(true);
ui.dockWidget->setEnabled(true);
ui.gameView->setEnabled(true);
// 取消自动运行按钮的选中状态
ui.actionAutoRun_A->setChecked(false);
if (arg1) {
// 自动运行前禁用控件
ui.dockWidget->setEnabled(false);
ui.gameView->setEnabled(false);
// 启动定时器
autoRunTimer.start(game->getDurationTime() + 50);
}
else {
// 关闭定时器
autoRunTimer.stop();
// 自动运行结束后启用控件
ui.dockWidget->setEnabled(true);
ui.gameView->setEnabled(true);
}
}
void NineChessWindow::on_actionLocal_L_triggered()

View File

@ -5,6 +5,7 @@
#include <QTextStream>
#include <QStringListModel>
#include <QFile>
#include <QTimer>
#include "ui_ninechesswindow.h"
class GameScene;
@ -22,27 +23,16 @@ protected:
bool eventFilter(QObject * watched, QEvent * event);
void closeEvent(QCloseEvent *event);
private:
// 界面文件
Ui::NineChessWindowClass ui;
// 视图场景
GameScene *scene;
// 控制器
GameController *game;
// 动态增加的菜单栏动作列表
QList <QAction *> ruleActionList;
// 游戏的规则号,涉及菜单项和对话框,所以要有
int ruleNo;
// 文件
QFile file;
// 更新规则标签
void ruleInfo();
private slots:
// 初始化
void initialize();
// 动态增加的菜单栏动作的槽函数
void actionRules_triggered();
// 更新规则标签
void ruleInfo();
// 自动运行定时处理函数
void onAutoRunTimeOut(QPrivateSignal signal);
// 下面是各动作的槽函数
// 注释掉的是已在UI管理器或主窗口初始化函数中连接好的
void on_actionNew_N_triggered();
@ -74,6 +64,22 @@ private slots:
void on_actionViewHelp_V_triggered();
void on_actionWeb_W_triggered();
void on_actionAbout_A_triggered();
private:
// 界面文件
Ui::NineChessWindowClass ui;
// 视图场景
GameScene *scene;
// 控制器
GameController *game;
// 动态增加的菜单栏动作列表
QList <QAction *> ruleActionList;
// 游戏的规则号,涉及菜单项和对话框,所以要有
int ruleNo;
// 文件
QFile file;
// 定时器
QTimer autoRunTimer;
};
#endif // NINECHESSWINDOW_H