diff --git a/NineChess/src/aithread.cpp b/NineChess/src/aithread.cpp index 20dfebcf..207e527a 100644 --- a/NineChess/src/aithread.cpp +++ b/NineChess/src/aithread.cpp @@ -34,15 +34,14 @@ void AiThread::run() mutex.unlock(); ai_ab.setChess(*chess); - ai_ab.alphaBetaPruning(1); + ai_ab.alphaBetaPruning(5); const char * str = ai_ab.bestMove(); qDebug() << str; - emit command(str); + if (strcmp(str, "error!")) + emit command(str); // 测试用 - qDebug() << "thread running " << iTemp << "ms"; - msleep(250); - iTemp += 250; + qDebug() << "thread running " << iTemp++ << "times"; } } @@ -67,10 +66,10 @@ void AiThread::stop() return; mutex.lock(); + requestInterruption(); if (waiting_) { waiting_ = false; pauseCondition.wakeAll(); } - requestInterruption(); mutex.unlock(); } diff --git a/NineChess/src/gamecontroller.cpp b/NineChess/src/gamecontroller.cpp index 2c4a45c8..a686e169 100644 --- a/NineChess/src/gamecontroller.cpp +++ b/NineChess/src/gamecontroller.cpp @@ -92,6 +92,14 @@ void GameController::gameReset() chess.reset(); chessTemp = chess; + // 停掉线程 + ai1.stop(); + ai1.quit(); + ai1.wait(); + ai2.stop(); + ai2.quit(); + ai2.wait(); + // 清除棋子 qDeleteAll(pieceList); pieceList.clear(); @@ -210,7 +218,10 @@ void GameController::setEngine1(bool arg) if (arg) { qDebug() << "Player1 is computer."; ai1.setAi(chess); - ai1.start(); + if (ai1.isRunning()) + ai1.resume(); + else + ai1.start(); } else { qDebug() << "Player1 is not computer."; @@ -221,8 +232,18 @@ void GameController::setEngine1(bool arg) void GameController::setEngine2(bool arg) { isEngine2 = arg; - qDebug() << "size of NineChess::ChessData" << sizeof(NineChess::ChessData); - qDebug() << "size of NineChess: " << sizeof(chess); + if (arg) { + qDebug() << "Player2 is computer."; + ai2.setAi(chess); + if (ai2.isRunning()) + ai2.resume(); + else + ai2.start(); + } + else { + qDebug() << "Player2 is not computer."; + ai2.stop(); + } } void GameController::setAnimation(bool arg) @@ -708,18 +729,20 @@ bool GameController::updateScence(NineChess &chess) // 如果还未决出胜负 if (chess.whoWin() == NineChess::NOBODY) { if (chess.whosTurn() == NineChess::PLAYER1) { - ai1.resume(); + if(isEngine1) + ai1.resume(); ai2.pause(); } else { + if(isEngine2) + ai2.resume(); ai1.pause(); - ai2.resume(); } } // 如果已经决出胜负 else { - ai1.pause(); - ai1.pause(); + ai1.stop(); + ai2.stop(); } } diff --git a/NineChess/src/ninechess.cpp b/NineChess/src/ninechess.cpp index 24133835..32645eab 100644 --- a/NineChess/src/ninechess.cpp +++ b/NineChess/src/ninechess.cpp @@ -633,7 +633,7 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/) return false; } // 移子 - move_ = currentPos << 8 + pos; + move_ = (currentPos << 8) + pos; player_ms = update(time_p); sprintf(cmdline, "(%1u,%1u)->(%1u,%1u) %02u:%02u.%03u", currentPos / SEAT, currentPos % SEAT + 1, c, p, player_ms / 60000, player_ms / 1000, player_ms % 1000); @@ -910,7 +910,7 @@ bool NineChess::place(int pos) return false; } // 移子 - move_ = currentPos << 8 + pos; + move_ = (currentPos << 8) + pos; board[pos] = board[currentPos]; board[currentPos] = '\x00'; currentPos = pos; diff --git a/NineChess/src/ninechess.h b/NineChess/src/ninechess.h index 42886a99..74488dea 100644 --- a/NineChess/src/ninechess.h +++ b/NineChess/src/ninechess.h @@ -111,15 +111,15 @@ public: enum NineChess::Actions action; // 玩家1剩余未放置子数 - int8_t player1_InHand; + char player1_InHand; // 玩家2剩余未放置子数 - int8_t player2_InHand; + char player2_InHand; // 玩家1盘面剩余子数 - int8_t player1_Remain; + char player1_Remain; // 玩家1盘面剩余子数 - int8_t player2_Remain; + char player2_Remain; // 尚待去除的子数 - int8_t num_NeedRemove; + char num_NeedRemove; /* 本打算用如下的结构体来表示“三连” struct Mill { diff --git a/NineChess/src/ninechessai_ab.cpp b/NineChess/src/ninechessai_ab.cpp index ed03e137..a7c173d1 100644 --- a/NineChess/src/ninechessai_ab.cpp +++ b/NineChess/src/ninechessai_ab.cpp @@ -22,11 +22,17 @@ depth(3) // 默认3层深度 NineChessAi_ab::~NineChessAi_ab() { deleteTree(rootNode); + rootNode = nullptr; } void NineChessAi_ab::buildChildren(Node *node) { - char opponent; + // 如果有子节点,则返回,避免重复建立 + if (node->children.size()) + return; + + // 临时变量 + char opponent = chessTemp.data.turn == NineChess::PLAYER1 ? 0x20 : 0x10; // 列出所有合法的下一招 switch (chessTemp.data.action) { @@ -49,28 +55,29 @@ void NineChessAi_ab::buildChildren(Node *node) char newPos; for (int i = NineChess::SEAT; i < (NineChess::RING + 1)*NineChess::SEAT; i++) { if (!chessTemp.choose(i)) - break; + continue; if ((chessTemp.data.turn == NineChess::PLAYER1 && (chessTemp.data.player1_Remain > chessTemp.rule.numAtLest || !chessTemp.rule.canFly)) || (chessTemp.data.turn == NineChess::PLAYER2 && (chessTemp.data.player2_Remain > chessTemp.rule.numAtLest || !chessTemp.rule.canFly))) { for (int j = 0; j < 4; j++) { - if (newPos == chessTemp.moveTable[i][j]) { + newPos = chessTemp.moveTable[i][j]; + if (newPos && !chessTemp.board[newPos]) { Node * newNode = new Node; newNode->parent = node; newNode->value = 0; - newNode->move = i << 8 + newPos; + newNode->move = (i << 8) + newPos; node->children.push_back(newNode); } } } else { for (int j = NineChess::SEAT; j < (NineChess::RING + 1)*NineChess::SEAT; j++) { - if (newPos & chessTemp.board[j]) - break; - Node * newNode = new Node; - newNode->parent = node; - newNode->value = 0; - newNode->move = i << 8 + j; - node->children.push_back(newNode); + if (!chessTemp.board[j]) { + Node * newNode = new Node; + newNode->parent = node; + newNode->value = 0; + newNode->move = (i << 8) + j; + node->children.push_back(newNode); + } } } } @@ -78,7 +85,6 @@ void NineChessAi_ab::buildChildren(Node *node) break; case NineChess::ACTION_CAPTURE: - opponent = chessTemp.data.turn == NineChess::PLAYER1 ? 0x20 : 0x10; // 全成三的情况 if (chessTemp.isAllInMills(opponent)) { for (int i = NineChess::SEAT; i < (NineChess::RING + 1)*NineChess::SEAT; i++) { @@ -94,13 +100,13 @@ void NineChessAi_ab::buildChildren(Node *node) else { for (int i = NineChess::SEAT; i < (NineChess::RING + 1)*NineChess::SEAT; i++) { if (chessTemp.board[i] & opponent) { - if (chessTemp.isInMills(i)) - break; - Node * newNode = new Node; - newNode->parent = node; - newNode->value = 0; - newNode->move = -i; - node->children.push_back(newNode); + if (!chessTemp.isInMills(i)) { + Node * newNode = new Node; + newNode->parent = node; + newNode->value = 0; + newNode->move = -i; + node->children.push_back(newNode); + } } } } @@ -139,6 +145,12 @@ void NineChessAi_ab::setChess(const NineChess &chess) this->chess = chess; chessTemp = chess; chessData = &(chessTemp.data); + deleteTree(rootNode); + rootNode = new Node; + rootNode->value = 0; + rootNode->move = 0; + rootNode->parent = nullptr; + requiredQuit = false; // 生成棋子价值表 for (int j = 0; j < NineChess::SEAT; j++) @@ -191,9 +203,9 @@ int NineChessAi_ab::evaluate(Node *node) case NineChess::ACTION_CHOOSE: case NineChess::ACTION_PLACE: break; - // 如果形成去子状态,每有一个可去的子,算100分 + // 如果形成去子状态,每有一个可去的子,算500分 case NineChess::ACTION_CAPTURE: - value += (chessData->turn == NineChess::PLAYER1) ? chessData->num_NeedRemove * 100 : -chessData->num_NeedRemove * 100; + value += (chessData->turn == NineChess::PLAYER1) ? chessData->num_NeedRemove * 500 : -chessData->num_NeedRemove * 500; break; default: break; @@ -240,11 +252,11 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node) // 对先手,搜索Max if (chessTemp.whosTurn() == NineChess::PLAYER1) { for (auto child : node->children) { - hashTable.push_back({chessTemp.data, 0, depth}); + dataStack.push(chessTemp.data); chessTemp.command(child->move); value = alphaBetaPruning(depth - 1, alpha, beta, child); - chessTemp.data = hashTable.back().data; - hashTable.pop_back(); + chessTemp.data = dataStack.top(); + dataStack.pop(); // 取最大值 if (value > alpha) alpha = value; @@ -259,11 +271,11 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node) // 对后手,搜索Min else { for (auto child : node->children) { - hashTable.push_back({ chessTemp.data, 0, depth }); + dataStack.push(chessTemp.data); chessTemp.command(child->move); value = alphaBetaPruning(depth - 1, alpha, beta, child); - chessTemp.data = hashTable.back().data; - hashTable.pop_back(); + chessTemp.data = dataStack.top(); + dataStack.pop(); // 取最小值 if (value < beta) beta = value; @@ -293,7 +305,7 @@ const char *NineChessAi_ab::bestMove() break; } srand((unsigned)time(0)); - int i = rand() % 12; + int i = rand() % n; return move2string(moves[i]); } @@ -304,16 +316,16 @@ const char *NineChessAi_ab::move2string(int16_t move) chessTemp.pos2cp(-move, c, p); sprintf(cmdline, "-(%1u,%1u)", c, p); } - else if (move & 0x00ff) { - chessTemp.pos2cp(move & 0x00ff, c, p); - sprintf(cmdline, "(%1u,%1u)", c, p); - } - else { + else if (move & 0x7f00) { int c1, p1; chessTemp.pos2cp(move >> 8, c1, p1); chessTemp.pos2cp(move & 0x00ff, c, p); sprintf(cmdline, "(%1u,%1u)->(%1u,%1u)", c1, p1, c, p); } + else { + chessTemp.pos2cp(move & 0x007f, c, p); + sprintf(cmdline, "(%1u,%1u)", c, p); + } return cmdline; } diff --git a/NineChess/src/ninechessai_ab.h b/NineChess/src/ninechessai_ab.h index 4921be08..10d5e037 100644 --- a/NineChess/src/ninechessai_ab.h +++ b/NineChess/src/ninechessai_ab.h @@ -9,6 +9,9 @@ #include "ninechess.h" #include +#include + +using namespace std; // 注意:NineChess类不是线程安全的! // 所以不能在ai类中修改NineChess类的静态成员变量,切记! @@ -79,6 +82,8 @@ private: // 根节点 Node * rootNode; + // 局面数据栈 + stack dataStack; // 局面数据哈希表 list hashTable; // 哈希表最大大小