修改了一些bug,但AI仍然有些蠢
This commit is contained in:
parent
24d897eb69
commit
76da5d3527
|
@ -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号线程只管玩家1,2号线程只管玩家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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
// 线程等待标识,这里没用到,留着以后扩展用
|
// 线程等待标识,这里没用到,留着以后扩展用
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue