コード例 #1
0
ファイル: ChessGame.cs プロジェクト: CatAndLion/PvPChess
        /// <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);
        }
コード例 #2
0
 /// <summary>
 /// Убрать фигуру с доски
 /// </summary>
 /// <param name="position">позиция</param>
 public void RemovePiece(BoardCoord position)
 {
     if (!IsValidSpace(position))
     {
         return;
     }
     board[position.row, position.column] = null;
 }
コード例 #3
0
 /// <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;
 }
コード例 #4
0
 public ChessPiece GetPiece(BoardCoord position)
 {
     if (!IsValidSpace(position))
     {
         return(null);
     }
     return(board[position.row, position.column]);
 }
コード例 #5
0
ファイル: ChessMove.cs プロジェクト: CatAndLion/PvPChess
 public ChessMove(PlayerColor player, BoardCoord from, BoardCoord to, ChessPiece piece, ChessPiece defeated = null)
 {
     this.player   = player;
     From          = from;
     To            = to;
     MovingPiece   = piece;
     DefeatedPiece = defeated;
 }
コード例 #6
0
        public void MovePiece(BoardCoord from, BoardCoord to)
        {
            ChessPiece p = board[from.row, from.column];

            if (p != null)
            {
                PutPiece(p, to);
                RemovePiece(from);
            }
        }
コード例 #7
0
 /// <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);
 }
コード例 #8
0
ファイル: ChessGame.cs プロジェクト: CatAndLion/PvPChess
        /// <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);
        }
コード例 #9
0
ファイル: MovementRules.cs プロジェクト: CatAndLion/PvPChess
        /// <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);
        }
コード例 #10
0
ファイル: MovementRules.cs プロジェクト: CatAndLion/PvPChess
        /// <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);
        }
コード例 #11
0
ファイル: MovementRules.cs プロジェクト: CatAndLion/PvPChess
        /// <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);
        }
コード例 #12
0
ファイル: ChessGame.cs プロジェクト: CatAndLion/PvPChess
        /// <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);
        }
コード例 #13
0
ファイル: MovementRules.cs プロジェクト: CatAndLion/PvPChess
        /// <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);
        }
コード例 #14
0
 /// <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);
 }