From 82b39b02acbb2cdaa0ad5da2f6b55db38cf82211 Mon Sep 17 00:00:00 2001 From: liuweilhy Date: Tue, 11 Dec 2018 23:28:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=A3=8B=E5=B1=80=E7=9A=84?= =?UTF-8?q?=E9=95=9C=E5=83=8F=E3=80=81=E7=BF=BB=E8=BD=AC=E3=80=81=E6=97=8B?= =?UTF-8?q?=E8=BD=AC=E7=AE=97=E6=B3=95=EF=BC=8C=E6=9C=AA=E5=AE=8C=E6=88=90?= =?UTF-8?q?=EF=BC=8C=E4=B8=B4=E6=97=B6=E4=B8=8A=E4=BC=A0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NineChess/src/gamecontroller.cpp | 36 +++++ NineChess/src/gamecontroller.h | 9 ++ NineChess/src/ninechess.cpp | 260 ++++++++++++++++++++++++++++++ NineChess/src/ninechess.h | 20 ++- NineChess/src/ninechessai_ab.cpp | 5 +- NineChess/src/ninechesswindow.cpp | 27 ++-- 6 files changed, 335 insertions(+), 22 deletions(-) diff --git a/NineChess/src/gamecontroller.cpp b/NineChess/src/gamecontroller.cpp index fe6de332..b2c5c393 100644 --- a/NineChess/src/gamecontroller.cpp +++ b/NineChess/src/gamecontroller.cpp @@ -273,6 +273,42 @@ void GameController::playSound(const QString &soundPath) } } + +// 上下翻转 +void GameController::flip() +{ + chess.mirror(); + chess.rotate(180); + chessTemp = chess; + updateScence(); +} + +// 左右镜像 +void GameController::mirror() +{ + chess.mirror(); + chessTemp = chess; + updateScence(); +} + +// 视图须时针旋转90° +void GameController::turnRight() +{ + chess.rotate(90); + chessTemp = chess; + updateScence(); +} + +// 视图逆时针旋转90° +void GameController::turnLeft() +{ + chess.rotate(270); + chessTemp = chess; + updateScence(); +} + + + //bool GameController::eventFilter(QObject * watched, QEvent * event) //{ // return QObject::eventFilter(watched, event); diff --git a/NineChess/src/gamecontroller.h b/NineChess/src/gamecontroller.h index 09805743..13229c53 100644 --- a/NineChess/src/gamecontroller.h +++ b/NineChess/src/gamecontroller.h @@ -67,6 +67,15 @@ public slots: void setSound(bool arg = true); // 播放声音 void playSound(const QString &soundPath); + // 上下翻转 + void flip(); + // 左右镜像 + void mirror(); + // 视图须时针旋转90° + void turnRight(); + // 视图逆时针旋转90° + void turnLeft(); + // 根据QGraphicsScene的信号和状态来执行选子、落子或去子 bool actionPiece(QPointF p); // 认输 diff --git a/NineChess/src/ninechess.cpp b/NineChess/src/ninechess.cpp index d3782f44..414539e8 100644 --- a/NineChess/src/ninechess.cpp +++ b/NineChess/src/ninechess.cpp @@ -1588,3 +1588,263 @@ void NineChess::getPlayer_TimeMS(int &p1_ms, int &p2_ms) p1_ms = player1_MS; p2_ms = player2_MS; } + +void NineChess::mirror(bool cmdChange /*= true*/) +{ + char ch; + int i, j; + for (i = 1; i <= RING; i++) { + for (j = 1; j < SEAT / 2; j++) { + ch = board[i*SEAT + j]; + board[i*SEAT + j] = board[(i + 1)*SEAT - j]; + board[(i + 1)*SEAT - j] = ch; + } + } + + int16_t p1, p2, p3; + if (move_ < 0) { + i = (-move_) / SEAT; + j = (-move_) % SEAT; + j = (SEAT - j) % SEAT; + move_ = -(i * SEAT + j); + } + else { + p1 = move_ >> 8; + p2 = move_ & 0x00ff; + i = p1 / SEAT; + j = p1 % SEAT; + j = (SEAT - j) % SEAT; + p1 = i * SEAT + j; + i = p2 / SEAT; + j = p2 % SEAT; + j = (SEAT - j) % SEAT; + p2 = i * SEAT + j; + move_ = (p1 << 8) | p2; + } + + i = currentPos / SEAT; + j = currentPos % SEAT; + j = (SEAT - j) % SEAT; + currentPos = i * SEAT + j; + + if (rule.canRepeated) { + for (auto mill = data.millList.begin(); mill != data.millList.end(); mill++) { + p1 = (*mill & 0x000000ff00000000) >> 32; + p2 = (*mill & 0x0000000000ff0000) >> 16; + p2 = (*mill & 0x00000000000000ff); + + i = p1 / SEAT; + j = p1 % SEAT; + j = (SEAT - j) % SEAT; + p1 = i * SEAT + j; + + i = p2 / SEAT; + j = p2 % SEAT; + j = (SEAT - j) % SEAT; + p2 = i * SEAT + j; + + i = p3 / SEAT; + j = p3 % SEAT; + j = (SEAT - j) % SEAT; + p3 = i * SEAT + j; + + *mill &= 0xffffff00ff00ff00; + *mill |= (p1 << 32) | (p2 << 16) | p3; + } + } + + // 命令行解析 + if (cmdChange) { + ; + } +} + +void NineChess::turn(bool cmdChange /*= true*/) +{ + char ch; + int i, j; + for (i = 0; i < SEAT; i++) { + ch = board[SEAT + i]; + board[SEAT + i] = board[SEAT*RING + i]; + board[SEAT*RING + i] = ch; + } + + int16_t p1, p2, p3; + + if (move_ < 0) { + i = (-move_) / SEAT; + j = (-move_) % SEAT; + if (i == 1) + i = RING; + else if (i == RING) + i = 1; + move_ = -(i * SEAT + j); + } + else { + p1 = move_ >> 8; + p2 = move_ & 0x00ff; + i = p1 / SEAT; + j = p1 % SEAT; + if (i == 1) + i = RING; + else if (i == RING) + i = 1; + p1 = i * SEAT + j; + i = p2 / SEAT; + j = p2 % SEAT; + if (i == 1) + i = RING; + else if (i == RING) + i = 1; + p2 = i * SEAT + j; + move_ = (p1 << 8) | p2; + } + + i = currentPos / SEAT; + j = currentPos % SEAT; + if (i == 1) + i = RING; + else if (i == RING) + i = 1; + currentPos = i * SEAT + j; + + if (rule.canRepeated) { + for (auto mill = data.millList.begin(); mill != data.millList.end(); mill++) { + p1 = (*mill & 0x000000ff00000000) >> 32; + p2 = (*mill & 0x0000000000ff0000) >> 16; + p2 = (*mill & 0x00000000000000ff); + + i = p1 / SEAT; + j = p1 % SEAT; + if (i == 1) + i = RING; + else if (i == RING) + i = 1; + p1 = i * SEAT + j; + + i = p2 / SEAT; + j = p2 % SEAT; + if (i == 1) + i = RING; + else if (i == RING) + i = 1; + p2 = i * SEAT + j; + + i = p3 / SEAT; + j = p3 % SEAT; + if (i == 1) + i = RING; + else if (i == RING) + i = 1; + p3 = i * SEAT + j; + + *mill &= 0xffffff00ff00ff00; + *mill |= (p1 << 32) | (p2 << 16) | p3; + } + } + + // 命令行解析 + if (cmdChange) { + ; + } +} + +void NineChess::rotate(int degrees, bool cmdChange /*= true*/) +{ + // 将degrees转化为0~359之间的数 + degrees = degrees % 360; + if (degrees < 0) + degrees += 360; + + if (degrees != 90 || degrees != 180 || degrees != 270) + return; + else + degrees /= 45; + + char ch; + int i, j; + for (i = 0; i < SEAT; i++) { + ch = board[SEAT + i]; + board[SEAT + i] = board[SEAT*RING + i]; + board[SEAT*RING + i] = ch; + } + + int16_t p1, p2, p3; + + if (move_ < 0) { + i = (-move_) / SEAT; + j = (-move_) % SEAT; + if (i == 1) + i = RING; + else if (i == RING) + i = 1; + move_ = -(i * SEAT + j); + } + else { + p1 = move_ >> 8; + p2 = move_ & 0x00ff; + i = p1 / SEAT; + j = p1 % SEAT; + if (i == 1) + i = RING; + else if (i == RING) + i = 1; + p1 = i * SEAT + j; + i = p2 / SEAT; + j = p2 % SEAT; + if (i == 1) + i = RING; + else if (i == RING) + i = 1; + p2 = i * SEAT + j; + move_ = (p1 << 8) | p2; + } + + i = currentPos / SEAT; + j = currentPos % SEAT; + if (i == 1) + i = RING; + else if (i == RING) + i = 1; + currentPos = i * SEAT + j; + + if (rule.canRepeated) { + for (auto mill = data.millList.begin(); mill != data.millList.end(); mill++) { + p1 = (*mill & 0x000000ff00000000) >> 32; + p2 = (*mill & 0x0000000000ff0000) >> 16; + p2 = (*mill & 0x00000000000000ff); + + i = p1 / SEAT; + j = p1 % SEAT; + if (i == 1) + i = RING; + else if (i == RING) + i = 1; + p1 = i * SEAT + j; + + i = p2 / SEAT; + j = p2 % SEAT; + if (i == 1) + i = RING; + else if (i == RING) + i = 1; + p2 = i * SEAT + j; + + i = p3 / SEAT; + j = p3 % SEAT; + if (i == 1) + i = RING; + else if (i == RING) + i = 1; + p3 = i * SEAT + j; + + *mill &= 0xffffff00ff00ff00; + *mill |= (p1 << 32) | (p2 << 16) | p3; + } + } + + // 命令行解析 + if (cmdChange) { + ; + } +} diff --git a/NineChess/src/ninechess.h b/NineChess/src/ninechess.h index e6eb7bd4..538edfb3 100644 --- a/NineChess/src/ninechess.h +++ b/NineChess/src/ninechess.h @@ -89,7 +89,7 @@ public: ACTION_CAPTURE = 0x0400 // 提子 }; - // 棋局结构体,包含当前棋盘数据 + // 棋局结构体,算法相关,包含当前棋盘数据 // 单独分离出来供AI判断局面用,生成置换表时使用 struct ChessData { // 棋局,抽象为一个(5×8)的char数组,上下两行留空 @@ -222,21 +222,23 @@ public: bool reset(); // 游戏开始 bool start(); + // 选子,在第c圈第p个位置,为迎合日常,c和p下标都从1开始 bool choose(int c, int p); // 落子,在第c圈第p个位置,为迎合日常,c和p下标都从1开始 bool place(int c, int p, long time_p = -1); // 去子,在第c圈第p个位置,为迎合日常,c和p下标都从1开始 bool capture(int c, int p, long time_p = -1); - // 下面3个函数没有算法无关判断和无关操作 - bool choose(int pos); - bool place(int pos); - bool capture(int pos); // 认输 bool giveup(Players loser); // 命令行解析函数 - bool command(int16_t move); bool command(const char *cmd); + // 局面左右镜像 + void mirror(bool cmdChange = true); + // 局面内外翻转 + void turn(bool cmdChange = true); + // 局面顺时针旋转 + void rotate(int degrees, bool cmdChange = true); protected: // 判断棋盘pos处的棋子处于几个“三连”中 @@ -266,6 +268,12 @@ protected: // 设置提示 void setTip(); + // 下面几个函数没有算法无关判断和无关操作,节约算法时间 + bool command(int16_t move); + bool choose(int pos); + bool place(int pos); + bool capture(int pos); + private: // 当前使用的规则 struct Rule rule; diff --git a/NineChess/src/ninechessai_ab.cpp b/NineChess/src/ninechessai_ab.cpp index f2d7ec53..5ab957d7 100644 --- a/NineChess/src/ninechessai_ab.cpp +++ b/NineChess/src/ninechessai_ab.cpp @@ -120,9 +120,10 @@ void NineChessAi_ab::buildChildren(Node *node) void NineChessAi_ab::sortChildren(Node *node) { // 这个函数对效率的影响很大,排序好的话,剪枝较早,节省时间,但不能在此函数耗费太多时间 - // 先赋初值,初始值不会影响alpha-beta剪枝 + // 这里我用一个随机排序,使AI不至于每次走招相同 + srand((unsigned)time(0)); for (auto i : node->children) { - i->value = evaluate(node); + i->value = rand(); } // 排序 if(chessTemp.whosTurn() == NineChess::PLAYER1) diff --git a/NineChess/src/ninechesswindow.cpp b/NineChess/src/ninechesswindow.cpp index 7459a7d7..45b60207 100644 --- a/NineChess/src/ninechesswindow.cpp +++ b/NineChess/src/ninechesswindow.cpp @@ -57,20 +57,6 @@ NineChessWindow::NineChessWindow(QWidget *parent) ui.actionInternet_I->setDisabled(true); ui.actionSetting_O->setDisabled(true); - // 关联既有动作信号和主窗口槽 - // 视图上下翻转 - connect(ui.actionFlip_F, &QAction::triggered, - ui.gameView, &GameView::flip); - // 视图左右镜像 - connect(ui.actionMirror_M, &QAction::triggered, - ui.gameView, &GameView::mirror); - // 视图须时针旋转90° - connect(ui.actionTurnRight_R, &QAction::triggered, - ui.gameView, &GameView::turnRight); - // 视图逆时针旋转90° - connect(ui.actionTurnLeftt_L, &QAction::triggered, - ui.gameView, &GameView::turnLeft); - // 初始化游戏规则菜单 ui.menu_R->installEventFilter(this); @@ -167,6 +153,19 @@ void NineChessWindow::initialize() connect(ui.actionAnimation_A, SIGNAL(toggled(bool)), game, SLOT(setAnimation(bool))); + // 视图上下翻转 + connect(ui.actionFlip_F, &QAction::triggered, + game, &GameController::flip); + // 视图左右镜像 + connect(ui.actionMirror_M, &QAction::triggered, + game, &GameController::mirror); + // 视图须时针旋转90° + connect(ui.actionTurnRight_R, &QAction::triggered, + game, &GameController::turnRight); + // 视图逆时针旋转90° + connect(ui.actionTurnLeftt_L, &QAction::triggered, + game, &GameController::turnLeft); + // 关联控制器的信号和主窗口控件的槽 // 更新LCD1,显示玩家1用时 connect(game, SIGNAL(time1Changed(QString)),