From 22d450a193f51d3f05ffdb8a34a9ee08d8494b11 Mon Sep 17 00:00:00 2001 From: CalciteM Team Date: Sat, 6 Jul 2019 15:32:19 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8B=9B=E6=B3=95=E6=94=B9=E5=90=8D=E4=B8=BA?= =?UTF-8?q?=E7=9D=80=E6=B3=95=E5=B9=B6=E6=B7=BB=E5=8A=A0=E6=9B=B4=E5=A4=9A?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NineChess/ninechesswindow.ui | 2 +- NineChess/src/aithread.h | 2 +- NineChess/src/gamecontroller.cpp | 2 +- NineChess/src/ninechess.cpp | 8 +++---- NineChess/src/ninechess.h | 12 +++++------ NineChess/src/ninechessai_ab.cpp | 36 ++++++++++++++++++------------- NineChess/src/ninechessai_ab.h | 4 ++-- NineChess/src/ninechesswindow.cpp | 2 +- 8 files changed, 37 insertions(+), 31 deletions(-) diff --git a/NineChess/ninechesswindow.ui b/NineChess/ninechesswindow.ui index 1163e7f1..1136b50f 100644 --- a/NineChess/ninechesswindow.ui +++ b/NineChess/ninechesswindow.ui @@ -85,7 +85,7 @@ - 招法(&M) + 着法(&M) diff --git a/NineChess/src/aithread.h b/NineChess/src/aithread.h index 53b71b60..2ce8aa8c 100644 --- a/NineChess/src/aithread.h +++ b/NineChess/src/aithread.h @@ -17,7 +17,7 @@ public: ~AiThread(); signals: - // 招法信号 + // 着法信号 void command(const QString &cmdline, bool update = true); // 开始计算的信号 diff --git a/NineChess/src/gamecontroller.cpp b/NineChess/src/gamecontroller.cpp index bac424d5..121fb66b 100644 --- a/NineChess/src/gamecontroller.cpp +++ b/NineChess/src/gamecontroller.cpp @@ -44,7 +44,7 @@ GameController::GameController(GameScene & scene, QObject * parent) : gameReset(); - // 关联AI和控制器的招法命令行 + // 关联AI和控制器的着法命令行 connect(&ai1, SIGNAL(command(const QString &, bool)), this, SLOT(command(const QString &, bool))); connect(&ai2, SIGNAL(command(const QString &, bool)), diff --git a/NineChess/src/ninechess.cpp b/NineChess/src/ninechess.cpp index 0e47e59c..158d4a9b 100644 --- a/NineChess/src/ninechess.cpp +++ b/NineChess/src/ninechess.cpp @@ -111,7 +111,7 @@ const int NineChess::onBoard[(N_RINGS + 2) * N_SEATS] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -// 招法表 +// 着法表 int NineChess::moveTable[(N_RINGS + 2) * N_SEATS][N_MOVE_DIRECTIONS] = { 0 }; // 成三表 @@ -398,7 +398,7 @@ bool NineChess::setContext(const struct Rule *rule, int maxStepsLedToDraw, int m // 胜负标识 winner = NOBODY; - // 生成招法表 + // 生成着法表 createMoveTable(); // 生成成三表 @@ -713,7 +713,7 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/) break; } - // 不在招法表中 + // 不在着法表中 if (i == 4) return false; } @@ -1027,7 +1027,7 @@ bool NineChess::place(int pos) if (pos == moveTable[currentPos][i]) break; } - // 不在招法表中 + // 不在着法表中 if (i == 4) return false; } diff --git a/NineChess/src/ninechess.h b/NineChess/src/ninechess.h index 1af18430..28d1883e 100644 --- a/NineChess/src/ninechess.h +++ b/NineChess/src/ninechess.h @@ -205,7 +205,7 @@ private: // 空棋盘点位,用于判断一个棋子位置是否在棋盘上 static const int onBoard[(N_RINGS + 2) * N_SEATS]; - // 招法表,每个位置有最多4种走法:顺时针、逆时针、向内、向外 + // 着法表,每个位置有最多4种走法:顺时针、逆时针、向内、向外 // 这个表跟规则有关,一旦规则改变需要重新修改 static int moveTable[(N_RINGS + 2) * N_SEATS][N_MOVE_DIRECTIONS]; @@ -213,7 +213,7 @@ private: // 这个表跟规则有关,一旦规则改变需要重新修改 static int millTable[(N_RINGS + 2) * N_SEATS][3][2]; - // 生成招法表 + // 生成着法表 void createMoveTable(); // 生成成三表 @@ -317,7 +317,7 @@ public: // 获取位置点棋子的归属人 enum Player getWhosPiece(int c, int p); - // 获取当前招法 + // 获取当前着法 const char *getCmdLine() const { return cmdline; @@ -481,7 +481,7 @@ private: // 玩家2用时(毫秒) long elapsedMS_2; - /* 当前招法,AI会用到,如下表示 + /* 当前着法,AI会用到,如下表示 0x 00 00 pos1 pos2 开局落子:0x00??,??为棋盘上的位置 @@ -503,8 +503,8 @@ private: */ int32_t move_; - // 招法命令行用于棋谱的显示和解析 - // 当前招法的命令行指令,即一招棋谱 + // 着法命令行用于棋谱的显示和解析 + // 当前着法的命令行指令,即一招棋谱 char cmdline[32]; // 棋谱 diff --git a/NineChess/src/ninechessai_ab.cpp b/NineChess/src/ninechessai_ab.cpp index 94629ef6..2c3824e6 100644 --- a/NineChess/src/ninechessai_ab.cpp +++ b/NineChess/src/ninechessai_ab.cpp @@ -137,9 +137,9 @@ void NineChessAi_ab::buildChildren(Node *node) (chessTemp.context.nPiecesOnBoard_1 > chessTemp.currentRule.nPiecesAtLeast || !chessTemp.currentRule.allowFlyWhenRemainThreePieces)) || (chessTemp.context.turn == NineChess::PLAYER2 && (chessTemp.context.nPiecesOnBoard_2 > chessTemp.currentRule.nPiecesAtLeast || !chessTemp.currentRule.allowFlyWhenRemainThreePieces))) { - // 对于棋盘上还有3个子以上,或不允许飞子的情况,要求必须在招法表中 + // 对于棋盘上还有3个子以上,或不允许飞子的情况,要求必须在着法表中 for (int moveDirection = NineChess::MOVE_DIRECTION_CLOCKWISE; moveDirection <= NineChess::MOVE_DIRECTION_OUTWARD; moveDirection++) { - // 对于原有位置,遍历四个方向的招法,如果棋盘上为空位就加到结点列表中 + // 对于原有位置,遍历四个方向的着法,如果棋盘上为空位就加到结点列表中 newPos = chessTemp.moveTable[oldPos][moveDirection]; if (newPos && !chessTemp.board_[newPos]) { int move = (oldPos << 8) + newPos; @@ -147,7 +147,7 @@ void NineChessAi_ab::buildChildren(Node *node) } } } else { - // 对于棋盘上还有不到3个字,但允许飞子的情况,不要求在招法表中,是空位就行 + // 对于棋盘上还有不到3个字,但允许飞子的情况,不要求在着法表中,是空位就行 for (newPos = NineChess::POS_BEGIN; newPos < NineChess::POS_END; newPos++) { if (!chessTemp.board_[newPos]) { int move = (oldPos << 8) + newPos; @@ -488,7 +488,7 @@ int NineChessAi_ab::alphaBetaPruning(int depth) qDebug() << "IDS Time: " << time1.elapsed() / 1000.0 << "s"; #endif /* IDS_SUPPORT */ - value = alphaBetaPruning(d, -INF_VALUE, INF_VALUE, rootNode); + value = alphaBetaPruning(d, -INF_VALUE /* alpha */, INF_VALUE /* beta */, rootNode); qDebug() << "Total Time: " << time1.elapsed() / 1000.0 << "s\n"; @@ -582,7 +582,7 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node) hashMapMutex.unlock(); #endif /* HASH_MAP_ENABLE */ - // 生成子节点树 + // 生成子节点树,即生成每个合理的着法 buildChildren(node); // 排序子节点树 @@ -593,10 +593,10 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node) minMax = chessTemp.whosTurn() == NineChess::PLAYER1 ? -INF_VALUE : INF_VALUE; for (auto child : node->children) { - // 上下文入栈保存 + // 上下文入栈保存,以便后续撤销着法 contextStack.push(chessTemp.context); - // 替换为演算用的招法 + // 执行着法 chessTemp.command(child->move); #ifdef DEAL_WITH_HORIZON_EFFECT @@ -611,31 +611,37 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node) // 递归 Alpha-Beta 剪枝 value = alphaBetaPruning(depth - 1 + epsilon, alpha, beta, child); - // 上下文弹出栈 + // 上下文弹出栈,撤销着法 chessTemp.context = contextStack.top(); contextStack.pop(); if (chessTemp.whosTurn() == NineChess::PLAYER1) { - // 为走棋一方的层 + // 为走棋一方的层, 局面对走棋的一方来说是以 α 为评价 // 取最大值 minMax = std::max(value, minMax); - // alpha 为走棋一方搜索到的最好值,任何比它小的值对当前结点的走棋方都没有意义 + // α 为走棋一方搜索到的最好值,任何比它小的值对当前结点的走棋方都没有意义 + // 如果某个着法的结果小于或等于 α,那么它就是很差的着法,因此可以抛弃 alpha = std::max(value, alpha); } else { - // 为走棋方的对手一方的层 + // 为走棋方的对手一方的层, 局面对对手一方来说是以 β 为评价 // 取最小值 minMax = std::min(value, minMax); - // beta 表示对手目前的劣势,这是对手所能承受的最坏结果 - // beta 值越大,表示对手劣势越明显 - // 如果当前结点返回 beta 或比 beta 更好的值,作为父结点的对方就绝对不会选择这种策略 + // β 表示对手目前的劣势,这是对手所能承受的最坏结果 + // β 值越大,表示对手劣势越明显 + // 在对手看来,他总是会找到一个对策不比 β 更坏的 + // 如果当前结点返回 β 或比 β 更好的值,作为父结点的对方就绝对不会选择这种策略, + // 如果搜索过程中返回 β 或比 β 更好的值,那就够好的了,走棋的一方就没有机会使用这种策略了。 + // 如果某个着法的结果大于或等于 β,那么整个结点就作废了,因为对手不希望走到这个局面,而它有别的着法可以避免到达这个局面。 + // 因此如果我们找到的评价大于或等于β,就证明了这个结点是不会发生的,因此剩下的合理着法没有必要再搜索。 beta = std::min(value, beta); } - // 剪枝返回 + // 如果某个着法的结果大于 α 但小于β,那么这个着法就是走棋一方可以考虑走的 + // 否则剪枝返回 if (alpha >= beta) break; } diff --git a/NineChess/src/ninechessai_ab.h b/NineChess/src/ninechessai_ab.h index 080940e4..16bcc9dd 100644 --- a/NineChess/src/ninechessai_ab.h +++ b/NineChess/src/ninechessai_ab.h @@ -36,7 +36,7 @@ public: // 定义一个节点结构体 struct Node { - int move; // 招法的命令行指令,图上标示为节点前的连线 + int move; // 着法的命令行指令,图上标示为节点前的连线 int value; // 节点的值 list children; // 子节点列表 struct Node* parent; // 父节点 @@ -107,7 +107,7 @@ protected: // Alpha-Beta剪枝算法 int alphaBetaPruning(int depth, int alpha, int beta, Node *node); - // 返回招法的命令行 + // 返回着法的命令行 const char *move2string(int move); // 篡改深度 diff --git a/NineChess/src/ninechesswindow.cpp b/NineChess/src/ninechesswindow.cpp index c5e835df..4ef9cbf9 100644 --- a/NineChess/src/ninechesswindow.cpp +++ b/NineChess/src/ninechesswindow.cpp @@ -251,7 +251,7 @@ void NineChessWindow::initialize() connect(ui.actionEnd_E, &QAction::triggered, this, &NineChessWindow::on_actionRowChange); - // 手动在listView里选择招法后更新的槽 + // 手动在listView里选择着法后更新的槽 connect(ui.listView, &ManualListView::currentChangedSignal, this, &NineChessWindow::on_actionRowChange);