From a99577d089b7212e701d45f7d2c1b051428672d9 Mon Sep 17 00:00:00 2001 From: liuweilhy Date: Sun, 2 Dec 2018 01:03:54 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84NineChess=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=EF=BC=8C=E5=81=9A=E4=BA=86=E6=95=B0=E6=8D=AE=E5=88=86=E7=A6=BB?= =?UTF-8?q?=EF=BC=8C=E8=AF=84=E4=BC=B0=E7=94=A8=E7=9A=84=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=A4=A7=E5=B0=8F=E4=BB=8E304=E5=AD=97=E8=8A=82=E5=87=8F?= =?UTF-8?q?=E5=B0=8F=E4=B8=BA88=E5=AD=97=E8=8A=82=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NineChess/ninechess.pro.user | 58 ++- NineChess/ninechess.sln | 6 + NineChess/ninechess.vcxproj.filters | 108 +++--- NineChess/src/gamecontroller.cpp | 217 +++++------ NineChess/src/gamecontroller.h | 2 +- NineChess/src/ninechess.cpp | 535 ++++++++++++++++------------ NineChess/src/ninechess.h | 224 ++++++------ NineChess/src/ninechesswindow.cpp | 2 - NineChess/src/pieceitem.h | 1 + 9 files changed, 648 insertions(+), 505 deletions(-) diff --git a/NineChess/ninechess.pro.user b/NineChess/ninechess.pro.user index 8ed40c40..da6cd138 100644 --- a/NineChess/ninechess.pro.user +++ b/NineChess/ninechess.pro.user @@ -1,10 +1,10 @@ - + EnvironmentId - {fba36f69-c7a3-4c3f-91d4-7c71ad79549c} + {9a8c5f9d-1814-40d9-ab01-983c45f229c5} ProjectExplorer.Project.ActiveTarget @@ -54,19 +54,22 @@ ProjectExplorer.Project.PluginSettings - + + + true + ProjectExplorer.Project.Target.0 - Desktop Qt 5.11.0 MSVC2017 64bit - Desktop Qt 5.11.0 MSVC2017 64bit - qt.qt5.5110.win64_msvc2017_64_kit + Desktop Qt 5.9.7 GCC 64bit + Desktop Qt 5.9.7 GCC 64bit + qt.qt5.597.gcc_64_kit 0 0 0 - E:/My program/QT/NineChess/build-ninechess-Desktop_Qt_5_11_0_MSVC2017_64bit-Debug + /media/sniper/Work/My program/QT/NineChess/build-ninechess-Desktop_Qt_5_9_7_GCC_64bit-Debug true @@ -84,7 +87,10 @@ Make Qt4ProjectManager.MakeStep - + + -w + -r + false @@ -100,7 +106,10 @@ Make Qt4ProjectManager.MakeStep - + + -w + -r + true clean @@ -120,7 +129,7 @@ true - E:/My program/QT/NineChess/build-ninechess-Desktop_Qt_5_11_0_MSVC2017_64bit-Release + /media/sniper/Work/My program/QT/NineChess/build-ninechess-Desktop_Qt_5_9_7_GCC_64bit-Release true @@ -138,7 +147,10 @@ Make Qt4ProjectManager.MakeStep - + + -w + -r + false @@ -154,7 +166,10 @@ Make Qt4ProjectManager.MakeStep - + + -w + -r + true clean @@ -174,7 +189,7 @@ true - E:/My program/QT/NineChess/build-ninechess-Desktop_Qt_5_11_0_MSVC2017_64bit-Profile + /media/sniper/Work/My program/QT/NineChess/build-ninechess-Desktop_Qt_5_9_7_GCC_64bit-Profile true @@ -192,7 +207,10 @@ Make Qt4ProjectManager.MakeStep - + + -w + -r + false @@ -208,7 +226,10 @@ Make Qt4ProjectManager.MakeStep - + + -w + -r + true clean @@ -236,7 +257,7 @@ ProjectExplorer.BuildSteps.Deploy 1 - 部署设置 + Deploy Configuration ProjectExplorer.DefaultDeployConfiguration @@ -286,13 +307,12 @@ ninechess - Qt4ProjectManager.Qt4RunConfiguration:E:/My program/QT/NineChess/NineChess/ninechess.pro + Qt4ProjectManager.Qt4RunConfiguration:/media/sniper/Work/My program/QT/NineChess/NineChess/ninechess.pro true ninechess.pro - false - E:/My program/QT/NineChess/build-ninechess-Desktop_Qt_5_11_0_MSVC2017_64bit-Debug + /media/sniper/Work/My program/QT/NineChess/build-ninechess-Desktop_Qt_5_9_7_GCC_64bit-Debug 3768 false true diff --git a/NineChess/ninechess.sln b/NineChess/ninechess.sln index 30aa6cdb..06c59f80 100644 --- a/NineChess/ninechess.sln +++ b/NineChess/ninechess.sln @@ -8,13 +8,19 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {D6EBE2B6-17F9-30EA-AE68-9CD0BB526200}.Debug|x64.ActiveCfg = Debug|x64 {D6EBE2B6-17F9-30EA-AE68-9CD0BB526200}.Debug|x64.Build.0 = Debug|x64 + {D6EBE2B6-17F9-30EA-AE68-9CD0BB526200}.Debug|x86.ActiveCfg = Debug|Win32 + {D6EBE2B6-17F9-30EA-AE68-9CD0BB526200}.Debug|x86.Build.0 = Debug|Win32 {D6EBE2B6-17F9-30EA-AE68-9CD0BB526200}.Release|x64.ActiveCfg = Release|x64 {D6EBE2B6-17F9-30EA-AE68-9CD0BB526200}.Release|x64.Build.0 = Release|x64 + {D6EBE2B6-17F9-30EA-AE68-9CD0BB526200}.Release|x86.ActiveCfg = Release|Win32 + {D6EBE2B6-17F9-30EA-AE68-9CD0BB526200}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/NineChess/ninechess.vcxproj.filters b/NineChess/ninechess.vcxproj.filters index 7945718a..55cdc238 100644 --- a/NineChess/ninechess.vcxproj.filters +++ b/NineChess/ninechess.vcxproj.filters @@ -23,10 +23,6 @@ {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - {D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E} qrc;* @@ -41,85 +37,76 @@ {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {B83CAF91-C7BF-462F-B76C-EA11631F866C} - * - false - {d3810898-e5d4-49ce-92da-beddffba0697} {16c52ca8-0391-4ad2-919c-4a865ad87e98} + + {afa4cc20-6ea3-4aee-8211-eca831a215d8} + + + {2dce63cc-311c-4d88-a5a4-7fdc289f99c6} + + + {bc588bf0-770b-4800-89b5-64e97e98b22a} + - - Source Files + + Control - Source Files + Control + + + View - Source Files + View - Source Files + View - Source Files - - - Source Files + View - Source Files + View - Source Files + View - - Source Files + + Model - Source Files + Model - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - Generated Files - - Header Files - - Header Files + Control - - Header Files + + Control + + View + + + View + + + Model + + + Model + @@ -269,10 +256,7 @@ - Header Files - - - Header Files + View @@ -285,4 +269,18 @@ Project Files + + + View + + + View + + + View + + + View + + \ No newline at end of file diff --git a/NineChess/src/gamecontroller.cpp b/NineChess/src/gamecontroller.cpp index d6c57f8e..7e821cc7 100644 --- a/NineChess/src/gamecontroller.cpp +++ b/NineChess/src/gamecontroller.cpp @@ -71,7 +71,6 @@ const QMap GameController::getActions() return actions; } - void GameController::gameStart() { chess.start(); @@ -100,11 +99,17 @@ void GameController::gameReset() // 重新绘制棋盘 scene.setDiagonal(chess.getRule()->hasObliqueLine); - // 绘制所有棋子,放在起始位置,分成2组写,后面好区分 + // 绘制所有棋子,放在起始位置 + // 0: 先手第1子; 1:后手第1子 + // 2:先手嫡2子; 3:后手第2子 + // ...... + PieceItem::Models md; + PieceItem *newP; for (int i = 0; i < chess.getRule()->numOfChess; i++) { - PieceItem::Models md = isInverted ? PieceItem::whitePiece : PieceItem::blackPiece; - PieceItem *newP = new PieceItem; + // 先手的棋子 + md = isInverted ? PieceItem::whitePiece : PieceItem::blackPiece; + newP = new PieceItem; newP->setModel(md); newP->setPos(scene.pos_p1); newP->setNum(i + 1); @@ -113,20 +118,19 @@ void GameController::gameReset() newP->setShowNum(true); pieceList.append(newP); scene.addItem(newP); - } - for (int i = 0; i < chess.getRule()->numOfChess; i++) - { - PieceItem::Models md = isInverted ? PieceItem::blackPiece : PieceItem::whitePiece; - PieceItem *newP = new PieceItem; - newP->setModel(md); - newP->setPos(scene.pos_p2); - newP->setNum(i + 1); - // 如果重复三连不可用,则显示棋子序号,九连棋专用玩法 - if (!(chess.getRule()->canRepeated)) - newP->setShowNum(true); - pieceList.append(newP); - scene.addItem(newP); - } + + // 后手的棋子 + md = isInverted ? PieceItem::blackPiece : PieceItem::whitePiece; + newP = new PieceItem; + newP->setModel(md); + newP->setPos(scene.pos_p2); + newP->setNum(i + 1); + // 如果重复三连不可用,则显示棋子序号,九连棋专用玩法 + if (!(chess.getRule()->canRepeated)) + newP->setShowNum(true); + pieceList.append(newP); + scene.addItem(newP); + } // 读取规则限时要求 timeLimit = chess.getRule()->maxTime; @@ -218,7 +222,8 @@ 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); } void GameController::setAnimation(bool arg) @@ -243,10 +248,10 @@ void GameController::playSound(const QString &soundPath) } } -bool GameController::eventFilter(QObject * watched, QEvent * event) -{ - return QObject::eventFilter(watched, event); -} +//bool GameController::eventFilter(QObject * watched, QEvent * event) +//{ +// return QObject::eventFilter(watched, event); +//} void GameController::timerEvent(QTimerEvent *event) { @@ -348,7 +353,7 @@ bool GameController::phaseChange(int row) qDebug() << mlist.at(i); chessTemp.command(mlist.at(i).toStdString().c_str()); } - // 下面这步关键,让悔棋者承担时间损失 + // 下面这步关键,会让悔棋者承担时间损失 chessTemp.setStartTimeb(chess.getStartTimeb()); // 刷新棋局场景 updateScence(chessTemp); @@ -583,12 +588,12 @@ bool GameController::updateScence() bool GameController::updateScence(NineChess &chess) { - const char *board = chess.getBoard(); - QPointF pos; - // chess类中的棋子代码 - int key; - // 棋子总数 - int n = chess.getRule()->numOfChess * 2; + const char *board = chess.getBoard(); + QPointF pos; + // chess类中的棋子代码 + int key; + // 棋子总数 + int n = chess.getRule()->numOfChess * 2; // 动画组 QParallelAnimationGroup *animationGroup = new QParallelAnimationGroup; @@ -596,92 +601,100 @@ bool GameController::updateScence(NineChess &chess) // 棋子就位 PieceItem *piece = nullptr; for (int i = 0; i < n; i++) - { - piece = pieceList.at(i); - // 将pieceList的下标转换为chess的棋子代号 - key = (i >= n/2) ? (i + 0x21 -n/2) : (i + 0x11); - int j; - // 放置棋盘上的棋子 - for (j = NineChess::SEAT; j < (NineChess::SEAT)*(NineChess::RING + 1); j++) - { - if (board[j] == key) - { - pos = scene.cp2pos(j / NineChess::SEAT, j % NineChess::SEAT + 1); - if (piece->pos() != pos) { + { + piece = pieceList.at(i); + // 将pieceList的下标转换为chess的棋子代号 + key = (i % 2) ? (i/2 + 0x21) : (i/2 + 0x11); + int j; + // 遍历棋盘,查找并放置棋盘上的棋子 + for (j = NineChess::SEAT; j < (NineChess::SEAT)*(NineChess::RING + 1); j++) + { + if (board[j] == key) + { + pos = scene.cp2pos(j / NineChess::SEAT, j % NineChess::SEAT + 1); + if (piece->pos() != pos) { + // 让移动的棋子位于顶层 + piece->setZValue(1); + // 棋子移动动画 QPropertyAnimation *animation = new QPropertyAnimation(piece, "pos"); - animation->setDuration(durationTime); - animation->setStartValue(piece->pos()); - animation->setEndValue(pos); - animation->setEasingCurve(QEasingCurve::InOutQuad); - animationGroup->addAnimation(animation); - } - break; - } - } + animation->setDuration(durationTime); + animation->setStartValue(piece->pos()); + animation->setEndValue(pos); + animation->setEasingCurve(QEasingCurve::InOutQuad); + animationGroup->addAnimation(animation); + } + else + { + // 让静止的棋子位于底层 + piece->setZValue(0); + } + break; + } + } - // 放置棋盘外的棋子 - if (j == (NineChess::SEAT)*(NineChess::RING + 1)) - { - // 判断是被吃掉的子,还是未安放的子 - if (key & 0x10) { - pos = (key - 0x11 < n / 2 - chess.getPlayer1_InHand()) ? scene.pos_p2_g : scene.pos_p1; - } - else - pos = (key - 0x21 < n / 2 - chess.getPlayer2_InHand()) ? scene.pos_p1_g : scene.pos_p2; + // 如果没有找到,放置棋盘外的棋子 + if (j == (NineChess::SEAT)*(NineChess::RING + 1)) + { + // 判断是被吃掉的子,还是未安放的子 + if (key & 0x10) { + pos = (key - 0x11 < n / 2 - chess.getPlayer1_InHand()) ? scene.pos_p2_g : scene.pos_p1; + } + else + pos = (key - 0x21 < n / 2 - chess.getPlayer2_InHand()) ? scene.pos_p1_g : scene.pos_p2; - if (piece->pos() != pos) { + if (piece->pos() != pos) { QPropertyAnimation *animation = new QPropertyAnimation(piece, "pos"); animation->setDuration(durationTime); animation->setStartValue(piece->pos()); animation->setEndValue(pos); - animation->setEasingCurve(QEasingCurve::InOutQuad); - animationGroup->addAnimation(animation); + animation->setEasingCurve(QEasingCurve::InOutQuad); + animationGroup->addAnimation(animation); } } - piece->setSelected(false); - } + piece->setSelected(false); + } - // 添加开局禁子点 - if (chess.getRule()->hasForbidden && chess.getPhase() == NineChess::GAME_OPENING) - { - for (int j = NineChess::SEAT; j < (NineChess::SEAT)*(NineChess::RING + 1); j++) - { - if (board[j] == 0x0F) - { - pos = scene.cp2pos(j / NineChess::SEAT, j % NineChess::SEAT + 1); - if (n < pieceList.size()) - { - pieceList.at(n++)->setPos(pos); - } - else - { - PieceItem *newP = new PieceItem; - newP->setDeleted(); - newP->setPos(pos); - pieceList.append(newP); - n++; - scene.addItem(newP); - } - } - } - } + // 添加开局禁子点 + if (chess.getRule()->hasForbidden && chess.getPhase() == NineChess::GAME_OPENING) + { + for (int j = NineChess::SEAT; j < (NineChess::SEAT)*(NineChess::RING + 1); j++) + { + if (board[j] == 0x0F) + { + pos = scene.cp2pos(j / NineChess::SEAT, j % NineChess::SEAT + 1); + if (n < pieceList.size()) + { + pieceList.at(n++)->setPos(pos); + } + else + { + PieceItem *newP = new PieceItem; + newP->setDeleted(); + newP->setPos(pos); + pieceList.append(newP); + n++; + scene.addItem(newP); + } + } + } + } - // 中局清除禁子点 - if (chess.getRule()->hasForbidden && chess.getPhase() != NineChess::GAME_OPENING) - { - while (n < pieceList.size()) - { - delete pieceList.at(n); - pieceList.removeAt(n); - } - } + // 中局清除禁子点 + if (chess.getRule()->hasForbidden && chess.getPhase() != NineChess::GAME_OPENING) + { + while (n < pieceList.size()) + { + delete pieceList.at(n); + pieceList.removeAt(n); + } + } - // 选中当前棋子 + // 选中当前棋子 int ipos = chess.getCurrentPos(); if (ipos) { - key = board[chess.getCurrentPos()]; - currentPiece = pieceList.at(key & 0x10 ? key - 0x11 : key - 0x21 + n/2); - currentPiece->setSelected(true); + key = board[chess.getCurrentPos()]; + currentPiece = pieceList.at(key & 0x10 ? (key - 0x11)*2 : (key - 0x21)*2 + 1); + currentPiece->setSelected(true); } animationGroup->start(QAbstractAnimation::DeleteWhenStopped); diff --git a/NineChess/src/gamecontroller.h b/NineChess/src/gamecontroller.h index 13deae2c..3bdc748d 100644 --- a/NineChess/src/gamecontroller.h +++ b/NineChess/src/gamecontroller.h @@ -80,7 +80,7 @@ public slots: bool updateScence(NineChess &chess); protected: - bool eventFilter(QObject * watched, QEvent * event); + //bool eventFilter(QObject * watched, QEvent * event); // 定时器 void timerEvent(QTimerEvent * event); // 选子 diff --git a/NineChess/src/ninechess.cpp b/NineChess/src/ninechess.cpp index 6eac615d..3bb8bb3b 100644 --- a/NineChess/src/ninechess.cpp +++ b/NineChess/src/ninechess.cpp @@ -105,15 +105,57 @@ const char NineChess::inBoard[(RING + 2)*SEAT] = { '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00' }; +// 招法表 char NineChess::moveTable[(RING + 2)*SEAT][4] = { 0 }; + +// 成三表 char NineChess::millTable[(RING + 2)*SEAT][3][2] = { 0 }; NineChess::NineChess() { + // 单独提出board,免得每次都写data.board; + board = data.board; // 默认选择第0号规则,即“成三棋” setData(&RULES[0]); } +NineChess::NineChess(const NineChess &chess) +{ + rule = chess.rule; + data = chess.data; + board = data.board; + currentPos = chess.currentPos; + winner = chess.winner; + startTimeb = chess.startTimeb; + currentTimeb = chess.currentTimeb; + player1_MS = chess.player1_MS; + player2_MS = chess.player2_MS; + move_ = chess.move_; + memcpy(cmdline, chess.cmdline, sizeof(cmdline)); + cmdlist = chess.cmdlist; + tip = chess.tip; +} + +const NineChess & NineChess::operator=(const NineChess &chess) +{ + if (this == &chess) + return *this; + rule = chess.rule; + data = chess.data; + board = data.board; + currentPos = chess.currentPos; + winner = chess.winner; + startTimeb = chess.startTimeb; + currentTimeb = chess.currentTimeb; + player1_MS = chess.player1_MS; + player2_MS = chess.player2_MS; + move_ = chess.move_; + memcpy(cmdline, chess.cmdline, sizeof(cmdline)); + cmdlist = chess.cmdlist; + tip = chess.tip; +} + + NineChess::~NineChess() { } @@ -129,45 +171,85 @@ bool NineChess::setData(const struct Rule *rule, int s, int t, int step, int fla this->rule = *rule; this->rule.maxSteps = s; this->rule.maxTime = t; - // 设置步数 - this->step = step; - // 设置状态 + // 设置棋局数据 + { + // 设置步数 + data.step = step; + + // 局面阶段标识 + if (flags & GAME_NOTSTARTED) + data.phase = GAME_NOTSTARTED; + else if (flags & GAME_OPENING) + data.phase = GAME_OPENING; + else if (flags & GAME_MID) + data.phase = GAME_MID; + else if (flags & GAME_OVER) + data.phase = GAME_OVER; + else + return false; + // 轮流状态标识 + if (flags & PLAYER1) + data.turn = PLAYER1; + else if (flags & PLAYER2) + data.turn = PLAYER2; + else + return false; + // 动作状态标识 + if (flags & ACTION_CHOOSE) + data.action = ACTION_CHOOSE; + else if (flags & ACTION_PLACE) + data.action = ACTION_PLACE; + else if (flags & ACTION_REMOVE) + data.action = ACTION_REMOVE; + else + return false; + + // 当前棋局(3×8) + if (boardsource == nullptr) + memset(data.board, 0, sizeof(data.board)); + else + memcpy(data.board, boardsource, sizeof(data.board)); + + // 计算盘面子数 + data.player1_Remain = data.player2_Remain = 0; + for (int i = 1; i < RING + 2; i++) + { + for (int j = 0; j < SEAT; j++) + { + if (data.board[i*SEAT + j] & '\x10') + data.player1_Remain++; + else if (data.board[i*SEAT + j] & '\x20') { + data.player2_Remain++; + } + } + } + + // 设置玩家盘面剩余子数和未放置子数 + if (data.player1_Remain > rule->numOfChess || data.player2_Remain > rule->numOfChess) + return false; + if (p1_InHand < 0 || p2_InHand < 0) + return false; + data.player1_InHand = rule->numOfChess - data.player1_Remain; + data.player2_InHand = rule->numOfChess - data.player2_Remain; + data.player1_InHand = p1_InHand < data.player1_InHand ? p1_InHand : data.player1_InHand; + data.player2_InHand = p2_InHand < data.player2_InHand ? p2_InHand : data.player2_InHand; + + // 设置去子状态时的剩余尚待去除子数 + if (flags & ACTION_REMOVE) { + if (num_NeedRemove >= 0 && num_NeedRemove < 3) + data.num_NeedRemove = num_NeedRemove; + } + else + data.num_NeedRemove = 0; + + // 清空成三记录 + data.millList.clear(); + } - // 局面阶段标识 - if (flags & GAME_NOTSTARTED) - phase = GAME_NOTSTARTED; - else if (flags & GAME_OPENING) - phase = GAME_OPENING; - else if (flags & GAME_MID) - phase = GAME_MID; - else if (flags & GAME_OVER) - phase = GAME_OVER; - else - return false; - // 轮流状态标识 - if (flags & PLAYER1) - turn = PLAYER1; - else if (flags & PLAYER2) - turn = PLAYER2; - else - return false; - // 动作状态标识 - if (flags & ACTION_CHOOSE) - action = ACTION_CHOOSE; - else if (flags & ACTION_PLACE) - action = ACTION_PLACE; - else if (flags & ACTION_REMOVE) - action = ACTION_REMOVE; - else - return false; // 胜负标识 winner = NOBODY; - // 当前棋局(3×8) - if (boardsource == nullptr) - memset(this->board, 0, sizeof(this->board)); - else - memcpy(this->board, boardsource, sizeof(this->board)); + // 生成招法表 for (int i = 1; i <= RING; i++) { @@ -197,6 +279,7 @@ bool NineChess::setData(const struct Rule *rule, int s, int t, int step, int fla //} } } + // 生成成三表 for (int j = 0; j < SEAT; j++) { @@ -256,40 +339,6 @@ bool NineChess::setData(const struct Rule *rule, int s, int t, int step, int fla } } - // 计算盘面子数 - player1_Remain = player2_Remain = 0; - for (int i = 1; i < RING + 2; i++) - { - for (int j = 0; j < SEAT; j++) - { - if (board[i*SEAT + j] & '\x10') - player1_Remain++; - else if (board[i*SEAT + j] & '\x20') { - player2_Remain++; - } - } - } - // 设置玩家盘面剩余子数和未放置子数 - if (player1_Remain > rule->numOfChess || player2_Remain > rule->numOfChess) - return false; - if (p1_InHand < 0 || p2_InHand < 0) - return false; - player1_InHand = rule->numOfChess - player1_Remain; - player2_InHand = rule->numOfChess - player2_Remain; - player1_InHand = p1_InHand < player1_InHand ? p1_InHand : player1_InHand; - player2_InHand = p2_InHand < player2_InHand ? p2_InHand : player2_InHand; - - // 设置去子状态时的剩余尚待去除子数 - if (flags & ACTION_REMOVE) { - if (num_NeedRemove >= 0 && num_NeedRemove < 3) - this->num_NeedRemove = num_NeedRemove; - } - else - this->num_NeedRemove = 0; - - // 清空成三记录 - millList.clear(); - // 不选中棋子 currentPos = 0; @@ -318,39 +367,32 @@ bool NineChess::setData(const struct Rule *rule, int s, int t, int step, int fla //return true; } -void NineChess::getData(struct Rule &rule, int &step, int &chess, const char *&board, +void NineChess::getData(struct Rule &rule, int &step, int &flags, const char *&board, int &p1_InHand, int &p2_InHand, int &num_NeedRemove) { rule = this->rule; - step = this->step; - chess = phase | turn | action | winner; - board = this->board; - p1_InHand = player1_InHand; - p2_InHand = player2_InHand; - num_NeedRemove = this->num_NeedRemove; -} - -const char * NineChess::getBoard() -{ - return board; + step = data.step; + flags = data.phase | data.turn | data.action; + board = board; + p1_InHand = data.player1_InHand; + p2_InHand = data.player2_InHand; + num_NeedRemove = data.num_NeedRemove; } bool NineChess::reset() { - if (phase == GAME_NOTSTARTED && player1_MS == player2_MS == 0) + if (data.phase == GAME_NOTSTARTED && player1_MS == player2_MS == 0) return true; // 步数归零 - step = 0; + data.step = 0; // 局面阶段标识 - phase = GAME_NOTSTARTED; - + data.phase = GAME_NOTSTARTED; // 轮流状态标识 - turn = PLAYER1; - + data.turn = PLAYER1; // 动作状态标识 - action = ACTION_PLACE; + data.action = ACTION_PLACE; // 胜负标识 winner = NOBODY; @@ -359,16 +401,16 @@ bool NineChess::reset() memset(board, 0, sizeof(board)); // 盘面子数归零 - player1_Remain = player2_Remain = 0; + data.player1_Remain = data.player2_Remain = 0; // 设置玩家盘面剩余子数和未放置子数 - player1_InHand = player2_InHand = rule.numOfChess; + data.player1_InHand = data.player2_InHand = rule.numOfChess; // 设置去子状态时的剩余尚待去除子数 - num_NeedRemove = 0; + data.num_NeedRemove = 0; // 清空成三记录 - millList.clear(); + data.millList.clear(); // 不选中棋子 currentPos = 0; @@ -400,25 +442,82 @@ bool NineChess::reset() bool NineChess::start() { + switch (data.phase) + { // 如果游戏已经开始,则返回false - if (phase == GAME_OPENING || phase == GAME_MID) + case GAME_OPENING: + case GAME_MID: return false; - // 如果游戏结束,则重置游戏,进入未开始状态 - if (phase == GAME_OVER) - reset(); - + case GAME_OVER: + reset(); // 这里不要break; // 如果游戏处于未开始状态 - if (phase == GAME_NOTSTARTED) { - phase = GAME_OPENING; + case GAME_NOTSTARTED: // 启动计时器 ftime(&startTimeb); + // 进入开局状态 + data.phase = GAME_OPENING; + return true; + default: + return false; + } +} + +bool NineChess::getPieceCP(const Players &player, const int &number, int &c, int &p) +{ + char piece; + + if (player == PLAYER1) + piece = 0x10; + else if (player == PLAYER2) + piece = 0x20; + else + return false; + + if (number > 0 && number <= rule.numOfChess) + piece &= number; + else + return false; + + for (int i = SEAT; i < SEAT*(RING + 1); i++) { + if (board[i] == piece) { + pos2cp(i, c, p); + return true; + } } - // 其它情况 return false; } +// 获取当前棋子 +bool NineChess::getCurrentPiece(Players &player, int &number) +{ + if (!inBoard[currentPos]) + return false; + + if (board[currentPos] & 0x10) { + player = PLAYER1; + number = board[currentPos] - 0x10; + } + else if (board[currentPos] & 0x20) { + player = PLAYER2; + number = board[currentPos] - 0x20; + } + else + return false; + + return true; +} + +bool NineChess::pos2cp(const int pos, int &c, int &p) +{ + if (pos < SEAT || pos >= SEAT * (RING + 1)) + return false; + c = pos / SEAT; + p = pos % SEAT + 1; + return true; +} + int NineChess::cp2pos(int c, int p) { if (c < 1 || c > RING || p < 1 || p > SEAT) @@ -429,14 +528,14 @@ int NineChess::cp2pos(int c, int p) bool NineChess::place(int c, int p, long time_p /* = -1*/) { // 如果局面为“结局”,返回false - if (phase == GAME_OVER) + if (data.phase == GAME_OVER) return false; // 如果局面为“未开局”,则开具 - if (phase == GAME_NOTSTARTED) + if (data.phase == GAME_NOTSTARTED) start(); // 如非“落子”状态,返回false - if (action != ACTION_PLACE) + if (data.action != ACTION_PLACE) return false; // 如果落子位置在棋盘外、已有子点或禁点,返回false int pos = cp2pos(c, p); @@ -448,28 +547,28 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/) // 对于开局落子 char piece = '\x00'; int n = 0; - if (phase == GAME_OPENING) { + if (data.phase == GAME_OPENING) { // 先手下 - if (turn == PLAYER1) + if (data.turn == PLAYER1) { - piece = '\x11' + rule.numOfChess - player1_InHand; - board[pos] = piece; - player1_InHand--; - player1_Remain++; + piece = '\x11' + rule.numOfChess - data.player1_InHand; + data.player1_InHand--; + data.player1_Remain++; } // 后手下 else { - piece = '\x21' + rule.numOfChess - player2_InHand; - board[pos] = piece; - player2_InHand--; - player2_Remain++; + piece = '\x21' + rule.numOfChess - data.player2_InHand; + data.player2_InHand--; + data.player2_Remain++; } + board[pos] = piece; + move_ = pos; player_ms = update(time_p); sprintf(cmdline, "(%1u,%1u) %02u:%02u.%03u", c, p, player_ms / 60000, player_ms / 1000, player_ms % 1000); cmdlist.push_back(string(cmdline)); currentPos = pos; - step++; + data.step++; // 如果决出胜负 if (win()) { setTip(); @@ -480,20 +579,21 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/) // 开局阶段未成三 if (n == 0) { // 如果双方都无未放置的棋子 - if (player1_InHand == 0 && player2_InHand == 0) { + if (data.player1_InHand == 0 && data.player2_InHand == 0) { // 进入中局阶段 - phase = GAME_MID; + data.phase = GAME_MID; // 进入选子状态 - action = ACTION_CHOOSE; + data.action = ACTION_CHOOSE; // 清除禁点 cleanForbidden(); // 设置轮到谁走 if (rule.isDefensiveMoveFirst) { - turn = PLAYER2; + data.turn = PLAYER2; } else { - turn = PLAYER1; + data.turn = PLAYER1; } + // 再决胜负 if (win()) { setTip(); @@ -509,19 +609,19 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/) // 如果成三 else { // 设置去子数目 - num_NeedRemove = rule.removeMore ? n : 1; + data.num_NeedRemove = rule.removeMore ? n : 1; // 进入去子状态 - action = ACTION_REMOVE; + data.action = ACTION_REMOVE; } setTip(); return true; } // 对于中局落子 - else if (phase == GAME_MID) { + else if (data.phase == GAME_MID) { // 如果落子不合法 - if ((turn == PLAYER1 && (player1_Remain > rule.numAtLest || !rule.canFly)) || - (turn == PLAYER2 && (player2_Remain > rule.numAtLest || !rule.canFly))) { + if ((data.turn == PLAYER1 && (data.player1_Remain > rule.numAtLest || !rule.canFly)) || + (data.turn == PLAYER2 && (data.player2_Remain > rule.numAtLest || !rule.canFly))) { int i; for (i = 0; i < 4; i++) { if (pos == moveTable[currentPos][i]) @@ -532,6 +632,7 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/) return false; } // 移子 + 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); @@ -539,13 +640,13 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/) board[pos] = board[currentPos]; board[currentPos] = '\x00'; currentPos = pos; - step++; + data.step++; n = addMills(currentPos); // 中局阶段未成三 if (n == 0) { // 进入选子状态 - action = ACTION_CHOOSE; + data.action = ACTION_CHOOSE; // 设置轮到谁走 changeTurn(); // 如果决出胜负 @@ -557,9 +658,9 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/) // 中局阶段成三 else { // 设置去子数目 - num_NeedRemove = rule.removeMore ? n : 1; + data.num_NeedRemove = rule.removeMore ? n : 1; // 进入去子状态 - action = ACTION_REMOVE; + data.action = ACTION_REMOVE; setTip(); } setTip(); @@ -572,20 +673,20 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/) bool NineChess::remove(int c, int p, long time_p /* = -1*/) { // 如果局面为"未开局"或“结局”,返回false - if (phase == GAME_NOTSTARTED || phase == GAME_OVER) + if (data.phase == GAME_NOTSTARTED || data.phase == GAME_OVER) return false; // 如非“去子”状态,返回false - if (action != ACTION_REMOVE) + if (data.action != ACTION_REMOVE) return false; // 如果去子完成,返回false - if (num_NeedRemove <= 0) + if (data.num_NeedRemove <= 0) return false; // 时间的临时变量 long player_ms = -1; int pos = cp2pos(c, p); // 对手 - enum Player opponent = PLAYER2; - if (turn == PLAYER2) + enum Players opponent = PLAYER2; + if (data.turn == PLAYER2) opponent = PLAYER1; // 判断去子不是对手棋 if (getWhosPiece(c, p) != opponent) @@ -597,20 +698,21 @@ bool NineChess::remove(int c, int p, long time_p /* = -1*/) } // 去子(设置禁点) - if (rule.hasForbidden && phase == GAME_OPENING) + if (rule.hasForbidden && data.phase == GAME_OPENING) board[pos] = '\x0f'; else // 去子 board[pos] = '\x00'; - if (turn == PLAYER1) - player2_Remain--; - else if (turn == PLAYER2) - player1_Remain--; + if (data.turn == PLAYER1) + data.player2_Remain--; + else if (data.turn == PLAYER2) + data.player1_Remain--; + move_ = -pos; player_ms = update(time_p); sprintf(cmdline, "-(%1u,%1u) %02u:%02u.%03u", c, p, player_ms / 60000, player_ms / 1000, player_ms % 1000); cmdlist.push_back(string(cmdline)); currentPos = 0; - num_NeedRemove--; - step++; + data.num_NeedRemove--; + data.step++; // 去子完成 // 如果决出胜负 @@ -619,28 +721,28 @@ bool NineChess::remove(int c, int p, long time_p /* = -1*/) return true; } // 还有其余的子要去吗 - if (num_NeedRemove > 0) { + if (data.num_NeedRemove > 0) { // 继续去子 return true; } // 所有去子都完成了 else { // 开局阶段 - if (phase == GAME_OPENING) { + if (data.phase == GAME_OPENING) { // 如果双方都无未放置的棋子 - if (player1_InHand == 0 && player2_InHand == 0) { + if (data.player1_InHand == 0 && data.player2_InHand == 0) { // 进入中局阶段 - phase = GAME_MID; + data.phase = GAME_MID; // 进入选子状态 - action = ACTION_CHOOSE; + data.action = ACTION_CHOOSE; // 清除禁点 cleanForbidden(); // 设置轮到谁走 if (rule.isDefensiveMoveFirst) { - turn = PLAYER2; + data.turn = PLAYER2; } else { - turn = PLAYER1; + data.turn = PLAYER1; } // 再决胜负 if (win()) { @@ -651,7 +753,7 @@ bool NineChess::remove(int c, int p, long time_p /* = -1*/) // 如果双方还有子 else { // 进入落子状态 - action = ACTION_PLACE; + data.action = ACTION_PLACE; // 设置轮到谁走 changeTurn(); // 如果决出胜负 @@ -664,7 +766,7 @@ bool NineChess::remove(int c, int p, long time_p /* = -1*/) // 中局阶段 else { // 进入选子状态 - action = ACTION_CHOOSE; + data.action = ACTION_CHOOSE; // 设置轮到谁走 changeTurn(); // 如果决出胜负 @@ -681,17 +783,17 @@ bool NineChess::remove(int c, int p, long time_p /* = -1*/) bool NineChess::choose(int c, int p) { // 如果局面不是"中局”,返回false - if (phase != GAME_MID) + if (data.phase != GAME_MID) return false; // 如非“选子”或“落子”状态,返回false - if (action != ACTION_CHOOSE && action != ACTION_PLACE) + if (data.action != ACTION_CHOOSE && data.action != ACTION_PLACE) return false; int pos = cp2pos(c, p); // 根据先后手,判断可选子 char t ='\0'; - if (turn == PLAYER1) + if (data.turn == PLAYER1) t = '\x10'; - else if (turn == PLAYER2) + else if (data.turn == PLAYER2) t = '\x20'; // 判断选子是否可选 if (board[pos] & t) { @@ -702,19 +804,19 @@ bool NineChess::choose(int c, int p) // 选子 currentPos = pos; // 选子完成,进入落子状态 - action = ACTION_PLACE; + data.action = ACTION_PLACE; return true; } return false; } -bool NineChess::giveup(Player loser) +bool NineChess::giveup(Players loser) { - if (phase == GAME_MID || phase == GAME_OPENING) + if (data.phase == GAME_MID || data.phase == GAME_OPENING) { if (loser == PLAYER1) { - phase = GAME_OVER; + data.phase = GAME_OVER; winner = PLAYER2; tip = "玩家1投子认负,恭喜玩家2获胜!"; sprintf(cmdline, "Player1 give up!"); @@ -723,7 +825,7 @@ bool NineChess::giveup(Player loser) } else if (loser == PLAYER2) { - phase = GAME_OVER; + data.phase = GAME_OVER; winner = PLAYER1; tip = "玩家2投子认负,恭喜玩家1获胜!"; sprintf(cmdline, "Player2 give up!"); @@ -784,7 +886,7 @@ bool NineChess::command(const char *cmd) } // 认输 - args = sscanf(cmd, "Player%1u give up!", &t); + args = sscanf(cmd, "Players%1u give up!", &t); if (args == 1) { if (t == 1) { return giveup(PLAYER1); @@ -801,11 +903,11 @@ bool NineChess::command(const char *cmd) inline long NineChess::update(long time_p /*= -1*/) { long ret = -1; - long *player_ms = (turn == PLAYER1 ? &player1_MS : &player2_MS); - long playerNext_ms = (turn == PLAYER1 ? player2_MS : player1_MS); + long *player_ms = (data.turn == PLAYER1 ? &player1_MS : &player2_MS); + long playerNext_ms = (data.turn == PLAYER1 ? player2_MS : player1_MS); // 根据局面调整计时器 - switch (phase) + switch (data.phase) { case NineChess::GAME_OPENING: case NineChess::GAME_MID: @@ -847,9 +949,9 @@ inline long NineChess::update(long time_p /*= -1*/) // 是否分出胜负 bool NineChess::win() { - if (phase == GAME_OVER) + if (data.phase == GAME_OVER) return true; - if (phase == GAME_NOTSTARTED) + if (data.phase == GAME_NOTSTARTED) return false; // 如果有时间限定 @@ -859,7 +961,7 @@ bool NineChess::win() if (player1_MS > rule.maxTime * 60000) { player1_MS = rule.maxTime * 60000; winner = PLAYER2; - phase = GAME_OVER; + data.phase = GAME_OVER; tip = "玩家1超时,恭喜玩家2获胜!"; sprintf(cmdline, "Time over. Player2 win!"); cmdlist.push_back(string(cmdline)); @@ -869,7 +971,7 @@ bool NineChess::win() else if (player2_MS > rule.maxTime * 60000) { player2_MS = rule.maxTime * 60000; winner = PLAYER1; - phase = GAME_OVER; + data.phase = GAME_OVER; tip = "玩家2超时,恭喜玩家1获胜!"; sprintf(cmdline, "Time over. Player1 win!"); cmdlist.push_back(string(cmdline)); @@ -879,9 +981,9 @@ bool NineChess::win() // 如果有步数限定 if (rule.maxSteps > 0) { - if (step > rule.maxSteps) { + if (data.step > rule.maxSteps) { winner = DRAW; - phase = GAME_OVER; + data.phase = GAME_OVER; sprintf(cmdline, "Steps over. In draw!"); cmdlist.push_back(string(cmdline)); return true; @@ -889,26 +991,26 @@ bool NineChess::win() } // 如果玩家1子数小于赛点,则玩家2获胜 - if (player1_Remain + player1_InHand < rule.numAtLest) { + if (data.player1_Remain + data.player1_InHand < rule.numAtLest) { winner = PLAYER2; - phase = GAME_OVER; + data.phase = GAME_OVER; sprintf(cmdline, "Player2 win!"); cmdlist.push_back(string(cmdline)); return true; } // 如果玩家2子数小于赛点,则玩家1获胜 - else if (player2_Remain + player2_InHand < rule.numAtLest) { + else if (data.player2_Remain + data.player2_InHand < rule.numAtLest) { winner = PLAYER1; - phase = GAME_OVER; + data.phase = GAME_OVER; sprintf(cmdline, "Player1 win!"); cmdlist.push_back(string(cmdline)); return true; } // 如果摆满了,根据规则判断胜负 - else if (player1_Remain + player2_Remain >= SEAT * RING) { + else if (data.player1_Remain + data.player2_Remain >= SEAT * RING) { if (rule.isFullLose) { winner = PLAYER2; - phase = GAME_OVER; + data.phase = GAME_OVER; sprintf(cmdline, "Player2 win!"); cmdlist.push_back(string(cmdline)); return true; @@ -916,21 +1018,21 @@ bool NineChess::win() else { winner = DRAW; - phase = GAME_OVER; + data.phase = GAME_OVER; sprintf(cmdline, "Full. In draw!"); cmdlist.push_back(string(cmdline)); return true; } } // 如果中局被“闷” - else if (phase == GAME_MID && action == ACTION_CHOOSE && isAllSurrounded(turn)) { + else if (data.phase == GAME_MID && data.action == ACTION_CHOOSE && isAllSurrounded(data.turn)) { // 规则要求被“闷”判负,则对手获胜 if (rule.isNoWayLose) { - if (turn == PLAYER1) + if (data.turn == PLAYER1) { tip = "玩家1无子可走,恭喜玩家2获胜!"; winner = PLAYER2; - phase = GAME_OVER; + data.phase = GAME_OVER; sprintf(cmdline, "Player1 no way to go. Player2 win!"); cmdlist.push_back(string(cmdline)); return true; @@ -939,7 +1041,7 @@ bool NineChess::win() { tip = "玩家2无子可走,恭喜玩家1获胜!"; winner = PLAYER1; - phase = GAME_OVER; + data.phase = GAME_OVER; sprintf(cmdline, "Player2 no way to go. Player1 win!"); cmdlist.push_back(string(cmdline)); return true; @@ -1019,15 +1121,15 @@ int NineChess::addMills(int pos) // 迭代器 list::iterator itor; // 遍历 - for (itor = millList.begin(); itor != millList.end(); itor++) + for (itor = data.millList.begin(); itor != data.millList.end(); itor++) { if (mill == *itor) break; } // 如果没找到历史项 - if (itor == millList.end()) { + if (itor == data.millList.end()) { n++; - millList.push_back(mill); + data.millList.push_back(mill); } } } @@ -1035,7 +1137,7 @@ int NineChess::addMills(int pos) return n; } -bool NineChess::isAllInMills(enum Player player) +bool NineChess::isAllInMills(enum Players player) { char ch = '\x00'; if (player == PLAYER1) @@ -1044,7 +1146,6 @@ bool NineChess::isAllInMills(enum Player player) ch = '\x20'; else return true; - for (int i = 1; i <= RING; i++) for (int j = 0; j < SEAT; j++) { if (board[i*SEAT + j] & ch) { @@ -1060,8 +1161,8 @@ bool NineChess::isAllInMills(enum Player player) bool NineChess::isSurrounded(int pos) { // 判断pos处的棋子是否被“闷” - if ((turn == PLAYER1 && (player1_Remain > rule.numAtLest || !rule.canFly)) || - (turn == PLAYER2 && (player2_Remain > rule.numAtLest || !rule.canFly))) + if ((data.turn == PLAYER1 && (data.player1_Remain > rule.numAtLest || !rule.canFly)) || + (data.turn == PLAYER2 && (data.player2_Remain > rule.numAtLest || !rule.canFly))) { int i, movePos; for (i = 0; i < 4; i++) { @@ -1078,7 +1179,7 @@ bool NineChess::isSurrounded(int pos) } // 判断玩家的棋子是否全部被围 -bool NineChess::isAllSurrounded(enum Player ply) +bool NineChess::isAllSurrounded(enum Players ply) { char t = '\x30'; if (ply == PLAYER1) @@ -1086,11 +1187,11 @@ bool NineChess::isAllSurrounded(enum Player ply) else if (ply == PLAYER2) t &= '\x20'; // 如果摆满 - if (player1_Remain + player2_Remain >= SEAT * RING) + if (data.player1_Remain + data.player2_Remain >= SEAT * RING) return true; // 判断是否可以飞子 - if ((turn == PLAYER1 && (player1_Remain <= rule.numAtLest && rule.canFly)) || - (turn == PLAYER2 && (player2_Remain <= rule.numAtLest && rule.canFly))) + if ((data.turn == PLAYER1 && (data.player1_Remain <= rule.numAtLest && rule.canFly)) || + (data.turn == PLAYER2 && (data.player2_Remain <= rule.numAtLest && rule.canFly))) { return false; } @@ -1121,52 +1222,53 @@ void NineChess::cleanForbidden() } } -enum NineChess::Player NineChess::changeTurn() +enum NineChess::Players NineChess::changeTurn() { // 设置轮到谁走 - return turn = (turn == PLAYER1) ? PLAYER2 : PLAYER1; + data.turn = (data.turn == PLAYER1) ? PLAYER2 : PLAYER1; + return data.turn; } void NineChess::setTip() { - switch (phase) + switch (data.phase) { case NineChess::GAME_NOTSTARTED: - tip = "轮到玩家1落子,剩余" + std::to_string(player1_InHand) + "子"; + tip = "轮到玩家1落子,剩余" + std::to_string(data.player1_InHand) + "子"; break; case NineChess::GAME_OPENING: - if (action == ACTION_PLACE) { - if (turn == PLAYER1) { - tip = "轮到玩家1落子,剩余" + std::to_string(player1_InHand) + "子"; + if (data.action == ACTION_PLACE) { + if (data.turn == PLAYER1) { + tip = "轮到玩家1落子,剩余" + std::to_string(data.player1_InHand) + "子"; } - else if (turn == PLAYER2) { - tip = "轮到玩家2落子,剩余" + std::to_string(player2_InHand) + "子"; + else if (data.turn == PLAYER2) { + tip = "轮到玩家2落子,剩余" + std::to_string(data.player2_InHand) + "子"; } } - else if (action == ACTION_REMOVE) { - if (turn == PLAYER1) { - tip = "轮到玩家1去子,需去" + std::to_string(num_NeedRemove) + "子"; + else if (data.action == ACTION_REMOVE) { + if (data.turn == PLAYER1) { + tip = "轮到玩家1去子,需去" + std::to_string(data.num_NeedRemove) + "子"; } - else if (turn == PLAYER2) { - tip = "轮到玩家2去子,需去" + std::to_string(num_NeedRemove) + "子"; + else if (data.turn == PLAYER2) { + tip = "轮到玩家2去子,需去" + std::to_string(data.num_NeedRemove) + "子"; } } break; case NineChess::GAME_MID: - if (action == ACTION_PLACE || action == ACTION_CHOOSE) { - if (turn == PLAYER1) { + if (data.action == ACTION_PLACE || data.action == ACTION_CHOOSE) { + if (data.turn == PLAYER1) { tip = "轮到玩家1选子移动"; } - else if (turn == PLAYER2) { + else if (data.turn == PLAYER2) { tip = "轮到玩家2选子移动"; } } - else if (action == ACTION_REMOVE) { - if (turn == PLAYER1) { - tip = "轮到玩家1去子,需去" + std::to_string(num_NeedRemove) + "子"; + else if (data.action == ACTION_REMOVE) { + if (data.turn == PLAYER1) { + tip = "轮到玩家1去子,需去" + std::to_string(data.num_NeedRemove) + "子"; } - else if (turn == PLAYER2) { - tip = "轮到玩家2去子,需去" + std::to_string(num_NeedRemove) + "子"; + else if (data.turn == PLAYER2) { + tip = "轮到玩家2去子,需去" + std::to_string(data.num_NeedRemove) + "子"; } } break; @@ -1191,7 +1293,7 @@ void NineChess::setTip() } } -enum NineChess::Player NineChess::getWhosPiece(int c, int p) +enum NineChess::Players NineChess::getWhosPiece(int c, int p) { int pos = cp2pos(c, p); if (board[pos] & '\x10') @@ -1201,13 +1303,6 @@ enum NineChess::Player NineChess::getWhosPiece(int c, int p) return NOBODY; } -int NineChess::getPieceNum(int c, int p) -{ - int pos = cp2pos(c, p); - int n = 0x0f & board[pos]; - return n; -} - void NineChess::getPlayer_TimeMS(int &p1_ms, int &p2_ms) { update(); diff --git a/NineChess/src/ninechess.h b/NineChess/src/ninechess.h index d6d2636d..4a9bd8ce 100644 --- a/NineChess/src/ninechess.h +++ b/NineChess/src/ninechess.h @@ -21,6 +21,14 @@ using std::list; class NineChess { public: + // 5个静态成员常量 + // 3圈,禁止修改! + static const int RING = 3; + // 8位,禁止修改! + static const int SEAT = 8; + // 预定义的规则数目 + static const int RULENUM = 4; + // 嵌套的规则结构体 struct Rule { @@ -53,39 +61,80 @@ public: // 包干最长时间(秒),超出判负,为0则不计时 int maxTime; }; + // 预定义的规则 + static const struct Rule RULES[RULENUM]; // 局面阶段标识 enum Phases { - GAME_NOTSTARTED = 0x00000001, // 未开局 - GAME_OPENING = 0x00000002, // 开局(摆棋) - GAME_MID = 0x00000004, // 中局(走棋) - GAME_OVER = 0x00000008 // 结局 + GAME_NOTSTARTED = 0x0001, // 未开局 + GAME_OPENING = 0x0002, // 开局(摆棋) + GAME_MID = 0x0004, // 中局(走棋) + GAME_OVER = 0x0008 // 结局 }; // 玩家标识,轮流状态,胜负标识 - enum Player { - PLAYER1 = 0x00000010, // 玩家1 - PLAYER2 = 0x00000020, // 玩家2 - DRAW = 0x00000040, // 双方和棋 - NOBODY = 0x00000080 // 胜负未分 + enum Players { + PLAYER1 = 0x0010, // 玩家1 + PLAYER2 = 0x0020, // 玩家2 + DRAW = 0x0040, // 双方和棋 + NOBODY = 0x0080 // 胜负未分 }; // 动作状态标识 enum Actions { - ACTION_CHOOSE = 0x00000100, // 选子 - ACTION_PLACE = 0x00000200, // 落子 - ACTION_REMOVE = 0x00000400 // 提子 + ACTION_CHOOSE = 0x0100, // 选子 + ACTION_PLACE = 0x0200, // 落子 + ACTION_REMOVE = 0x0400 // 提子 }; - // 5个静态成员常量 - // 3圈,禁止修改! - static const int RING = 3; - // 8位,禁止修改! - static const int SEAT = 8; - // 预定义的规则数目 - static const int RULENUM = 4; - // 预定义的规则 - static const struct Rule RULES[RULENUM]; + // 棋局结构体,包含当前棋盘数据 + // 单独分离出来供AI判断局面用,生成置换表时使用 + struct ChessData { + // 棋局,抽象为一个(5×8)的char数组,上下两行留空 + /* 0x00代表无棋子 + 0x0F代表禁点 + 0x11~0x1C代表先手第1~12子 + 0x21~0x2c代表后手第1~12子 + 判断棋子是先手的用(board[i] & 0x10) + 判断棋子是后手的用(board[i] & 0x20) */ + char board[(NineChess::RING + 2)*NineChess::SEAT]; + + // 当前步数 + int step; + // 局面阶段标识 + enum NineChess::Phases phase; + // 轮流状态标识 + enum NineChess::Players turn; + // 动作状态标识 + enum NineChess::Actions action; + + // 玩家1剩余未放置子数 + char player1_InHand; + // 玩家2剩余未放置子数 + char player2_InHand; + // 玩家1盘面剩余子数 + char player1_Remain; + // 玩家1盘面剩余子数 + char player2_Remain; + // 尚待去除的子数 + char num_NeedRemove; + + /* 本打算用如下的结构体来表示“三连” + struct Mill { + char piece1; // “三连”中最小的棋子 + char pos1; // 最小棋子的位置 + char piece2; // 次小的棋子 + char pos2; // 次小棋子的位置 + char piece3; // 最大的棋子 + char pos3; // 最大棋子的位置 + }; + 但为了提高执行效率改用一个64位整数了,规则如下 + 0x 00 00 00 00 00 00 00 00 + unused unused piece1 pos1 piece2 pos2 piece3 pos3 + */ + // “三连列表” + list millList; + }; private: // 空棋盘点位,用于判断一个棋子位置是否在棋盘上 @@ -100,20 +149,19 @@ private: static char millTable[(RING + 2)*SEAT][3][2]; public: - NineChess(); + explicit NineChess(); virtual ~NineChess(); - /* 拷贝构造函数 - 其实NineChess类没有指针类型的成员变量,list内的值也是深拷贝 - 所以没有必要写拷贝构造函数了 - */ - //explicit NineChess(const NineChess &); + // 拷贝构造函数 + explicit NineChess(const NineChess &); + // 运算符重载 + const NineChess & operator=(const NineChess &); // 设置棋局状态和棋盘数据,用于初始化 bool setData(const struct Rule *rule, int s = 0, // 限制步数 int t = 0, // 限制时间 int step = 0, // 默认起始步数为0 - int flags = GAME_NOTSTARTED | PLAYER1 | ACTION_PLACE | NOBODY, // 默认状态 + int flags = GAME_NOTSTARTED | PLAYER1 | ACTION_PLACE, // 默认状态 const char *boardsource = nullptr, // 默认空棋盘 int p1_InHand = 12, // 玩家1剩余未放置子数 int p2_InHand = 12, // 玩家2剩余未放置子数 @@ -122,30 +170,32 @@ public: // 获取棋局状态和棋盘数据 void getData(struct Rule &rule, int &step, int &flags, const char *&boardsource, int &p1_InHand, int &p2_InHand, int &num_NeedRemove); - // 获取棋盘数据 - const char *getBoard(); // 获取当前规则 const struct Rule *getRule() { return &rule; } - // 获取当前点 + // 获取棋盘数据 + const char *getBoard() { return data.board; } + // 获取棋子位置(c, p) + bool getPieceCP(const Players &player, const int &number, int &c, int &p); + // 获取当前棋子 + bool getCurrentPiece(Players &player, int &number); + // 获取当前棋子位置点 int getCurrentPos() { return currentPos; } // 获取当前步数 - int getStep() { return step; } + int getStep() { return data.step; } // 获取局面阶段标识 - enum Phases getPhase() { return phase; } + enum Phases getPhase() { return data.phase; } // 获取轮流状态标识 - enum Player whosTurn() { return turn; } + enum Players whosTurn() { return data.turn; } // 获取动作状态标识 - enum Actions getAction() { return action; } + enum Actions getAction() { return data.action; } // 判断胜负 - enum Player whoWin() { return winner; } + enum Players whoWin() { return winner; } // 玩家1和玩家2的用时 void getPlayer_TimeMS(int &p1_ms, int &p2_ms); // 获取棋局的字符提示 const string getTip() { return tip; } // 获取位置点棋子的归属人 - enum Player getWhosPiece(int c, int p); - // 获取位置点棋子的序号 - int getPieceNum(int c, int p); + enum Players getWhosPiece(int c, int p); // 获取当前招法 const char *getCmdLine() { return cmdline; } // 获得棋谱 @@ -156,15 +206,15 @@ public: void setStartTimeb(timeb stimeb) { startTimeb = stimeb; } // 玩家1剩余未放置子数 - int getPlayer1_InHand() { return player1_InHand; } + int getPlayer1_InHand() { return data.player1_InHand; } // 玩家2剩余未放置子数 - int getPlayer2_InHand() { return player2_InHand; } + int getPlayer2_InHand() { return data.player2_InHand; } // 玩家1盘面剩余子数 - int getPlayer1_Remain() { return player1_Remain; } + int getPlayer1_Remain() { return data.player1_Remain; } // 玩家1盘面剩余子数 - int getPlayer2_Remain() { return player2_Remain; } + int getPlayer2_Remain() { return data.player2_Remain; } // 尚待去除的子数 - int getNum_NeedRemove() { return num_NeedRemove; } + int getNum_NeedRemove() { return data.num_NeedRemove; } // 游戏重置 bool reset(); @@ -177,7 +227,7 @@ public: // 去子,在第c圈第p个位置,为迎合日常,c和p下标都从1开始 bool remove(int c, int p, long time_p = -1); // 认输 - bool giveup(Player loser); + bool giveup(Players loser); // 命令行解析函数 bool command(const char *cmd); @@ -185,13 +235,15 @@ protected: // 判断棋盘pos处的棋子处于几个“三连”中 int isInMills(int pos); // 判断玩家的所有棋子是否都处于“三连”状态 - bool isAllInMills(enum Player); + bool isAllInMills(enum Players); // 判断玩家的棋子是否被围 bool isSurrounded(int pos); // 判断玩家的棋子是否全部被围 - bool isAllSurrounded(enum Player); + bool isAllSurrounded(enum Players); // 三连加入列表 int addMills(int pos); + // 将棋盘下标形式转化为第c圈,第p位,c和p下标都从1开始 + bool pos2cp(const int pos, int &c, int &p); // 将第c圈,第p位转化为棋盘下标形式,c和p下标都从1开始 int cp2pos(int c, int p); // 更新时间和状态,用内联函数以提高效率 @@ -201,72 +253,21 @@ protected: // 清除所有禁点 void cleanForbidden(); // 改变轮流 - enum NineChess::Player changeTurn(); + enum NineChess::Players changeTurn(); // 设置提示 void setTip(); private: - // 当前步数 - int step; - // 局面阶段标识 - enum Phases phase; - // 轮流状态标识 - enum Player turn; - // 动作状态标识 - enum Actions action; - // 赢家 - enum Player winner; - - // 玩家1剩余未放置子数 - int player1_InHand; - // 玩家2剩余未放置子数 - int player2_InHand; - // 玩家1盘面剩余子数 - int player1_Remain; - // 玩家1盘面剩余子数 - int player2_Remain; - // 尚待去除的子数 - int num_NeedRemove; - - /* 棋局,抽象为一个(5×8)的char数组,上下两行留空 - * 0x00代表无棋子 - * 0x0F代表禁点 - * 0x11~0x1C代表先手第1~12子 - * 0x21~0x2c代表后手第1~12子 - * 判断棋子是先手的用(board[i] & 0x10) - * 判断棋子是后手的用(board[i] & 0x20) - */ - char board[(NineChess::RING + 2)*NineChess::SEAT]; - - /* 本打算用如下的结构体来表示“三连” - struct Mill { - char piece1; // “三连”中最小的棋子 - char pos1; // 最小棋子的位置 - char piece2; // 次小的棋子 - char pos2; // 次小棋子的位置 - char piece3; // 最大的棋子 - char pos3; // 最大棋子的位置 - }; - 但为了提高执行效率改用一个64位整数了,规则如下 - 0x 00 00 00 00 00 00 00 00 - unused unused piece1 pos1 piece2 pos2 piece3 pos3 - */ - // “三连列表” - list millList; - - /* 当前招法,AI会用到,如下表示 - 0x 00 00 - pos1 pos2 - 开局落子:0x00??,??为棋盘上的位置 - 移子:0x__??,__为移动前的位置,??为移动后的位置 - 去子:0xFF??,??为棋盘上去子点的位置 - */ - short move_; - // 当前使用的规则 struct Rule rule; + // 棋局数据 + struct ChessData data; + // 棋局数据中的棋盘数据,单独提出来 + char *board; // 选中的棋子在board中的位置 - int currentPos; + char currentPos; + // 胜负标识 + enum Players winner; // 游戏起始时间 timeb startTimeb; @@ -277,11 +278,22 @@ private: // 玩家2用时(毫秒) long player2_MS; + /* 当前招法,AI会用到,如下表示 + 0x 00 00 + pos1 pos2 + 开局落子:0x00??,??为棋盘上的位置 + 移子:0x__??,__为移动前的位置,??为移动后的位置 + 去子:0xFF??,??取位置补码,即为负数 + */ + short move_; + // 招法命令行用于棋谱的显示和解析 // 当前招法的命令行指令,即一招棋谱 char cmdline[32]; + // 棋谱 list cmdlist; + // 当前棋局的字符提示 string tip; }; diff --git a/NineChess/src/ninechesswindow.cpp b/NineChess/src/ninechesswindow.cpp index 926ce61b..819d3a18 100644 --- a/NineChess/src/ninechesswindow.cpp +++ b/NineChess/src/ninechesswindow.cpp @@ -251,7 +251,6 @@ void NineChessWindow::actionRules_triggered() ruleInfo(); } - void NineChessWindow::on_actionNew_N_triggered() { if (file.isOpen()) @@ -521,7 +520,6 @@ void NineChessWindow::on_actionAutoRun_A_toggled(bool arg1) ui.actionAutoRun_A->setChecked(false); } - void NineChessWindow::on_actionLimited_T_triggered() { /* 其实本来可以用设计器做个ui,然后从QDialog派生个自己的对话框 diff --git a/NineChess/src/pieceitem.h b/NineChess/src/pieceitem.h index 2e6e169c..6ac1ca44 100644 --- a/NineChess/src/pieceitem.h +++ b/NineChess/src/pieceitem.h @@ -32,6 +32,7 @@ public: enum Models getModel() { return model; } void setModel(enum Models model) { this->model = model; } + int getNum() { return num; } void setNum(int n) { num = n; } bool isDeleted() { return deleted; } void setDeleted(bool deleted = true)