private CheckersMove IsMoveValidCore(CheckersPiece piece, Point[] path) { // Failsafe .. be sure piece is valid if (piece == null) { throw new ArgumentNullException("piece"); } if (!pieces.Contains(piece)) { throw new ArgumentException("Argument 'piece' must be a piece in play to the current game."); } // Be sure piece can be moved if (!CanMovePiece(piece)) { throw new ArgumentException("Checkers piece cannot be moved on this turn.", "piece"); } CheckersMove move = CheckersMove.FromPath(this, piece, path); if (!move.Moved) { return(null); // No movement } if (move.MustMove) { return(null); // A move must yet be made } // Success return(move); }
/// <summary>Returns whether or not a move is valid.</summary> /// <param name="move">The CheckersMove object to check.</param> /// <returns>True if the move is valid.</returns> public bool IsValidMove(CheckersPiece piece, Point[] path) { if (!isPlaying) { throw new InvalidOperationException("Operation requires game to be playing."); } return(IsMoveValidCore(piece, path) != null); }
/// <summary>Enumerates all possible moves from this point.</summary> /// <param name="optionalJumping">Overrides the game's OptionalJumping parameter for the enumeration.</param> /// <param name="jumped">Returns the array of Checkers piecse that are jumped, with respect to the moves.</param> /// <returns>An array of points which represent valid moves.</returns> public Point[] EnumMoves(bool optionalJumping, out CheckersPiece[] jumped) { if (this._CannotMove) { jumped = new CheckersPiece[0]; return(new Point[0]); } return(EnumMovesCore(this._CurrentLocation, out jumped, optionalJumping)); }
/// <summary>Moves a Checkers piece on the board.</summary> /// <param name="piece">The checkers piece to move.</param> /// <param name="path">The the location for the piece to be moved to, and the path taken to get there.</param> /// <returns>True if the piece was moved successfully.</returns> public bool MovePiece(CheckersPiece piece, Point[] path) { if (isReadOnly) { throw new InvalidOperationException("Game is read only."); } if (!isPlaying) { throw new InvalidOperationException("Operation requires game to be playing."); } // Check for valid move CheckersMove move = IsMoveValidCore(piece, path); // Remove jumped pieces foreach (CheckersPiece jumped in move.Jumped) { if (board[jumped.Location.X, jumped.Location.Y] == jumped) { board[jumped.Location.X, jumped.Location.Y] = null; } pieces.Remove(jumped); jumped.RemovedFromPlay(); } // Move the piece on board board[piece.Location.X, piece.Location.Y] = null; board[move.CurrentLocation.X, move.CurrentLocation.Y] = piece; piece.Moved(move.CurrentLocation); // King a pawn if reached other end of board if (move.Kinged) { piece.Promoted(); } // Remember last move lastMove = move; // Update player's turn int prevTurn = turn; if (++turn > PlayerCount) { turn = 1; } // Check for win by removal of opponent's pieces or by no turns available this turn if ((EnumPlayerPieces(prevTurn).Length == 0) || (EnumMovablePieces().Length == 0)) { DeclareWinner(prevTurn); } else if (TurnChanged != null) { TurnChanged(this, EventArgs.Empty); } return(true); }
/// <summary>Enumerates all possible jump moves from this point.</summary> /// <param name="jumped">Returns the array of Checkers piecse that are jumped, with respect to the moves.</param> /// <returns>An array of points which represent valid moves.</returns> public Point[] EnumJumpMoves(out CheckersPiece[] jumped) { if (this._CannotMove) { jumped = new CheckersPiece[0]; return(new Point[0]); } ArrayList jumpedList; ArrayList moves = EnumJumpMovesCore(this._CurrentLocation, out jumpedList); jumped = (CheckersPiece[])jumpedList.ToArray(typeof(CheckersPiece)); return((Point[])moves.ToArray(typeof(Point))); }
// Construtores #region Construtores /// <summary> /// Será criada um movimento indiretamente por um jogo através do método BeginMove /// </summary> /// <param name="game">Jogo qual o movimento pertence</param> /// <param name="piece">Peça movida</param> /// <param name="makeReadOnlyCopy">É somente leitura?</param> internal CheckersMove(CheckersGame game, CheckersPiece piece, bool makeReadOnlyCopy) { this._Game = game; this._Piece = piece; this._InitialGame = (((makeReadOnlyCopy) && (!game.IsReadOnly)) ? (CheckersGame.MakeReadOnly(game)) : (game)); this._InitialPiece = this._InitialGame.Pieces[Array.IndexOf(game.Pieces, piece)]; this._Board = (CheckersPiece[, ])game.Board.Clone(); this._CurrentLocation = piece.Location; this._Jumped = new ArrayList(); this._Path = new ArrayList(); this._CannotMove = false; this._Kinged = false; }
// Métodos públicos #region Publicos /// <summary>Cria uma peça igual para um outro jogo (possívelmene clonado).</summary> /// <param name="game">Jogo para o qual será criada a peça</param> /// <returns>A nova peça criada.</returns> public CheckersPiece Clone(CheckersGame game) { // Recupera a peça a clonada CheckersPiece clonedPiece = game.PieceAt(Location); // Certifica que a peça existe e é igual if (clonedPiece?.Player != Player || (clonedPiece.InPlay != InPlay) || (clonedPiece.Rank != Rank)) { return(null); } // Retorna peça clonada return(clonedPiece); }
/// <summary>Begins the checkers game.</summary> public void Play() { if (isReadOnly) { throw new InvalidOperationException("Game is read only."); } if (isPlaying) { throw new InvalidOperationException("Game has already started."); } Stop(); isPlaying = true; for (int y = BoardSize.Height - 1; y >= 5; y--) { for (int x = 0; x < BoardSize.Width; x++) { if ((x % 2) == (y % 2)) { continue; } CheckersPiece piece = new CheckersPiece(this, 1, CheckersRank.Pawn, new Point(x, y), true); board[x, y] = piece; pieces.Add(piece); } } for (int y = 0; y < 3; y++) { for (int x = 0; x < BoardSize.Width; x++) { if ((x % 2) == (y % 2)) { continue; } CheckersPiece piece = new CheckersPiece(this, 2, CheckersRank.Pawn, new Point(x, y), true); board[x, y] = piece; pieces.Add(piece); } } // Set player's turn turn = firstMove; lastMove = null; if (GameStarted != null) { GameStarted(this, EventArgs.Empty); } }
/// <summary>Returns whether or not the checkers piece can be moved this turn.</summary> /// <param name="piece">The checkers piece to test.</param> /// <returns>True when piece can be moved.</returns> public bool CanMovePiece(CheckersPiece piece) { if ((!isPlaying) && (winner == 0)) { throw new InvalidOperationException("Operation requires game to be playing."); } if (piece == null) { throw new ArgumentNullException("piece"); } if (!pieces.Contains(piece)) { throw new ArgumentException("Argument 'piece' must be a piece in play to the current game."); } return(piece.Player == turn); }
private ArrayList EnumJumpMovesCore(CheckersPiece piece, Point fromLocation, out ArrayList jumped) { ArrayList moves = new ArrayList(); jumped = new ArrayList(); // Append jumps (not of same team) if ((piece.Direction == CheckersDirection.Up) || (piece.Rank == CheckersRank.King)) { if (this._Game.InBounds(fromLocation.X - 1, fromLocation.Y - 1) && (this._Board[fromLocation.X - 1, fromLocation.Y - 1] != null) && (this._Board[fromLocation.X - 1, fromLocation.Y - 1].Player != piece.Player)) { if (InBounds(fromLocation.X - 2, fromLocation.Y - 2) && (this._Board[fromLocation.X - 2, fromLocation.Y - 2] == null)) { moves.Add(new Point(fromLocation.X - 2, fromLocation.Y - 2)); jumped.Add(this._Board[fromLocation.X - 1, fromLocation.Y - 1]); } } if (InBounds(fromLocation.X + 1, fromLocation.Y - 1) && (this._Board[fromLocation.X + 1, fromLocation.Y - 1] != null) && (this._Board[fromLocation.X + 1, fromLocation.Y - 1].Player != piece.Player)) { if (InBounds(fromLocation.X + 2, fromLocation.Y - 2) && (this._Board[fromLocation.X + 2, fromLocation.Y - 2] == null)) { moves.Add(new Point(fromLocation.X + 2, fromLocation.Y - 2)); jumped.Add(this._Board[fromLocation.X + 1, fromLocation.Y - 1]); } } } if ((piece.Direction == CheckersDirection.Down) || (piece.Rank == CheckersRank.King)) { if (InBounds(fromLocation.X - 1, fromLocation.Y + 1) && (this._Board[fromLocation.X - 1, fromLocation.Y + 1] != null) && (this._Board[fromLocation.X - 1, fromLocation.Y + 1].Player != piece.Player)) { if (InBounds(fromLocation.X - 2, fromLocation.Y + 2) && (this._Board[fromLocation.X - 2, fromLocation.Y + 2] == null)) { moves.Add(new Point(fromLocation.X - 2, fromLocation.Y + 2)); jumped.Add(this._Board[fromLocation.X - 1, fromLocation.Y + 1]); } } if (InBounds(fromLocation.X + 1, fromLocation.Y + 1) && (this._Board[fromLocation.X + 1, fromLocation.Y + 1] != null) && (this._Board[fromLocation.X + 1, fromLocation.Y + 1].Player != piece.Player)) { if (InBounds(fromLocation.X + 2, fromLocation.Y + 2) && (this._Board[fromLocation.X + 2, fromLocation.Y + 2] == null)) { moves.Add(new Point(fromLocation.X + 2, fromLocation.Y + 2)); jumped.Add(this._Board[fromLocation.X + 1, fromLocation.Y + 1]); } } } return(moves); }
// Métodos internos #region Internos /// <summary>Cria um movimento a partir do caminho passado</summary> /// <param name="game">Jogo para o qual será criado o movimento</param> /// <param name="piece">A peça que será movida</param> /// <param name="path">O caminho pelo qual a peça será movida</param> /// <returns>O movimento resultante</returns> internal static CheckersMove FromPath(CheckersGame game, CheckersPiece piece, Point[] path) { // Cria um novo movimento CheckersMove move = new CheckersMove(game, piece, true); // Para cada casa no caminho passado foreach (Point p in path) { // Se não conseguiu mover a peça if (move.Move(p) == false) { // Retorna null return(null); } } // Se moveu a peça por todas localizações, retorna o movimento return(move); }
/// <summary>Creates a Checkers game from supplied game parameters.</summary> /// <param name="optionalJumping">The Optional Jumping rule.</param> /// <param name="board">The Checkers board that makes up the game.</param> /// <param name="turn">Whose turn it is.</param> /// <param name="winner">The winner, or 0 if none yet.</param> /// <returns>The Checkers game.</returns> public static CheckersGame Create(bool optionalJumping, CheckersPiece[,] board, int turn, int winner) { if ((board.GetLength(0) != BoardSize.Width) || (board.GetLength(1) != BoardSize.Height)) { throw new ArgumentOutOfRangeException("board", board, "Board's dimensions must be " + BoardSize.Width + "x" + BoardSize.Height); } CheckersGame game = new CheckersGame(optionalJumping); game.board = new CheckersPiece[BoardSize.Width, BoardSize.Height]; game.pieces = new CheckersPieceCollection(); for (int y = 0; y < BoardSize.Height; y++) { for (int x = 0; x < BoardSize.Width; x++) { CheckersPiece piece = board[x, y]; if (piece == null) { continue; } if (piece.Owner != null) { throw new ArgumentOutOfRangeException("board", board, "Board contains a Checkers piece that belongs to another Checkers game."); } if (!piece.InPlay) { throw new ArgumentOutOfRangeException("board", board, "Board contains a Checkers piece that is not in play."); } if ((piece.Location.X != x) || (piece.Location.Y != y)) { throw new ArgumentOutOfRangeException("board", board, "Board contains a Checkers piece that does not match up with it's board location."); } if ((piece.Player != 1) || (piece.Player != 2)) { throw new ArgumentOutOfRangeException("board", board, "Board contains a Checkers piece that is not associated with a valid player."); } game.pieces.Add(new CheckersPiece(game, piece.Player, piece.Rank, piece.Location, piece.InPlay)); } } game.isPlaying = true; game.turn = turn; game.winner = winner; return(game); }
/// <summary>Begins a move by creating a CheckersMove object to assist in generating a valid movement.</summary> /// <param name="piece">The Checkers piece to be moved.</param> /// <returns>The CheckersMove object.</returns> public CheckersMove BeginMove(CheckersPiece piece) { if ((!isPlaying) && (winner == 0)) { throw new InvalidOperationException("Operation requires game to be playing."); } // Failsafe .. be sure piece is valid if (piece == null) { throw new ArgumentNullException("piece"); } if (!pieces.Contains(piece)) { throw new ArgumentException("Argument 'piece' must be a piece in play to the current game."); } // Be sure piece can be moved if (!CanMovePiece(piece)) { throw new ArgumentException("Checkers piece cannot be moved on this turn.", "piece"); } return(new CheckersMove(this, piece, true)); }
/// <summary>Creates a duplicate Checkers game object.</summary> /// <returns>The new Checkers move object.</returns> public CheckersGame Clone() { CheckersGame game = new CheckersGame(optionalJumping); game.isReadOnly = isReadOnly; game.isPlaying = isPlaying; game.firstMove = firstMove; game.turn = turn; game.winner = winner; game.pieces = new CheckersPieceCollection(); game.board = new CheckersPiece[BoardSize.Width, BoardSize.Height]; foreach (CheckersPiece piece in pieces) { CheckersPiece newPiece = new CheckersPiece(game, piece.Player, piece.Rank, piece.Location, piece.InPlay); game.board[newPiece.Location.X, newPiece.Location.Y] = newPiece; game.pieces.Add(newPiece); } int lastMovePieceIndex = ((lastMove != null) ? (pieces.IndexOf(lastMove.Piece)) : (-1)); game.lastMove = ((lastMovePieceIndex != -1) ? (CheckersMove.FromPath(game, game.pieces[lastMovePieceIndex], lastMove.Path)) : (null)); return(game); }
/// <summary> /// Retorna a posiçao que uma peça se encontra na coleçao /// </summary> /// <param name="item">Peça a ser procurada</param> /// <returns>Posição da peça na coleção</returns> public int IndexOf(CheckersPiece item) { // Index da peça return(InnerList.IndexOf(item)); }
/// <summary> /// Retorna se uma peça existe na coleção /// </summary> /// <param name="item">Peça a ser procurada</param> /// <returns>Se a peça existe</returns> public bool Contains(CheckersPiece item) { // Retorna se a peça existe return(InnerList.Contains(item)); }
/// <summary> /// Remove a peça passada /// </summary> /// <param name="item">Peça a ser removida</param> public void Remove(CheckersPiece item) { // Remove a peça InnerList.Remove(item); }
/// <summary> /// Insere uma peça em uma determinada posição /// </summary> /// <param name="index">Posiçao a inserir</param> /// <param name="item">Peça a ser inserida</param> public void Insert(int index, CheckersPiece item) { // Insere peça InnerList.Insert(index, item); }
/// <summary> /// Adiciona uma peça a coleção /// </summary> /// <param name="item">Peça a ser adicionada</param> /// <returns>Posição me que foi inserida</returns> public int Add(CheckersPiece item) { return(InnerList.Add(item)); }