修改了一些bug,但AI仍然有些蠢
This commit is contained in:
parent
24d897eb69
commit
76da5d3527
|
@ -1,9 +1,10 @@
|
|||
#include <QDebug>
|
||||
#include "aithread.h"
|
||||
|
||||
AiThread::AiThread(QObject *parent) : QThread(parent),
|
||||
AiThread::AiThread(int id, QObject *parent) : QThread(parent),
|
||||
waiting_(false)
|
||||
{
|
||||
this->id = id;
|
||||
}
|
||||
|
||||
AiThread::~AiThread()
|
||||
|
@ -22,27 +23,46 @@ void AiThread::setAi(const NineChess &chess)
|
|||
|
||||
void AiThread::run()
|
||||
{
|
||||
|
||||
// 测试用数据
|
||||
int iTemp = 0;
|
||||
// 设一个标识,1号线程只管玩家1,2号线程只管玩家2
|
||||
int i = 0;
|
||||
|
||||
forever{
|
||||
if (isInterruptionRequested())
|
||||
return;
|
||||
while (!isInterruptionRequested()) {
|
||||
mutex.lock();
|
||||
if (waiting_)
|
||||
pauseCondition.wait(&mutex);
|
||||
mutex.unlock();
|
||||
if (chess->whosTurn() == NineChess::PLAYER1)
|
||||
i = 1;
|
||||
else if (chess->whosTurn() == NineChess::PLAYER2)
|
||||
i = 2;
|
||||
else
|
||||
i = 0;
|
||||
|
||||
ai_ab.setChess(*chess);
|
||||
ai_ab.alphaBetaPruning(5);
|
||||
if (i != id || waiting_) {
|
||||
pauseCondition.wait(&mutex);
|
||||
mutex.unlock();
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
ai_ab.setChess(*chess);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
ai_ab.alphaBetaPruning(3);
|
||||
const char * str = ai_ab.bestMove();
|
||||
qDebug() << str;
|
||||
if (strcmp(str, "error!"))
|
||||
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()
|
||||
|
@ -62,14 +82,13 @@ void AiThread::resume()
|
|||
|
||||
void AiThread::stop()
|
||||
{
|
||||
if(isFinished())
|
||||
if (isFinished() || !isRunning())
|
||||
return;
|
||||
|
||||
if(!isInterruptionRequested())
|
||||
requestInterruption();
|
||||
mutex.lock();
|
||||
requestInterruption();
|
||||
if (waiting_) {
|
||||
waiting_ = false;
|
||||
pauseCondition.wakeAll();
|
||||
}
|
||||
waiting_ = false;
|
||||
pauseCondition.wakeAll();
|
||||
mutex.unlock();
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ class AiThread : public QThread
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AiThread(QObject *parent = nullptr);
|
||||
explicit AiThread(int id, QObject *parent = nullptr);
|
||||
~AiThread();
|
||||
|
||||
signals:
|
||||
|
@ -29,6 +29,8 @@ public slots:
|
|||
void stop();
|
||||
|
||||
private:
|
||||
// 玩家ID
|
||||
int id;
|
||||
// 互斥锁
|
||||
QMutex mutex;
|
||||
// 线程等待标识,这里没用到,留着以后扩展用
|
||||
|
|
|
@ -30,7 +30,9 @@ GameController::GameController(GameScene &scene, QObject *parent) : QObject(pare
|
|||
timeID(0),
|
||||
ruleNo(-1),
|
||||
timeLimit(0),
|
||||
stepsLimit(0)
|
||||
stepsLimit(0),
|
||||
ai1(1),
|
||||
ai2(2)
|
||||
{
|
||||
// 已在view的样式表中添加背景,scene中不用添加背景
|
||||
// 区别在于,view中的背景不随视图变换而变换,scene中的背景随视图变换而变换
|
||||
|
@ -53,6 +55,11 @@ GameController::~GameController()
|
|||
// 停止计时器
|
||||
if (timeID != 0)
|
||||
killTimer(timeID);
|
||||
// 停掉线程
|
||||
ai1.stop();
|
||||
ai2.stop();
|
||||
ai1.wait();
|
||||
ai2.wait();
|
||||
}
|
||||
|
||||
const QMap<int, QStringList> GameController::getActions()
|
||||
|
@ -94,11 +101,9 @@ void GameController::gameReset()
|
|||
|
||||
// 停掉线程
|
||||
ai1.stop();
|
||||
ai1.quit();
|
||||
ai1.wait();
|
||||
ai2.stop();
|
||||
ai2.quit();
|
||||
ai2.wait();
|
||||
isEngine1 = false;
|
||||
isEngine2 = false;
|
||||
|
||||
// 清除棋子
|
||||
qDeleteAll(pieceList);
|
||||
|
@ -331,29 +336,55 @@ void GameController::timerEvent(QTimerEvent *event)
|
|||
|
||||
bool GameController::command(const QString &cmd, bool update /*= true*/)
|
||||
{
|
||||
if (chess.command(cmd.toStdString().c_str())) {
|
||||
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());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// 防止接收滞后结束的线程发送的指令
|
||||
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;
|
||||
}
|
||||
|
||||
// 历史局面
|
||||
|
@ -724,27 +755,5 @@ bool GameController::updateScence(NineChess &chess)
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -1165,13 +1165,13 @@ bool NineChess::command(int16_t move)
|
|||
if (move < 0) {
|
||||
return capture(-move);
|
||||
}
|
||||
else if (move & 0x00ff) {
|
||||
return place(move & 0x00ff);
|
||||
}
|
||||
else {
|
||||
else if (move & 0x1f00) {
|
||||
if (choose(move >> 8))
|
||||
return place(move & 0x00ff);
|
||||
}
|
||||
else {
|
||||
return place(move & 0x00ff);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
// 获取当前规则
|
||||
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)
|
||||
bool getPieceCP(const Players &player, const int &number, int &c, int &p);
|
||||
// 获取当前棋子
|
||||
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的用时
|
||||
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);
|
||||
// 获取当前招法
|
||||
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; }
|
||||
|
||||
// 玩家1剩余未放置子数
|
||||
int getPlayer1_InHand() { return data.player1_InHand; }
|
||||
int getPlayer1_InHand() const { return data.player1_InHand; }
|
||||
// 玩家2剩余未放置子数
|
||||
int getPlayer2_InHand() { return data.player2_InHand; }
|
||||
int getPlayer2_InHand() const { return data.player2_InHand; }
|
||||
// 玩家1盘面剩余子数
|
||||
int getPlayer1_Remain() { return data.player1_Remain; }
|
||||
int getPlayer1_Remain() const { return data.player1_Remain; }
|
||||
// 玩家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();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "ninechessai_ab.h"
|
||||
#include <cmath>
|
||||
#include <time.h>
|
||||
#include <qdebug.h>
|
||||
|
||||
NineChessAi_ab::NineChessAi_ab():
|
||||
rootNode(nullptr),
|
||||
|
@ -125,7 +126,10 @@ void NineChessAi_ab::sortChildren(Node *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)
|
||||
|
@ -157,21 +161,21 @@ void NineChessAi_ab::setChess(const NineChess &chess)
|
|||
{
|
||||
// 对于0、2、4、6位(偶数位)
|
||||
if (!(j & 1)) {
|
||||
boardScore[1 * NineChess::SEAT + j] = 80;
|
||||
boardScore[1 * NineChess::SEAT + j] = 90;
|
||||
boardScore[2 * NineChess::SEAT + j] = 100;
|
||||
boardScore[3 * NineChess::SEAT + j] = 80;
|
||||
boardScore[3 * NineChess::SEAT + j] = 90;
|
||||
}
|
||||
// 对于有斜线情况下的1、3、5、7位(奇数位)
|
||||
else if(chessTemp.rule.hasObliqueLine) {
|
||||
boardScore[1 * NineChess::SEAT + j] = 70;
|
||||
boardScore[2 * NineChess::SEAT + j] = 90;
|
||||
boardScore[3 * NineChess::SEAT + j] = 70;
|
||||
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] = 60;
|
||||
boardScore[2 * NineChess::SEAT + j] = 80;
|
||||
boardScore[3 * NineChess::SEAT + j] = 60;
|
||||
boardScore[1 * NineChess::SEAT + j] = 80;
|
||||
boardScore[2 * NineChess::SEAT + j] = 85;
|
||||
boardScore[3 * NineChess::SEAT + j] = 80;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -203,9 +207,9 @@ int NineChessAi_ab::evaluate(Node *node)
|
|||
case NineChess::ACTION_CHOOSE:
|
||||
case NineChess::ACTION_PLACE:
|
||||
break;
|
||||
// 如果形成去子状态,每有一个可去的子,算500分
|
||||
// 如果形成去子状态,每有一个可去的子,算1000分
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
|
@ -253,7 +257,8 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
|
|||
if (chessTemp.whosTurn() == NineChess::PLAYER1) {
|
||||
for (auto child : node->children) {
|
||||
dataStack.push(chessTemp.data);
|
||||
chessTemp.command(child->move);
|
||||
if(!chessTemp.command(child->move))
|
||||
qDebug() << child->move;
|
||||
value = alphaBetaPruning(depth - 1, alpha, beta, child);
|
||||
chessTemp.data = dataStack.top();
|
||||
dataStack.pop();
|
||||
|
@ -262,6 +267,7 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
|
|||
alpha = value;
|
||||
// 剪枝返回
|
||||
if (alpha >= beta) {
|
||||
node->value = alpha;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
@ -272,7 +278,8 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
|
|||
else {
|
||||
for (auto child : node->children) {
|
||||
dataStack.push(chessTemp.data);
|
||||
chessTemp.command(child->move);
|
||||
if(!chessTemp.command(child->move))
|
||||
qDebug() << child->move;
|
||||
value = alphaBetaPruning(depth - 1, alpha, beta, child);
|
||||
chessTemp.data = dataStack.top();
|
||||
dataStack.pop();
|
||||
|
@ -281,6 +288,7 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
|
|||
beta = value;
|
||||
// 剪枝返回
|
||||
if (alpha >= beta) {
|
||||
node->value = beta;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ NineChessWindow::NineChessWindow(QWidget *parent)
|
|||
: QMainWindow(parent),
|
||||
scene(nullptr),
|
||||
game(nullptr),
|
||||
ruleNo(0)
|
||||
ruleNo(-1)
|
||||
{
|
||||
ui.setupUi(this);
|
||||
//去掉标题栏
|
||||
|
@ -181,7 +181,6 @@ void NineChessWindow::initialize()
|
|||
|
||||
// 默认第2号规则
|
||||
ruleNo = 2;
|
||||
// 设置选中当前规则的菜单项
|
||||
ruleActionList.at(ruleNo)->setChecked(true);
|
||||
// 重置游戏规则
|
||||
game->setRule(ruleNo);
|
||||
|
@ -232,6 +231,83 @@ void NineChessWindow::ruleInfo()
|
|||
// .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()
|
||||
{
|
||||
// 取消其它规则的选择
|
||||
|
@ -242,9 +318,14 @@ void NineChessWindow::actionRules_triggered()
|
|||
action->setChecked(true);
|
||||
ruleNo = action->data().toInt();
|
||||
|
||||
// 如果游戏规则没变化,则返回
|
||||
if (ruleNo == game->getRuleNo())
|
||||
return;
|
||||
|
||||
// 取消AI设定
|
||||
ui.actionEngine1_T->setChecked(false);
|
||||
ui.actionEngine2_R->setChecked(false);
|
||||
|
||||
// 重置游戏规则
|
||||
game->setRule(ruleNo);
|
||||
// 更新规则显示
|
||||
|
@ -255,6 +336,10 @@ void NineChessWindow::on_actionNew_N_triggered()
|
|||
{
|
||||
if (file.isOpen())
|
||||
file.close();
|
||||
// 取消AI设定
|
||||
ui.actionEngine1_T->setChecked(false);
|
||||
ui.actionEngine2_R->setChecked(false);
|
||||
// 重置游戏规则
|
||||
game->gameReset();
|
||||
}
|
||||
|
||||
|
@ -280,7 +365,10 @@ void NineChessWindow::on_actionOpen_O_triggered()
|
|||
bool isok = file.open(QFileDevice::ReadOnly | QFileDevice::Text);
|
||||
if (isok)
|
||||
{
|
||||
//读文件
|
||||
// 取消AI设定
|
||||
ui.actionEngine1_T->setChecked(false);
|
||||
ui.actionEngine2_R->setChecked(false);
|
||||
// 读文件
|
||||
QTextStream textStream(&file);
|
||||
QString cmd;
|
||||
cmd = textStream.readLine();
|
||||
|
@ -520,84 +608,6 @@ void NineChessWindow::on_actionAutoRun_A_toggled(bool arg1)
|
|||
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()
|
||||
{
|
||||
ui.actionLocal_L->setChecked(true);
|
||||
|
|
Loading…
Reference in New Issue