/// <summary> /// Set the board's pawn layout directly from an array representing the locations of pawns. /// </summary> /// <param name="pawns">An array representing the locations of pawns, nulls where there is no pawn.</param> public void SetupPawns(Pawn[,] pawns) { int n = Size; if (!(pawns.GetLength(0) == n && pawns.GetLength(1) == n)) { throw new ArrayTypeMismatchException("The array containing the pawns must be [n,n] in size, where n is the board's current length/height."); } this.pawns = pawns; InvalidateLayout(); }
// Not really needed. public void AddPawn(Pawn pawn, int row, int column) { throw new NotImplementedException(); }
// Not going to be implemented yet. public void MovePawn(Pawn pawn, int rowTo, int columnTo) { throw new NotImplementedException(); //MovePawn(Board.GetRow(pawn), Board.GetColumn(pawn), rowTo, columnTo); }
// Maybe replace with goto void PostMoveCleanup(Pawn selectedPawn) { selectedPawn.Style = GetBasicPawnStyle(selectedPawn); startPos = null; targetPos = null; }
/// <summary> /// Using startPos and targetPos, try to move the pawn on the logic component's board. Handle the results and move the pawns on the UI if needed. /// </summary> void MakeMove() { Pawn selectedPawn = Board.GetPawn(startPos.row, startPos.column); IMoveResults results = Logic.MovePawn(startPos.row, startPos.column, targetPos.row, targetPos.column); if (!results.Success) { HighlightPossibleMoves(startPos.row, startPos.column); PostMoveCleanup(selectedPawn); return; } if (results.PawnsKilled.Count > 0) { foreach (IPawn p in results.PawnsKilled) { Board.RemovePawn(p.Row, p.Column); } } Board.MovePawn(startPos.row, startPos.column, targetPos.row, targetPos.column); // Checkers special attributes if (results is CheckersMoveResults) { var checkersResults = (CheckersMoveResults)results; if (checkersResults.BecameKing) { // Animate the pawn's size change. // Not neat, but better than implementing generic animations interface for this one event. ThicknessAnimation ta = new ThicknessAnimation(); ta.From = selectedPawn.Margin; selectedPawn.PawnType = PawnType.king; // Get the style for the now king-type pawn. Style newStyle = GetBasicPawnStyle(selectedPawn); // Create a dummy pawn and apply the new style on it, because getting a specific property's value directly from a Style is awkward. Pawn dummyPawn = new Pawn(); dummyPawn.Style = newStyle; Thickness endMargin = dummyPawn.Margin; ta.To = endMargin; ta.Duration = TimeSpan.FromMilliseconds(500); Storyboard sb = new Storyboard(); sb.FillBehavior = FillBehavior.Stop; sb.Children.Add(ta); Storyboard.SetTarget(ta, selectedPawn); Storyboard.SetTargetProperty(ta, new PropertyPath("Margin")); sb.Begin(); selectedPawn.Style = newStyle; } } if (results.GameOver) { PostMoveCleanup(selectedPawn); GameOver(this, new GameOverEventArgs(results.Winner)); return; } if (!results.TurnOver) { var moves = results.Path; startPos = moves[moves.Count-1]; } else { PostMoveCleanup(selectedPawn); TurnOver(this, new TurnOverEventArgs(Logic.Turn)); } }
/// <summary> /// Get the normal style for a pawn. /// </summary> /// <param name="pawn">The pawn whose default style is wanted.</param> /// <returns>The default style of the pawn.</returns> Style GetBasicPawnStyle(Pawn pawn) { try { return playerPawnStyles[pawn.Player][pawn.PawnType]; } catch (KeyNotFoundException e) { throw new KeyNotFoundException("No style supplied for the pawn of Player: " + pawn.Player + ", Type: " + pawn.PawnType + ".", e); } }
/// <summary> /// Get the pawn layout from Logic and set Board accordingly. /// </summary> void SetupPawns() { int n = Board.Size; IPawn[,] squares = Logic.PawnLayout(); Pawn[,] pawns = new Pawn[n, n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { IPawn logicalPawn = squares[i, j]; if (logicalPawn == null) { continue; } Pawn p = new Pawn(); p.Player = logicalPawn.Player; p.PawnType = logicalPawn.PawnType; p.Style = GetBasicPawnStyle(p); p.Click += HandlePawnClick; pawns[i, j] = p; } } Board.SetupPawns(pawns); }