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 a list of legal moves from all pieces this turn.</summary> /// <param name="optionalJumping">Overrides the game's OptionalJumping parameter for the enumeration.</param> /// <returns>A list of legal moves.</returns> public CheckersMove[] EnumLegalMoves(bool optionalJumping) { if ((!isPlaying) && (winner == 0)) { throw new InvalidOperationException("Operation requires game to be playing."); } Stack incompleteMoves = new Stack(); ArrayList moves = new ArrayList(); foreach (CheckersPiece piece in EnumMovablePieces(optionalJumping)) { incompleteMoves.Push(BeginMove(piece)); } while (incompleteMoves.Count > 0) { CheckersMove move = (CheckersMove)incompleteMoves.Pop(); foreach (Point location in move.EnumMoves(optionalJumping)) { CheckersMove nextMove = move.Clone(); if (!nextMove.Move(location)) { continue; } if (nextMove.CanMove) { incompleteMoves.Push(nextMove); } if (!nextMove.MustMove) { moves.Add(nextMove); } } } return((CheckersMove[])moves.ToArray(typeof(CheckersMove))); }
/// <summary> /// Sends the player's move to the opponent's game. /// </summary> private void DoMovePieceNet(CheckersMove move) { try { BinaryWriter bw = new BinaryWriter(new NetworkStream(remotePlayer.Socket, false)); bw.Write((byte)ClientMessage.MakeMove); bw.Write(move.InitialPiece.Location.X); bw.Write(move.InitialPiece.Location.Y); bw.Write(move.Path.Length); foreach (Point point in move.Path) { bw.Write(point.X); bw.Write(point.Y); } bw.Close(); } catch (IOException) { AppendMessage("", "Connection closed"); CloseNetGame(); remotePlayer = null; } catch (SocketException ex) { AppendMessage("", "Disconnected from opponent: " + ex.Message); CloseNetGame(); remotePlayer = null; } catch (InvalidOperationException ex) { AppendMessage("", "Disconnected from opponent: " + ex.Message); CloseNetGame(); remotePlayer = null; } }
/// <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(CheckersMove move) { if (move == null) { return(false); } return(IsValidMove(move.Piece, move.Path)); }
/// <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>Moves a Checkers piece on the board.</summary> /// <param name="move">The movement object to which the piece will move to.</param> /// <returns>True if the piece was moved successfully.</returns> public bool MovePiece(CheckersMove move) { if (isReadOnly) { throw new InvalidOperationException("Game is read only."); } if (move == null) { return(false); } return(MovePiece(move.Piece, move.Path)); }
/// <summary>Creates a Checkers move object from a given path.</summary> /// <param name="game">The Checkers game to create the movement to.</param> /// <param name="piece">The Checkers piece which will be moving.</param> /// <param name="path">The path to move along.</param> /// <returns>The new Checkers move object.</returns> internal static CheckersMove FromPath(CheckersGame game, CheckersPiece piece, Point[] path) { CheckersMove move = new CheckersMove(game, piece, true); foreach (Point p in path) { if (move.Move(p) == false) { return(null); } } return(move); }
/// <summary>Creates a duplicate Checkers move object, so different paths may be tested from a particular point.</summary> /// <returns>The new Checkers move object.</returns> public CheckersMove Clone() { CheckersMove move = new CheckersMove(game, piece, false); move.initialGame = initialGame; move.initialPiece = initialPiece; move.board = (CheckersPiece[, ])board.Clone(); move.currentLocation = currentLocation; move.jumped = (ArrayList)jumped.Clone(); move.kinged = kinged; move.path = (ArrayList)path.Clone(); move.cannotMove = cannotMove; return(move); }
/// <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 a list of movable pieces this turn.</summary> /// <param name="optionalJumping">Overrides the game's OptionalJumping parameter for the enumeration.</param> /// <returns>A list of pieces that can be moved this turn.</returns> public CheckersPiece[] EnumMovablePieces(bool optionalJumping) { if ((!isPlaying) && (winner == 0)) { throw new InvalidOperationException("Operation requires game to be playing."); } ArrayList movable = new ArrayList(); foreach (CheckersPiece piece in EnumPlayerPieces(turn)) { CheckersMove move = new CheckersMove(this, piece, false); if (move.EnumMoves(optionalJumping).Length != 0) { movable.Add(piece); } } return((CheckersPiece[])movable.ToArray(typeof(CheckersPiece))); }
/// <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>Stops a decided game or forces a game-in-progress to stop prematurely with no winner.</summary> public void Stop() { if (isReadOnly) { throw new InvalidOperationException("Game is read only."); } isPlaying = false; pieces.Clear(); for (int y = 0; y < BoardSize.Height; y++) { for (int x = 0; x < BoardSize.Width; x++) { board[x, y] = null; } } lastMove = null; winner = 0; turn = 0; if (GameStopped != null) { GameStopped(this, EventArgs.Empty); } }