AI: 添加移动方向的enum以及其他一些重构

This commit is contained in:
CalciteM 2019-06-29 19:08:46 +08:00
parent 81ceed4271
commit 4aacd59e08
3 changed files with 41 additions and 23 deletions

View File

@ -112,7 +112,7 @@ const int NineChess::onBoard[(N_RINGS + 2) * N_SEATS] = {
};
// 招法表
int NineChess::moveTable[(N_RINGS + 2) * N_SEATS][4] = { 0 };
int NineChess::moveTable[(N_RINGS + 2) * N_SEATS][N_MOVE_DIRECTIONS] = { 0 };
// 成三表
int NineChess::millTable[(N_RINGS + 2) * N_SEATS][N_DIRECTIONS][N_RINGS - 1] = { 0 };
@ -194,21 +194,21 @@ void NineChess::createMoveTable()
for (int r = 1; r <= N_RINGS; r++) {
for (int s = 0; s < N_SEATS; s++) {
// 顺时针走一步的位置
moveTable[r * N_SEATS + s][0] = r * N_SEATS + (s + 1) % N_SEATS;
moveTable[r * N_SEATS + s][MOVE_DIRECTION_CLOCKWISE] = r * N_SEATS + (s + 1) % N_SEATS;
// 逆时针走一步的位置
moveTable[r * N_SEATS + s][1] = r * N_SEATS + (s + N_SEATS - 1) % N_SEATS;
moveTable[r * N_SEATS + s][MOVE_DIRECTION_ANTICLOCKWISE] = r * N_SEATS + (s + N_SEATS - 1) % N_SEATS;
// 如果是 0、2、4、6位偶数位或是有斜线
if (!(s & 1) || this->currentRule.hasObliqueLines) {
if (r > 1) {
// 向内走一步的位置
moveTable[r * N_SEATS + s][2] = (r - 1) * N_SEATS + s;
moveTable[r * N_SEATS + s][MOVE_DIRECTION_INWARD] = (r - 1) * N_SEATS + s;
}
if (r < N_RINGS) {
// 向外走一步的位置
moveTable[r * N_SEATS + s][3] = (r + 1) * N_SEATS + s;
moveTable[r * N_SEATS + s][MOVE_DIRECTION_OUTWARD] = (r + 1) * N_SEATS + s;
}
}
#if 0

View File

@ -33,9 +33,20 @@ public:
// 8位禁止修改
static const int N_SEATS = 8;
// 横直斜2个方向,禁止修改!
// 横直斜3个方向,禁止修改!
static const int N_DIRECTIONS = 3;
// 移动方向包括顺时针、逆时针、向内、向外4个方向
enum MoveDirection
{
MOVE_DIRECTION_CLOCKWISE = 0, // 顺时针
MOVE_DIRECTION_ANTICLOCKWISE = 1, // 逆时针
MOVE_DIRECTION_INWARD = 2, // 向内
MOVE_DIRECTION_OUTWARD = 3, // 向外
MOVE_DIRECTION_FLY = 4, // 飞子
N_MOVE_DIRECTIONS = 4 // 移动方向数
};
// 遍历棋盘点所用的起始位置,即 [8, 32)
static const int POS_BEGIN = N_SEATS;
static const int POS_END = ((N_RINGS + 1) * N_SEATS);
@ -196,7 +207,7 @@ private:
// 招法表每个位置有最多4种走法顺时针、逆时针、向内、向外
// 这个表跟规则有关,一旦规则改变需要重新修改
static int moveTable[(N_RINGS + 2) * N_SEATS][4];
static int moveTable[(N_RINGS + 2) * N_SEATS][N_MOVE_DIRECTIONS];
// 成三表,表示棋盘上各个位置有成三关系的对应位置表
// 这个表跟规则有关,一旦规则改变需要重新修改

View File

@ -81,6 +81,7 @@ void NineChessAi_ab::buildChildren(Node *node)
// 列出所有合法的下一招
switch (chessTemp.context.action) {
// 对于选子和落子动作
case NineChess::ACTION_CHOOSE:
case NineChess::ACTION_PLACE:
// 对于摆子阶段
@ -111,37 +112,43 @@ 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))) {
for (int j = 0; j < 4; j++) {
newPos = chessTemp.moveTable[oldPos][j];
// 对于棋盘上还有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;
addNode(node, 0, move);
}
}
} else {
for (int j = NineChess::POS_BEGIN; j < NineChess::POS_END; j++) {
if (!chessTemp.board_[j]) {
addNode(node, 0, (oldPos << 8) + j);
// 对于棋盘上还有不到3个字但允许飞子的情况不要求在招法表中是空位就行
for (newPos = NineChess::POS_BEGIN; newPos < NineChess::POS_END; newPos++) {
if (!chessTemp.board_[newPos]) {
int move = (oldPos << 8) + newPos;
addNode(node, 0, move);
}
}
}
}
}
break;
case NineChess::ACTION_CAPTURE:
// 全成三的情况
// 对于吃子动作
case NineChess::ACTION_CAPTURE:
if (chessTemp.isAllInMills(opponent)) {
for (int i = NineChess::POS_BEGIN; i < NineChess::POS_END; i++) {
if (chessTemp.board_[i] & opponent) {
addNode(node, 0, -i);
// 全成三的情况
for (int pos = NineChess::POS_BEGIN; pos < NineChess::POS_END; pos++) {
if (chessTemp.board_[pos] & opponent) {
addNode(node, 0, -pos);
}
}
} else if (!chessTemp.isAllInMills(opponent)) {
for (int i = NineChess::POS_BEGIN; i < NineChess::POS_END; i++) {
if (chessTemp.board_[i] & opponent) {
if (!chessTemp.isInMills(i)) {
addNode(node, 0, -i);
} else {
// 不是全成三的情况
for (int pos = NineChess::POS_BEGIN; pos < NineChess::POS_END; pos++) {
if (chessTemp.board_[pos] & opponent) {
if (!chessTemp.isInMills(pos)) {
addNode(node, 0, -pos);
}
}
}