基于ChessCtrl控件的国际象棋VC++MFC源码
ChessCtrl 是在 MFC 库的帮助下用 C++ 编写的功能齐全的国际象棋控件。您猜对了,主类是 ,其中包括类。CChessCtrlChessBoard ChessBoardclass 实现以下功能: - void resetBoard():制作新游戏;将 engine 的字段静止并在板上插入适当的部分。
- void submitMove(const TCHAR* fromSquare, const TCHAR* toSquare)
- void getANewBoard()
- void makeGameInCheck()
- void makeGameNotInCheck()
- void beginAGame()
- void endTheGame()
- void makeWhiteGoesNext()
- bool gameCanContinue(wstring sourceFileRank, wstring destFileRank):检查游戏是否未结束。
- bool sourceAndDestIsValid(wstring sourceFileRank, wstring destFileRank):检查给定的 source 和 dest 的文件和排名表示是否有效(wstring 有 2 个字符)并且在棋盘内。
- bool withinChessBoard(wstring fileRank):检查文件是否在“A”-“H”范围内,排名是否在“1”-“8”范围内。
- bool sourceIsNotEmpty(wstring sourceFileRank, Board* board): 检查源是否不是一个空的方格(即有一个棋子要移动)。
- bool isCurrentPlayerPiece(bool isWhiteTurn, Piece* piece, wstring sourceFileRank):检查源头的棋子是否依次属于玩家。
- bool pieceMoveIsValid(int returnCode, Piece* piece, wstring sourceFileRank, wstring destFileRank):检查验证 piece move 的返回码是否为零。
- bool pieceMoveKeepsKingSafe(bool isWhiteTurn, Piece* piece, wstring sourceFileRank, wstring destFileRank, Board* sandboxBoard):检查给定方的 K 在给定的棋盘下是否安全(在 ChessBoard 中,它将是一个沙箱),如果没有,则向用户发出错误并返回 false。
- void handleInvalidMove(int returnCode, Piece* piece, wstring sourceFileRank, wstring destFileRank):调用错误处理程序来打印错误,并传递调用函数给出的信息。
- bool kingIsSafeFromRivalry(bool isWhiteTurn, Board* board):如果另一方的任何棋子都无法捕获给定方的 King(即对 King 的档案和等级有有效的移动),则返回 true。
- bool playerHaveValidMove(bool isWhiteTurn, Board* board):如果给定的一方在给定的棋盘上有有效的移动,则返回 true。
- wstring findPlayersKingFileRank(bool isWhiteTurn, Board* board):迭代并返回给定一方的国王的位置(文件和等级)。
- Piece* tryMoveAndReturnCaptured(wstring sourceFileRank, wstring destFileRank, Board* board):给定一个板,从源移动到目的地并获取捕获物;情况 1 (尝试阻止) - 目标中的另一块 (进行捕获);情况 2 (catch block) - 目标中不存在棋子 (进行移动)。如果情况为 1,则返回该块,否则为 NULL。
- void confirmMoveOnBoard(wstring sourceFileRank, wstring destFileRank, Board* board):给定一个板,执行从源到目标的移动;情况 1 (尝试阻止) - 目标中的另一块 (进行捕获);情况 2 (catch block) - 目标中不存在棋子 (进行移动)。
- void switchPlayers()
- Board* cloneBoard(Board* board):深度克隆给定的棋盘 - 包括地图中的所有棋子。
- void deepCleanBoard(Board* board):深度清理给定的板子,释放所有包含 Piece 的内存和它自己。
- bool showMoveAndCheckIfGameCanContinue(Piece* piece, wstring sourceFileRank, Piece* capturedPiece, wstring destFileRank, bool isWhiteTurn, Board* board):在 stdout 上打印文本和图形的方法。
- void ComputerPlayer():如果启用,则为计算机的黑棋移动实施回溯算法。
ChessBoardclass 包括以下类: - EmptyPiece(源自Piece)
- Bishop(源自Piece)
- King(源自Piece)
- Knight(源自Piece)
- Pawn(源自Piece)
- Queen(源自Piece)
- Rook(源自Piece)
Piececlass 声明以下虚函数: - Piece* clone():返回一个不同的对象,该对象具有相同的自身信息。
- int isValidMove(wstring sourceFileRank, wstring destFileRank, map<wstring, Piece*>* board)
- wstring playerToString():返回乐曲 player 的 wString 代表。
- wstring toString(): 返回乐段的 wString 表示。
- wstring toGraphics():返回作品的图形表示。
- int Score():返回乐曲的乐谱(由 Backtracking 算法用于执行计算机移动)。
并且它实现了以下功能: - void confirmMove():在调用时设置 false,因为它至少移动了一次。isFirstMove
- bool isWhitePlayer(): 返回此棋子是否属于白棋手。
- bool isKing():如果棋子是 King(由 isKing 表示 - 仅由 King 构造函数设置为 true),则返回 true。
- bool isFriendly(Piece* that):如果此 Piece 和该 Piece 属于同一玩家,则返回 true。
- bool isSameFile(wstring sourceFileRank, wstring destFileRank):如果 sourceFileRank 和 destFileRank 分别位于同一文件/排名/对角线上,则返回 true;否则为 false。
- bool isSameRank(wstring sourceFileRank, wstring destFileRank):如果 sourceFileRank 和 destFileRank 分别位于同一文件/排名/对角线上,则返回 true;否则为 false。
- bool isSameDiagonal(wstring sourceFileRank, wstring destFileRank):如果 sourceFileRank 和 destFileRank 分别位于同一文件/排名/对角线上,则返回 true;否则为 false。
- bool noVerticalObstruction(wstring sourceFileRank, wstring destFileRank, map<wstring, Piece*>* board): 如果棋盘上没有中等等级的棋子,则返回 true;否则为 false。
- bool noHorizontalObstruction(wstring sourceFileRank, wstring destFileRank, map<wstring, Piece*>* board): 如果棋盘上的中间文件上没有棋子,则返回 true;否则为 false。
- bool noDiagonalObstruction(wstring sourceFileRank, wstring destFileRank, map<wstring, Piece*>* board):如果棋盘上的中间文件和排名上没有棋子,则返回 true;否则为 false。
- bool destExistFriendlyPiece(wstring destFileRank, map<wstring, Piece*>* board):如果棋盘上的中间文件和排名上没有棋子,则返回 true;否则为 false。
国际象棋规则
国际象棋规则(也称为国际象棋规则)支配着国际象棋游戏的进行。Chess 是一款双人抽象策略棋盘游戏。每个玩家控制棋盘上 6 种类型的 16 个棋子。每种类型的棋子都以不同的方式移动。游戏的目的是将死对方的国王;当国王受到被俘的威胁并且无法逃脱时,就会发生将死。除了将死之外,一盘棋还可以以多种方式结束:玩家可以认输,并且一盘棋可以通过多种方式以平局结束。 虽然国际象棋的确切起源尚不清楚,但现代规则最早形成于中世纪。规则继续略有修改,直到 19 世纪初,它们基本上达到了现在的形式。规则也因地区而异。今天,标准规则是由国际象棋管理机构 FIDE(国际象棋联合会)制定的。一些国家组织出于自身目的进行了轻微的修改。快速国际象棋、通信国际象棋、在线国际象棋和 Chess960 的规则有多种变体。 除了棋子的基本移动外,规则还管理使用的设备、时间控制、玩家的行为和道德、身体残疾玩家的住宿以及使用国际象棋符号记录移动。还提供了解决比赛期间可能发生的异常情况的程序。 初始设置
国际象棋是在棋盘上进行的,棋盘是一个方格,分为 64 个颜色交替的方格(8 x 8)的网格(类似于草稿中使用的棋盘)。无论棋盘的实际颜色如何,颜色较浅的方格称为“浅色”或“白色”,而颜色较深的方格称为“深色”或“黑色”。游戏开始时,16 颗“白”棋和 16 颗“黑”棋子被放置在棋盘上。放置棋盘时,每个玩家的右上角都有一个白色方块。水平行称为 ranks,垂直列称为 files。 每个玩家控制 16 个棋子:
基于ChessCtrl控件的国际象棋VC++MFC源码
在游戏开始时,棋子的排列如图所示:每方一个国王、一个皇后、两个车、两个象、两个骑士和八个兵。放置棋子,每个方格一个,如下所示: - 车放置在外角、右侧和左侧边缘。
- 骑士被放置在车的内侧。
- 主教被放置在骑士内部。
- 皇后被放置在与棋子颜色相同的中央方块上:白色皇后位于白色方块上,黑色皇后位于黑色方块上。
- 国王占据了王后旁边的空位。
- Pawn 被放置在所有其他棋子前面的一个方格中。
用来记住设置的流行助记词是 “queen on her own color” 和 “white on right”。后者是指设置棋盘,使每个玩家右侧最靠近的方格为白色。 游戏玩法
控制白棋的玩家命名为 “White”;控制黑棋的玩家被命名为 “Black”。白先下棋,然后玩家交替下棋。需要采取行动;跳过搬家是不合法的,即使不得不搬家是有害的。游戏一直持续到国王被将死、玩家弃权或宣布平局,如下所述。此外,如果游戏是在时间控制下进行的,超过时间限制的玩家将输掉游戏,除非他们无法将死。 官方国际象棋规则不包括决定谁下白棋的程序。相反,这个决定取决于特定于锦标赛的规则(例如瑞士制锦标赛或循环赛),或者在休闲游戏的情况下,双方达成协议,在这种情况下,可以采用某种随机选择,例如抛硬币。一种常见的方法是让一个玩家在任一手中隐藏每种颜色的兵;另一位玩家选择一手牌开牌,并获得所展示的棋子的颜色。 运动
基本动作
每种类型的棋子都有自己的移动方法。棋子移动到空位位置,除非吃掉对手的棋子。 除了骑士和易位的任何移动外,棋子不能跳过其他棋子。当进攻的敌方棋子在其方格上替换一个棋子时,该棋子被捕获(或拿走)。因此,捕获的棋子将从游戏中永久删除。国王可以被控制,但不能被捕获(见下文)。 国王正好在水平、垂直或对角线上移动一个方格。每位玩家每场比赛只允许使用国王进行一次特殊移动,称为易位(见下文)。 车水平或垂直移动任意数量的空位。在易位时,它也会移动。 象沿对角线移动任意数量的空位。(因此,象只能移动到浅色或深色方格,而不能同时移动到两者。 皇后可以水平、垂直或对角线移动任意数量的空位。 骑士移动到不在同一等级、文件或对角线上的最近方格之一。(这可以被认为是水平移动两个方格,然后垂直移动一个方格,或者水平移动一个方格,然后垂直移动两个方格——即呈“L”形。骑士没有被其他棋子挡住;它会跳转到新位置。 Pawn 具有最复杂的移动规则: 如果该方格为空,则兵直接向前移动一个方格。如果它还没有移动,兵也可以选择直接向前移动两个方格,前提是两个方格都是空的。Pawn 不能向后移动。 与其他棋子不同,兵的捕获方式与它的移动方式不同。兵可以在兵对角线前方的两个方格中的任何一个上吃掉一个敌方棋子。当空置时,它不能移动到那些方格,除非在边路边吃掉。
兵还参与了 en passant 和 promotion 这两个特殊动作。 王车易位
易位包括将国王向车移动两个方格,然后将车放在国王的另一侧,与它相邻。只有在满足以下所有条件的情况下,才允许进行易位转换: - 参与易位的 king 和 rook 之前必须没有移动过;
- 国王和车之间不能有棋子;
- 王目前不能受到攻击,王也不能穿过或进入受到敌方棋子攻击的方格(尽管允许车受到攻击并越过被攻击的方格);
- 如图所示,易位必须是 kingside 或 queenside。
一个未移动的国王和一个相同颜色的相同等级的未移动的车被称为具有易位权。 顺便一提
当兵在初始移动中前进两个方格并结束与同等级敌方兵相邻的回合时,它可能会被敌方兵顺便吃掉,就像它只移动了一个方格一样。这种捕获仅在 pawn 前进后的移动中是合法的。这些图展示了一个例子:如果白兵从 a2 移动到 a4,b4 上的黑兵可以顺便吃掉它,从 b4 移动到 a3,并且 a4 上的白兵从棋盘上移走。 晋升
如果玩家将兵提升到第八级,则根据玩家的选择(通常选择皇后),该兵将被提升(转换)为相同颜色的皇后、车、象或骑士。选择不仅限于以前捕获的棋子。因此,如果玩家的所有兵都被提升,理论上玩家最多可以有 9 个 Q 或最多 10 个车、象或马。 检查
当 K 受到至少一个敌方棋子的攻击时,它处于受控状态。一个棋子因为会让自己的 K 处于过路而无法移动(它与自己的 K 相对),仍然可以向对方玩家发送过牌。 做出控制或离开国王的举动是违法的。摆脱检查的可能方法是: - 将 K 移动到一个不受控制的方格。
- 捕获检查件。
- 在 K 和对手的威胁棋子之间插入一个棋子(阻止过路)。
在非正式对局中,习惯上在下棋将对手的国王置于对阵中时宣布“过牌”。然而,在正式比赛中,很少宣布检查。 游戏结束
将军
如果玩家的 K 被将死,并且玩家没有合法的移动来逃避过牌,那么该 K 被称为将死,游戏结束,该玩家输了。 该图显示了一个将死位置示例。白王受到黑王的威胁;国王可以移动到的空位也受到威胁;国王无法捕获皇后,因为那样它就会被车将军。 辞职
任何一名玩家都可以随时认牌,将游戏让给对手。为了表示 resignation,玩家可以说 “I resign”。翻倒国王也表示无奈,但应该与不小心将国王撞倒区分开来。停止两个 clocks 并不表示辞职,因为可以停止 clocks 以调用仲裁者。有时会使用握手提议,但可能会被误认为是平局提议。 根据国际棋联法律,如果一名棋手的弃权无法通过任何一系列合法棋步将死,则为平局,否则该棋手将输。 绘制
如果出现以下任何一种情况,则游戏以平局结束: - 要移动的玩家不在检查中,也没有合法的移动。这种情况称为僵局。此类位置的示例显示在相邻的图中。
- 游戏陷入死局。
- 在其中一名玩家提出这样的报价后,双方玩家都同意平局。
此外,在国际棋联规则中,如果一名选手的时间用完了(见下文),或者已经放弃,但局面是这样的,对手无法通过任何一系列的合法移动来将死,那么比赛就是平局。 国际棋联的竞技游戏规则允许玩家在以下两种情况下之一宣布平局: - 每个玩家都走了 50 步棋,没有捕获或提升兵(这是 50 步规则;
- 相同的位置已经出现过三次(或者已经出现过两次,而要求听牌的玩家可以强制第三次出现);这就是三重重复法则。
这些规则有助于防止游戏在锦标赛中无限期延长。 不再有专门将永久过牌定义为平局的规则。在这种情况下,三重重复规则或五十步规则最终都会生效。更多时候,玩家会简单地同意平局。 死区
死位被定义为任何玩家都无法通过任何合法移动序列将死对手的 K的位置。根据国际象棋规则,当棋盘上出现死局时,游戏立即终止。 一些基本结局总是死位;例如: - 国王对国王;
- 国王对抗国王和主教;
- 国王对抗国王和骑士。
可能会出现任何一方都无法取得进展的阻塞位置,例如图解位置;这些也是死局面。 USCF 规则,对于在不包括延迟或增量的时间控制下进行的比赛,允许因“输球机会不足”而要求平局。例如,如果每个玩家都只有一个 K 和一个 k,那么将死只有在两个玩家的合作下才能实现,即使它不是死局。 触摸移动规则
触棋规则是国际象棋的一项基本原则,确保棋手在脑海中经过深思熟虑地进行棋步,而无需在棋盘上进行身体实验。根据此规则,如果玩家触摸棋子并打算移动它,则必须在法律允许的情况下移动它。这条规则也适用于吃掉:如果有合法的吃球机会,触碰对手棋子的玩家必须吃掉它。特殊注意事项适用于易位和兵升级,这反映了它们在游戏中的独特性质。 如果玩家触摸棋子以调整其在方格内的物理位置,则必须首先通过说 J'adoube 或“I adjust”来提醒对手。游戏开始后,只有先走棋的玩家才可以触摸棋盘上的棋子。
此开源项目使用以下库(附件中已经包含以下项目库源码):
链接:https://pan.quark.cn/s/bcba5583fce5
提取码下载:
|