修改了一些bug,但AI仍然有些蠢

This commit is contained in:
liuweilhy 2018-12-06 22:09:40 +08:00
parent 24d897eb69
commit 76da5d3527
7 changed files with 229 additions and 181 deletions

View File

@ -1,9 +1,10 @@
#include <QDebug> #include <QDebug>
#include "aithread.h" #include "aithread.h"
AiThread::AiThread(QObject *parent) : QThread(parent), AiThread::AiThread(int id, QObject *parent) : QThread(parent),
waiting_(false) waiting_(false)
{ {
this->id = id;
} }
AiThread::~AiThread() AiThread::~AiThread()
@ -22,27 +23,46 @@ void AiThread::setAi(const NineChess &chess)
void AiThread::run() void AiThread::run()
{ {
// 测试用数据 // 测试用数据
int iTemp = 0; int iTemp = 0;
// 设一个标识1号线程只管玩家12号线程只管玩家2
int i = 0;
forever{ while (!isInterruptionRequested()) {
if (isInterruptionRequested())
return;
mutex.lock(); mutex.lock();
if (waiting_) if (chess->whosTurn() == NineChess::PLAYER1)
pauseCondition.wait(&mutex); i = 1;
mutex.unlock(); else if (chess->whosTurn() == NineChess::PLAYER2)
i = 2;
else
i = 0;
ai_ab.setChess(*chess); if (i != id || waiting_) {
ai_ab.alphaBetaPruning(5); pauseCondition.wait(&mutex);
mutex.unlock();
continue;
}
else {
ai_ab.setChess(*chess);
mutex.unlock();
}
ai_ab.alphaBetaPruning(3);
const char * str = ai_ab.bestMove(); const char * str = ai_ab.bestMove();
qDebug() << str; qDebug() << str;
if (strcmp(str, "error!")) if (strcmp(str, "error!"))
emit command(str); emit command(str);
qDebug() << "Thread" << id << " run " << ++iTemp << "times";
// 测试用 // 执行完毕后继续判断
qDebug() << "thread running " << iTemp++ << "times"; if (!isInterruptionRequested()) {
mutex.lock();
pauseCondition.wait(&mutex);
mutex.unlock();
}
} }
qDebug() << "Thread" << id << " quit.";
} }
void AiThread::pause() void AiThread::pause()
@ -62,14 +82,13 @@ void AiThread::resume()
void AiThread::stop() void AiThread::stop()
{ {
if(isFinished()) if (isFinished() || !isRunning())
return; return;
if(!isInterruptionRequested())
requestInterruption();
mutex.lock(); mutex.lock();
requestInterruption(); waiting_ = false;
if (waiting_) { pauseCondition.wakeAll();
waiting_ = false;
pauseCondition.wakeAll();
}
mutex.unlock(); mutex.unlock();
} }

View File

@ -12,7 +12,7 @@ class AiThread : public QThread
Q_OBJECT Q_OBJECT
public: public:
explicit AiThread(QObject *parent = nullptr); explicit AiThread(int id, QObject *parent = nullptr);
~AiThread(); ~AiThread();
signals: signals:
@ -29,6 +29,8 @@ public slots:
void stop(); void stop();
private: private:
// 玩家ID
int id;
// 互斥锁 // 互斥锁
QMutex mutex; QMutex mutex;
// 线程等待标识,这里没用到,留着以后扩展用 // 线程等待标识,这里没用到,留着以后扩展用

View File

@ -30,7 +30,9 @@ GameController::GameController(GameScene &scene, QObject *parent) : QObject(pare
timeID(0), timeID(0),
ruleNo(-1), ruleNo(-1),
timeLimit(0), timeLimit(0),
stepsLimit(0) stepsLimit(0),
ai1(1),
ai2(2)
{ {
// 已在view的样式表中添加背景scene中不用添加背景 // 已在view的样式表中添加背景scene中不用添加背景
// 区别在于view中的背景不随视图变换而变换scene中的背景随视图变换而变换 // 区别在于view中的背景不随视图变换而变换scene中的背景随视图变换而变换
@ -53,6 +55,11 @@ GameController::~GameController()
// 停止计时器 // 停止计时器
if (timeID != 0) if (timeID != 0)
killTimer(timeID); killTimer(timeID);
// 停掉线程
ai1.stop();
ai2.stop();
ai1.wait();
ai2.wait();
} }
const QMap<int, QStringList> GameController::getActions() const QMap<int, QStringList> GameController::getActions()
@ -94,11 +101,9 @@ void GameController::gameReset()
// 停掉线程 // 停掉线程
ai1.stop(); ai1.stop();
ai1.quit();
ai1.wait();
ai2.stop(); ai2.stop();
ai2.quit(); isEngine1 = false;
ai2.wait(); isEngine2 = false;
// 清除棋子 // 清除棋子
qDeleteAll(pieceList); qDeleteAll(pieceList);
@ -331,29 +336,55 @@ void GameController::timerEvent(QTimerEvent *event)
bool GameController::command(const QString &cmd, bool update /*= true*/) bool GameController::command(const QString &cmd, bool update /*= true*/)
{ {
if (chess.command(cmd.toStdString().c_str())) { // 防止接收滞后结束的线程发送的指令
if (chess.getPhase() == NineChess::GAME_NOTSTARTED) { if (sender() == &ai1 && !isEngine1)
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());
}
return true;
}
else {
return false; 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;
} }
// 历史局面 // 历史局面
@ -724,27 +755,5 @@ bool GameController::updateScence(NineChess &chess)
animationGroup->start(QAbstractAnimation::DeleteWhenStopped); animationGroup->start(QAbstractAnimation::DeleteWhenStopped);
// AI设置
if (&chess == &(this->chess)) {
// 如果还未决出胜负
if (chess.whoWin() == NineChess::NOBODY) {
if (chess.whosTurn() == NineChess::PLAYER1) {
if(isEngine1)
ai1.resume();
ai2.pause();
}
else {
if(isEngine2)
ai2.resume();
ai1.pause();
}
}
// 如果已经决出胜负
else {
ai1.stop();
ai2.stop();
}
}
return true; return true;
} }

View File

@ -1165,13 +1165,13 @@ bool NineChess::command(int16_t move)
if (move < 0) { if (move < 0) {
return capture(-move); return capture(-move);
} }
else if (move & 0x00ff) { else if (move & 0x1f00) {
return place(move & 0x00ff);
}
else {
if (choose(move >> 8)) if (choose(move >> 8))
return place(move & 0x00ff); return place(move & 0x00ff);
} }
else {
return place(move & 0x00ff);
}
return false; return false;
} }

View File

@ -173,50 +173,50 @@ public:
// 获取棋局状态和棋盘数据 // 获取棋局状态和棋盘数据
void getData(struct Rule &rule, int &step, int &flags, const char *&boardsource, int &p1_InHand, int &p2_InHand, int &num_NeedRemove); void getData(struct Rule &rule, int &step, int &flags, const char *&boardsource, int &p1_InHand, int &p2_InHand, int &num_NeedRemove);
// 获取当前规则 // 获取当前规则
const struct Rule *getRule() { return &rule; } const struct Rule *getRule() const { return &rule; }
// 获取棋盘数据 // 获取棋盘数据
const char *getBoard() { return data.board; } const char *getBoard() const { return data.board; }
// 获取棋子位置(c, p) // 获取棋子位置(c, p)
bool getPieceCP(const Players &player, const int &number, int &c, int &p); bool getPieceCP(const Players &player, const int &number, int &c, int &p);
// 获取当前棋子 // 获取当前棋子
bool getCurrentPiece(Players &player, int &number); bool getCurrentPiece(Players &player, int &number);
// 获取当前棋子位置点 // 获取当前棋子位置点
int getCurrentPos() { return currentPos; } int getCurrentPos() const { return currentPos; }
// 获取当前步数 // 获取当前步数
int getStep() { return data.step; } int getStep() const { return data.step; }
// 获取局面阶段标识 // 获取局面阶段标识
enum Phases getPhase() { return data.phase; } enum Phases getPhase() const { return data.phase; }
// 获取轮流状态标识 // 获取轮流状态标识
enum Players whosTurn() { return data.turn; } enum Players whosTurn() const { return data.turn; }
// 获取动作状态标识 // 获取动作状态标识
enum Actions getAction() { return data.action; } enum Actions getAction() const { return data.action; }
// 判断胜负 // 判断胜负
enum Players whoWin() { return winner; } enum Players whoWin() const { return winner; }
// 玩家1和玩家2的用时 // 玩家1和玩家2的用时
void getPlayer_TimeMS(int &p1_ms, int &p2_ms); void getPlayer_TimeMS(int &p1_ms, int &p2_ms);
// 获取棋局的字符提示 // 获取棋局的字符提示
const string getTip() { return tip; } const string getTip() const { return tip; }
// 获取位置点棋子的归属人 // 获取位置点棋子的归属人
enum Players getWhosPiece(int c, int p); enum Players getWhosPiece(int c, int p);
// 获取当前招法 // 获取当前招法
const char *getCmdLine() { return cmdline; } const char *getCmdLine() const { return cmdline; }
// 获得棋谱 // 获得棋谱
const list<string> * getCmdList() { return &cmdlist; } const list<string> * getCmdList() const { return &cmdlist; }
// 获取开局时间 // 获取开局时间
timeb getStartTimeb() { return startTimeb; } timeb getStartTimeb() const { return startTimeb; }
// 重新设置开局时间 // 重新设置开局时间
void setStartTimeb(timeb stimeb) { startTimeb = stimeb; } void setStartTimeb(timeb stimeb) { startTimeb = stimeb; }
// 玩家1剩余未放置子数 // 玩家1剩余未放置子数
int getPlayer1_InHand() { return data.player1_InHand; } int getPlayer1_InHand() const { return data.player1_InHand; }
// 玩家2剩余未放置子数 // 玩家2剩余未放置子数
int getPlayer2_InHand() { return data.player2_InHand; } int getPlayer2_InHand() const { return data.player2_InHand; }
// 玩家1盘面剩余子数 // 玩家1盘面剩余子数
int getPlayer1_Remain() { return data.player1_Remain; } int getPlayer1_Remain() const { return data.player1_Remain; }
// 玩家1盘面剩余子数 // 玩家1盘面剩余子数
int getPlayer2_Remain() { return data.player2_Remain; } int getPlayer2_Remain() const { return data.player2_Remain; }
// 尚待去除的子数 // 尚待去除的子数
int getNum_NeedRemove() { return data.num_NeedRemove; } int getNum_NeedRemove() const { return data.num_NeedRemove; }
// 游戏重置 // 游戏重置
bool reset(); bool reset();

View File

@ -7,6 +7,7 @@
#include "ninechessai_ab.h" #include "ninechessai_ab.h"
#include <cmath> #include <cmath>
#include <time.h> #include <time.h>
#include <qdebug.h>
NineChessAi_ab::NineChessAi_ab(): NineChessAi_ab::NineChessAi_ab():
rootNode(nullptr), rootNode(nullptr),
@ -125,7 +126,10 @@ void NineChessAi_ab::sortChildren(Node *node)
i->value = evaluate(node); i->value = evaluate(node);
} }
// 排序 // 排序
node->children.sort([](Node *n1, Node *n2) { return n1->value > n2->value; }); if(chessTemp.whosTurn() == NineChess::PLAYER1)
node->children.sort([](Node *n1, Node *n2) { return n1->value > n2->value; });
else
node->children.sort([](Node *n1, Node *n2) { return n1->value < n2->value; });
} }
void NineChessAi_ab::deleteTree(Node *node) void NineChessAi_ab::deleteTree(Node *node)
@ -157,21 +161,21 @@ void NineChessAi_ab::setChess(const NineChess &chess)
{ {
// 对于0、2、4、6位偶数位 // 对于0、2、4、6位偶数位
if (!(j & 1)) { if (!(j & 1)) {
boardScore[1 * NineChess::SEAT + j] = 80; boardScore[1 * NineChess::SEAT + j] = 90;
boardScore[2 * NineChess::SEAT + j] = 100; boardScore[2 * NineChess::SEAT + j] = 100;
boardScore[3 * NineChess::SEAT + j] = 80; boardScore[3 * NineChess::SEAT + j] = 90;
} }
// 对于有斜线情况下的1、3、5、7位奇数位 // 对于有斜线情况下的1、3、5、7位奇数位
else if(chessTemp.rule.hasObliqueLine) { else if(chessTemp.rule.hasObliqueLine) {
boardScore[1 * NineChess::SEAT + j] = 70; boardScore[1 * NineChess::SEAT + j] = 85;
boardScore[2 * NineChess::SEAT + j] = 90; boardScore[2 * NineChess::SEAT + j] = 95;
boardScore[3 * NineChess::SEAT + j] = 70; boardScore[3 * NineChess::SEAT + j] = 85;
} }
// 对于无斜线情况下的1、3、5、7位奇数位 // 对于无斜线情况下的1、3、5、7位奇数位
else { else {
boardScore[1 * NineChess::SEAT + j] = 60; boardScore[1 * NineChess::SEAT + j] = 80;
boardScore[2 * NineChess::SEAT + j] = 80; boardScore[2 * NineChess::SEAT + j] = 85;
boardScore[3 * NineChess::SEAT + j] = 60; boardScore[3 * NineChess::SEAT + j] = 80;
} }
} }
} }
@ -203,9 +207,9 @@ int NineChessAi_ab::evaluate(Node *node)
case NineChess::ACTION_CHOOSE: case NineChess::ACTION_CHOOSE:
case NineChess::ACTION_PLACE: case NineChess::ACTION_PLACE:
break; break;
// 如果形成去子状态,每有一个可去的子,算500分 // 如果形成去子状态,每有一个可去的子,算1000分
case NineChess::ACTION_CAPTURE: case NineChess::ACTION_CAPTURE:
value += (chessData->turn == NineChess::PLAYER1) ? chessData->num_NeedRemove * 500 : -chessData->num_NeedRemove * 500; value += (chessData->turn == NineChess::PLAYER1) ? chessData->num_NeedRemove * 1000 : -chessData->num_NeedRemove * 1000;
break; break;
default: default:
break; break;
@ -253,7 +257,8 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
if (chessTemp.whosTurn() == NineChess::PLAYER1) { if (chessTemp.whosTurn() == NineChess::PLAYER1) {
for (auto child : node->children) { for (auto child : node->children) {
dataStack.push(chessTemp.data); dataStack.push(chessTemp.data);
chessTemp.command(child->move); if(!chessTemp.command(child->move))
qDebug() << child->move;
value = alphaBetaPruning(depth - 1, alpha, beta, child); value = alphaBetaPruning(depth - 1, alpha, beta, child);
chessTemp.data = dataStack.top(); chessTemp.data = dataStack.top();
dataStack.pop(); dataStack.pop();
@ -262,6 +267,7 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
alpha = value; alpha = value;
// 剪枝返回 // 剪枝返回
if (alpha >= beta) { if (alpha >= beta) {
node->value = alpha;
return value; return value;
} }
} }
@ -272,7 +278,8 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
else { else {
for (auto child : node->children) { for (auto child : node->children) {
dataStack.push(chessTemp.data); dataStack.push(chessTemp.data);
chessTemp.command(child->move); if(!chessTemp.command(child->move))
qDebug() << child->move;
value = alphaBetaPruning(depth - 1, alpha, beta, child); value = alphaBetaPruning(depth - 1, alpha, beta, child);
chessTemp.data = dataStack.top(); chessTemp.data = dataStack.top();
dataStack.pop(); dataStack.pop();
@ -281,6 +288,7 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
beta = value; beta = value;
// 剪枝返回 // 剪枝返回
if (alpha >= beta) { if (alpha >= beta) {
node->value = beta;
return value; return value;
} }
} }

View File

@ -27,7 +27,7 @@ NineChessWindow::NineChessWindow(QWidget *parent)
: QMainWindow(parent), : QMainWindow(parent),
scene(nullptr), scene(nullptr),
game(nullptr), game(nullptr),
ruleNo(0) ruleNo(-1)
{ {
ui.setupUi(this); ui.setupUi(this);
//去掉标题栏 //去掉标题栏
@ -181,7 +181,6 @@ void NineChessWindow::initialize()
// 默认第2号规则 // 默认第2号规则
ruleNo = 2; ruleNo = 2;
// 设置选中当前规则的菜单项
ruleActionList.at(ruleNo)->setChecked(true); ruleActionList.at(ruleNo)->setChecked(true);
// 重置游戏规则 // 重置游戏规则
game->setRule(ruleNo); game->setRule(ruleNo);
@ -232,6 +231,83 @@ void NineChessWindow::ruleInfo()
// .arg(tr(NineChess::RULES[ruleNo].info)); // .arg(tr(NineChess::RULES[ruleNo].info));
} }
void NineChessWindow::on_actionLimited_T_triggered()
{
/* 其实本来可以用设计器做个ui然后从QDialog派生个自己的对话框
*
*
* QDialog界面
*/
int gStep = game->getStepsLimit();
int gTime = game->getTimeLimit();
// 定义新对话框
QDialog *dialog = new QDialog(this);
dialog->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);
dialog->setObjectName(QStringLiteral("Dialog"));
dialog->setWindowTitle(tr("步数和时间限制"));
dialog->resize(256, 108);
dialog->setModal(true);
// 生成各个控件
QFormLayout *formLayout = new QFormLayout(dialog);
QLabel *label_step = new QLabel(dialog);
QLabel *label_time = new QLabel(dialog);
QComboBox *comboBox_step = new QComboBox(dialog);
QComboBox *comboBox_time = new QComboBox(dialog);
QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
// 设置各个控件ObjectName不设也没关系
/*formLayout->setObjectName(QStringLiteral("formLayout"));
label_step->setObjectName(QStringLiteral("label_step"));
label_time->setObjectName(QStringLiteral("label_time"));
comboBox_step->setObjectName(QStringLiteral("comboBox_step"));
comboBox_time->setObjectName(QStringLiteral("comboBox_time"));
buttonBox->setObjectName(QStringLiteral("buttonBox"));*/
// 设置各个控件数据
label_step->setText(tr("超出限制步数判和:"));
label_time->setText(tr("任意一方超时判负:"));
comboBox_step->addItem(tr("无限制"), 0);
comboBox_step->addItem(tr("50步"), 50);
comboBox_step->addItem(tr("100步"), 100);
comboBox_step->addItem(tr("200步"), 200);
comboBox_time->addItem(tr("无限制"), 0);
comboBox_time->addItem(tr("5分钟"), 5);
comboBox_time->addItem(tr("10分钟"), 10);
comboBox_time->addItem(tr("20分钟"), 20);
comboBox_step->setCurrentIndex(comboBox_step->findData(gStep));
comboBox_time->setCurrentIndex(comboBox_time->findData(gTime));
buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
buttonBox->setCenterButtons(true);
buttonBox->button(QDialogButtonBox::Ok)->setText(tr("确定"));
buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("取消"));
// 布局
formLayout->setSpacing(6);
formLayout->setContentsMargins(11, 11, 11, 11);
formLayout->setWidget(0, QFormLayout::LabelRole, label_step);
formLayout->setWidget(0, QFormLayout::FieldRole, comboBox_step);
formLayout->setWidget(1, QFormLayout::LabelRole, label_time);
formLayout->setWidget(1, QFormLayout::FieldRole, comboBox_time);
formLayout->setWidget(2, QFormLayout::SpanningRole, buttonBox);
// 关联信号和槽函数
connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
// 收集数据
if (dialog->exec() == QDialog::Accepted) {
int dStep = comboBox_step->currentData().toInt();
int dTime = comboBox_time->currentData().toInt();
if (gStep != dStep || gTime != dTime) {
// 重置游戏规则
game->setRule(ruleNo, dStep, dTime);
}
}
// 删除对话框,子控件会一并删除
dialog->disconnect();
delete dialog;
// 更新规则显示
ruleInfo();
}
void NineChessWindow::actionRules_triggered() void NineChessWindow::actionRules_triggered()
{ {
// 取消其它规则的选择 // 取消其它规则的选择
@ -242,9 +318,14 @@ void NineChessWindow::actionRules_triggered()
action->setChecked(true); action->setChecked(true);
ruleNo = action->data().toInt(); ruleNo = action->data().toInt();
// 如果游戏规则没变化,则返回
if (ruleNo == game->getRuleNo())
return;
// 取消AI设定 // 取消AI设定
ui.actionEngine1_T->setChecked(false); ui.actionEngine1_T->setChecked(false);
ui.actionEngine2_R->setChecked(false); ui.actionEngine2_R->setChecked(false);
// 重置游戏规则 // 重置游戏规则
game->setRule(ruleNo); game->setRule(ruleNo);
// 更新规则显示 // 更新规则显示
@ -255,6 +336,10 @@ void NineChessWindow::on_actionNew_N_triggered()
{ {
if (file.isOpen()) if (file.isOpen())
file.close(); file.close();
// 取消AI设定
ui.actionEngine1_T->setChecked(false);
ui.actionEngine2_R->setChecked(false);
// 重置游戏规则
game->gameReset(); game->gameReset();
} }
@ -280,7 +365,10 @@ void NineChessWindow::on_actionOpen_O_triggered()
bool isok = file.open(QFileDevice::ReadOnly | QFileDevice::Text); bool isok = file.open(QFileDevice::ReadOnly | QFileDevice::Text);
if (isok) if (isok)
{ {
//读文件 // 取消AI设定
ui.actionEngine1_T->setChecked(false);
ui.actionEngine2_R->setChecked(false);
// 读文件
QTextStream textStream(&file); QTextStream textStream(&file);
QString cmd; QString cmd;
cmd = textStream.readLine(); cmd = textStream.readLine();
@ -520,84 +608,6 @@ void NineChessWindow::on_actionAutoRun_A_toggled(bool arg1)
ui.actionAutoRun_A->setChecked(false); ui.actionAutoRun_A->setChecked(false);
} }
void NineChessWindow::on_actionLimited_T_triggered()
{
/* 其实本来可以用设计器做个ui然后从QDialog派生个自己的对话框
*
*
* QDialog界面
*/
int stepLimited = game->getStepsLimit();
int timeLimited = game->getTimeLimit();
// 定义新对话框
QDialog *dialog = new QDialog(this);
dialog->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);
dialog->setObjectName(QStringLiteral("Dialog"));
dialog->setWindowTitle(tr("步数和时间限制"));
dialog->resize(256, 108);
dialog->setModal(true);
// 生成各个控件
QFormLayout *formLayout = new QFormLayout(dialog);
QLabel *label_step = new QLabel(dialog);
QLabel *label_time = new QLabel(dialog);
QComboBox *comboBox_step = new QComboBox(dialog);
QComboBox *comboBox_time = new QComboBox(dialog);
QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
// 设置各个控件ObjectName不设也没关系
/*formLayout->setObjectName(QStringLiteral("formLayout"));
label_step->setObjectName(QStringLiteral("label_step"));
label_time->setObjectName(QStringLiteral("label_time"));
comboBox_step->setObjectName(QStringLiteral("comboBox_step"));
comboBox_time->setObjectName(QStringLiteral("comboBox_time"));
buttonBox->setObjectName(QStringLiteral("buttonBox"));*/
// 设置各个控件数据
label_step->setText(tr("超出限制步数判和:"));
label_time->setText(tr("任意一方超时判负:"));
comboBox_step->addItem(tr("无限制"), 0);
comboBox_step->addItem(tr("50步"), 50);
comboBox_step->addItem(tr("100步"), 100);
comboBox_step->addItem(tr("200步"), 200);
comboBox_time->addItem(tr("无限制"), 0);
comboBox_time->addItem(tr("5分钟"), 5);
comboBox_time->addItem(tr("10分钟"), 10);
comboBox_time->addItem(tr("20分钟"), 20);
comboBox_step->setCurrentIndex(comboBox_step->findData(stepLimited));
comboBox_time->setCurrentIndex(comboBox_time->findData(timeLimited));
buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
buttonBox->setCenterButtons(true);
buttonBox->button(QDialogButtonBox::Ok)->setText(tr("确定"));
buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("取消"));
// 布局
formLayout->setSpacing(6);
formLayout->setContentsMargins(11, 11, 11, 11);
formLayout->setWidget(0, QFormLayout::LabelRole, label_step);
formLayout->setWidget(0, QFormLayout::FieldRole, comboBox_step);
formLayout->setWidget(1, QFormLayout::LabelRole, label_time);
formLayout->setWidget(1, QFormLayout::FieldRole, comboBox_time);
formLayout->setWidget(2, QFormLayout::SpanningRole, buttonBox);
// 关联信号和槽函数
connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
// 收集数据
if (dialog->exec() == QDialog::Accepted) {
stepLimited = comboBox_step->currentData().toInt();
timeLimited = comboBox_time->currentData().toInt();
// 选择当前规则
QAction *action = dynamic_cast<QAction *>(sender());
action->setChecked(true);
int ruleNo = action->data().toInt();
// 重置游戏规则
game->setRule(ruleNo, stepLimited, timeLimited);
}
// 删除对话框,子控件会一并删除
delete dialog;
// 更新规则显示
ruleInfo();
}
void NineChessWindow::on_actionLocal_L_triggered() void NineChessWindow::on_actionLocal_L_triggered()
{ {
ui.actionLocal_L->setChecked(true); ui.actionLocal_L->setChecked(true);