/// <summary> /// Проверка на рокировку /// </summary> /// <param name="piece">фигура проверки</param> /// <param name="from">начальная позиция</param> /// <param name="to">конечная позиция</param> /// <returns></returns> private bool CheckForCastling(ChessPiece piece, BoardCoord from, BoardCoord to) { if (piece.PieceType != ChessPieceType.King || piece.HasMoved) { return(false); } int kingMoveLength = from.column - to.column; if (from.row != to.row || Math.Abs(kingMoveLength) != 2) { return(false); } foreach (var rook in chessBoard.GetPiecesOfType(ChessPieceType.Rook, piece.Color)) { if (rook.Value.HasMoved || Math.Abs(rook.Key.column - to.column) > Math.Abs(kingMoveLength)) { continue; } int rookColumn = to.column + Math.Sign(kingMoveLength); currentMove.Push(new ChessMove(piece.Color, from, to, piece)); currentMove.Push(new ChessMove(piece.Color, rook.Key, new BoardCoord(rook.Key.row, (sbyte)rookColumn), rook.Value)); return(true); } return(false); }
/// <summary> /// Убрать фигуру с доски /// </summary> /// <param name="position">позиция</param> public void RemovePiece(BoardCoord position) { if (!IsValidSpace(position)) { return; } board[position.row, position.column] = null; }
/// <summary> /// Поставить фигуру на доску lol /// </summary> /// <param name="piece">фигура</param> /// <param name="position">позиция</param> public void PutPiece(ChessPiece piece, BoardCoord position) { if (!IsValidSpace(position)) { return; } board[position.row, position.column] = piece; }
public ChessPiece GetPiece(BoardCoord position) { if (!IsValidSpace(position)) { return(null); } return(board[position.row, position.column]); }
public ChessMove(PlayerColor player, BoardCoord from, BoardCoord to, ChessPiece piece, ChessPiece defeated = null) { this.player = player; From = from; To = to; MovingPiece = piece; DefeatedPiece = defeated; }
public void MovePiece(BoardCoord from, BoardCoord to) { ChessPiece p = board[from.row, from.column]; if (p != null) { PutPiece(p, to); RemovePiece(from); } }
/// <summary> /// Получить фигуру на доске /// </summary> /// <param name="position">позиция</param> /// <param name="piece">фигура</param> /// <returns></returns> public bool TryGetPiece(BoardCoord position, out ChessPiece piece) { piece = null; if (!IsValidSpace(position)) { return(false); } piece = board[position.row, position.column]; return(piece != null); }
/// <summary> /// Сделать ход /// </summary> /// <param name="from">начальная позиция</param> /// <param name="to">конечная позиция</param> /// <returns></returns> public Stack <ChessMove> MakeMove(BoardCoord from, BoardCoord to) { ChessPiece playerPiece, oponentPiece; if (!chessBoard.TryGetPiece(from, out playerPiece)) { return(null); } currentMove.Clear(); if (!CheckForCastling(playerPiece, from, to)) { /// если не рокировка, делаем обычный ход ChessMove move = new ChessMove(playerPiece.Color, from, to, playerPiece); currentMove.Push(move); if (chessBoard.TryGetPiece(to, out oponentPiece)) { move.DefeatedPiece = oponentPiece; } CheckForNewQueen(move); } bool selfCheck = false; foreach (ChessMove move in currentMove) { /// обновляем доску chessBoard.RemovePiece(move.To); chessBoard.MovePiece(move.From, move.To); /// проверка на собственный шах if (IsPlayerChecked(move.MovingPiece.Color)) { selfCheck = true; break; } playerPiece.HasMoved = true; /// проверка на шах и мат bool check; Mate = IsMate(move.To, move.MovingPiece.Color, out check); Check = check; CurrentPlayerColor = CurrentPlayerColor == PlayerColor.White ? PlayerColor.Black : PlayerColor.White; } /// отменяем ход if (selfCheck) { ReverseMove(); } return(currentMove); }
/// <summary> /// Получить возможные ходы /// </summary> /// <param name="board">доска</param> /// <param name="position">начальная позиция</param> /// <returns></returns> public List <BoardCoord> GetAvailableSpaces(ChessBoard board, BoardCoord position) { ChessPiece piece; List <BoardCoord> result = new List <BoardCoord>(); if (board == null || !board.TryGetPiece(position, out piece)) { return(result); } bool invert = MainPlayerColor != piece.Color; switch (piece.PieceType) { case ChessPieceType.Rook: { return(GetAvailableSpaces(board, position, PieceMovementType.Continuos, invert, Left, Right, Up, Down)); } case ChessPieceType.Bishop: { return(GetAvailableSpaces(board, position, PieceMovementType.Continuos, invert, UpLeft, UpRight, DownLeft, DownRight)); } case ChessPieceType.Knight: { return(GetAvailableSpaces(board, position, PieceMovementType.Descrete, invert, Up + UpLeft, Up + UpRight, Down + DownLeft, Down + DownRight, Left + UpLeft, Left + DownLeft, Right + UpRight, Right + DownRight)); } case ChessPieceType.Queen: { return(GetAvailableSpaces(board, position, PieceMovementType.Continuos, invert, Left, Right, Up, Down, UpLeft, UpRight, DownLeft, DownRight)); } case ChessPieceType.King: { return(GetKingAvailableSpaces(board, position, piece, invert)); } case ChessPieceType.Pawn: { return(GetPawnAvailableSpaces(board, position, piece, invert)); } } return(result); }
/// <summary> /// Получить возможные ходы пешки /// </summary> /// <param name="board">доска</param> /// <param name="position">начальная позиция</param> /// <param name="pawn">пешка</param> /// <param name="invert">инвертировать ход</param> /// <returns></returns> private List <BoardCoord> GetPawnAvailableSpaces(ChessBoard board, BoardCoord position, ChessPiece pawn, bool invert) { List <BoardCoord> result = new List <BoardCoord>(); if (board == null || pawn.PieceType != ChessPieceType.Pawn) { return(result); } BoardCoord[] increment = { Up, UpLeft, UpRight }; if (invert) { for (int i = 0; i < increment.Length; i++) { increment[i] = increment[i].Inverted(); } } /// проверка на наличие враждебных фигур ChessPiece piece; BoardCoord spaceCoord = position + increment[0]; int moveCount = pawn.HasMoved ? 1 : 2; for (int i = 0; i < moveCount; i++) { if (board.IsValidSpace(spaceCoord) && !board.TryGetPiece(spaceCoord, out piece)) { result.Add(spaceCoord); } else { break; } spaceCoord += increment[0]; } for (int i = 1; i < increment.Length; i++) { spaceCoord = position + increment[i]; if (board.TryGetPiece(spaceCoord, out piece) && piece.Color != pawn.Color) { result.Add(spaceCoord); } } return(result); }
/// <summary> /// Получить возможные ходы /// </summary> /// <param name="board">доска</param> /// <param name="position">начальная позиция</param> /// <param name="moveType">тип перемещения</param> /// <param name="invert">инвертировать ход</param> /// <param name="increment">направления хода</param> /// <returns></returns> private List <BoardCoord> GetAvailableSpaces(ChessBoard board, BoardCoord position, PieceMovementType moveType, bool invert, params BoardCoord[] increment) { ChessPiece piece; List <BoardCoord> result = new List <BoardCoord>(); if (increment == null || increment.Length == 0 || board == null || !board.TryGetPiece(position, out piece)) { return(result); } for (int i = 0; i < increment.Length; i++) { BoardCoord delta = increment[i]; if (invert) { delta = delta.Inverted(); } ChessPiece pieceAtSpace; BoardCoord spaceCoord = position + delta; while (board.IsValidSpace(spaceCoord)) { if (!board.TryGetPiece(spaceCoord, out pieceAtSpace)) { result.Add(spaceCoord); spaceCoord += delta; if (moveType == PieceMovementType.Descrete) { break; } } else { if (pieceAtSpace.Color != piece.Color) { result.Add(spaceCoord); } break; } } } return(result); }
/// <summary> /// Проверка на мат /// </summary> /// <param name="coord">позиция</param> /// <param name="color">цвет игрока</param> /// <param name="check">проверка на шах</param> /// <returns></returns> private bool IsMate(BoardCoord coord, PlayerColor color, out bool check) { check = false; PlayerColor otherPlayerColor = color == PlayerColor.Black ? PlayerColor.White : PlayerColor.Black; /// проверка на шах List <BoardCoord> spaces = chessRules.GetAvailableSpaces(chessBoard, coord); var king = chessBoard.GetPiecesOfType(ChessPieceType.King, otherPlayerColor).FirstOrDefault(); foreach (var space in spaces) { if (space == king.Key) { check = true; break; } } /// если не шах, то и продолжать незачем if (!check) { return(false); } /// проверка на мат foreach (var piece in chessBoard.GetAllChessPieces(otherPlayerColor)) { foreach (var space in chessRules.GetAvailableSpaces(chessBoard, piece.Key)) { ChessPiece tmp = chessBoard.GetPiece(space); chessBoard.RemovePiece(space); chessBoard.MovePiece(piece.Key, space); bool oponentChecked = IsPlayerChecked(otherPlayerColor); chessBoard.MovePiece(space, piece.Key); chessBoard.PutPiece(tmp, space); if (!oponentChecked) { return(false); } } } return(true); }
/// <summary> /// Получить возможные ходы короля /// </summary> /// <param name="board">доска</param> /// <param name="position">начальная позиция</param> /// <param name="king">король</param> /// <param name="invert">инвертировать ход</param> /// <returns></returns> private List <BoardCoord> GetKingAvailableSpaces(ChessBoard board, BoardCoord position, ChessPiece king, bool invert) { /// ходы по-умолчанию List <BoardCoord> result = GetAvailableSpaces(board, position, PieceMovementType.Descrete, invert, Up, Down, Left, Right, UpLeft, UpRight, DownLeft, DownRight); /// проверка на рокировку if (king.HasMoved) { return(result); } foreach (var rook in board.GetPiecesOfType(ChessPieceType.Rook, king.Color)) { if (rook.Value.HasMoved) { continue; } bool hasOtherPieces = false; int kingDir = rook.Key.column - position.column; for (int i = 1; i < System.Math.Abs(kingDir); i++) { ChessPiece piece; BoardCoord coord = new BoardCoord(rook.Key.row, (sbyte)(rook.Key.column - i * System.Math.Sign(kingDir))); if (board.TryGetPiece(coord, out piece)) { hasOtherPieces = true; break; } } if (!hasOtherPieces) { result.Add(new BoardCoord(position.row, (sbyte)(position.column + 2 * System.Math.Sign(kingDir)))); } } return(result); }
/// <summary> /// Проверка позиции на доске /// </summary> /// <param name="pos">позиция</param> /// <returns></returns> public bool IsValidSpace(BoardCoord pos) { return(pos.row >= 0 && pos.row < BOARD_SIZE && pos.column >= 0 && pos.column < BOARD_SIZE); }