/// <summary> /// Copy constructor. /// </summary> /// <param name="other">Prototype to copy.</param> public Square(Square other) { _x = other._x; _y = other._y; throw new NotImplementedException("NYI. need to deep copy links"); }
/// <summary> /// Initializes a player for the game start. /// </summary> /// <param name="id">Player ID.</param> /// <param name="fencesAvailable">How many fences available for the player.</param> /// <param name="startPosition">Player start position.</param> /// <param name="boardSize">Board size.</param> public Player(PlayerId id, int fencesAvailable, Square startPosition, IEnumerable<Square> goalPositions) { _playerId = id; _fencesAvailable = fencesAvailable; _position = startPosition; _goalPositions = goalPositions.ToArray(); }
internal JumpLink(Square from, Square via, Square to) : base(from, to) { if (!from.IsAdjacentTo(via) || !to.IsAdjacentTo(via)) { throw new InvalidOperationException("Squares should be adjacent."); } _via = via; }
/// <summary> /// /// </summary> /// <param name="newPosition"></param> public void MoveCurrentPlayer(Square newPosition) { if (!GameFinished) { Link link = _board.GetLinksFromSquare(CurrentPlayer.Position).Single(l => l.Squares.Contains(newPosition)); _board.MovePlayer(CurrentPlayer, link); GameFinished = CheckWinningConditions(); if (!GameFinished) { _currentPlayer = NextPlayer(); } } }
private Link GetStraitJumpLink(Square square, Link link) { Square target = link.LinkedSquare(square); // Check strait jump first int jumpX = target.X + (target.X - square.X); int jumpY = target.Y + (target.Y - square.Y); Square straitJump = target.Neighbours.FirstOrDefault(s => s.X == jumpX && s.Y == jumpY); if (straitJump == null) { return null; } MoveResult fromTarget = GetMoveResult(target, straitJump); switch (fromTarget) { case MoveResult.Succesfull: return new JumpLink(square, target, straitJump); case MoveResult.BlockedByFence: case MoveResult.BlockedByPlayer: return null; default: throw new InvalidOperationException("Unexpected move result."); } }
private void InitializeField(int size) { _squares = new Square[size * size]; var links = new List<Link>(2 * size * (size - 1)); for (int y = 0; y < _size; y++) { for (int x = 0; x < _size; x++) { int position = GetIndexFromPosition(x, y); _squares[position] = new Square(x, y); if (x > 0) { // Add horizontal link int neibourPosition = GetIndexFromPosition((x - 1), y); Link link = new Link(_squares[position], _squares[neibourPosition]); links.Add(link); _squares[position].AddLink(link); _squares[neibourPosition].AddLink(link); } if (y > 0) { // Add vertical link int neibourPosition = GetIndexFromPosition(x, y - 1); Link link = new Link(_squares[position], _squares[neibourPosition]); links.Add(link); _squares[position].AddLink(link); _squares[neibourPosition].AddLink(link); } } } _links = links; }
// Assumes the linked square is ocupied by player private IEnumerable<Link> GetJumpLinks(Square square, Link link) { // Jump links are used in the case one player stands in front of the other. // Jump links aren't presisted as they become stale quickly // Jumps can be made over a single player. // In case strait jump not possible because of the fences diagonal jumps can be made if aren't blocked by fences. Square target = link.LinkedSquare(square); Link straitJump = GetStraitJumpLink(square, link); if (straitJump != null) { yield return straitJump; yield break; } // handle diagonal jumps foreach (var l in GetDiagonalJumpLinks(square, link)) { yield return l; } }
private MoveResult GetMoveResult(Square from, Square to) { if (from.IsAdjacentTo(to)) { return GetMoveResult(from, from.Links.Single(l => l.LinkedSquare(from) == to)); } throw new InvalidOperationException("Jump cases should go via links."); }
/// <summary> /// /// </summary> /// <param name="square"></param> /// <returns></returns> public bool IsSquareOccupied(Square square) { return Players.Any(p => p.Position == square); }
private IEnumerable<Link> GetDiagonalJumpLinks(Square square, Link link) { Square target = link.LinkedSquare(square); int deltaX = target.X - square.X; int deltaY = target.Y - square.Y; int[] jumpDirection = { -1, 1 }; foreach (int direction in jumpDirection) { int jumpX = deltaX == 0 ? target.X + direction : target.X; int jumpY = deltaY == 0 ? target.Y + direction : target.Y; Square diagonalJump = target.Neighbours.FirstOrDefault(s => s.X == jumpX && s.Y == jumpY); if (diagonalJump == null) { continue; } MoveResult fromTarget = GetMoveResult(target, diagonalJump); switch (fromTarget) { case MoveResult.Succesfull: yield return new JumpLink(square, target, diagonalJump); break; case MoveResult.BlockedByFence: case MoveResult.BlockedByPlayer: break; default: throw new InvalidOperationException("Unexpected move result."); } } }
internal Link(Square square1, Square square2) { _squares[0] = square1; _squares[1] = square2; }
private Rectangle GetSquareRectangle(RectangleF canvasRectangle, int boardSize, Square square) { RectangleF rect = GetSquareRectangleF(canvasRectangle, boardSize, square); return new Rectangle((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height); }
/// <summary> /// Initializes a player for the game start. /// </summary> /// <param name="id">Player ID.</param> /// <param name="fencesAvailable">How many fences available for the player.</param> /// <param name="startPosition">Player start position.</param> /// <param name="boardSize">Board size.</param> public MovablePlayer(PlayerId id, int fencesAvailable, Square startPosition, IEnumerable<Square> goalPositions) : base(id, fencesAvailable, startPosition, goalPositions) { }
/// <summary> /// Moves player to the new position /// </summary> /// <param name="position">New position</param> protected void MoveTo(Square position) { _position = position; }
// check for null public bool IsAGoal(Square square) { return _goalPositions.Contains(square); }
private RectangleF GetSquareRectangleF(RectangleF canvasRectangle, int boardSize, Square square) { int row = square.Y; int column = square.X; float left = GetHorizontalPositionForLeftEdge(canvasRectangle, boardSize, column); float width = GetHorizontalPositionForRightEdge(canvasRectangle, boardSize, column) - left; float top = GetVerticalPositionForUpperEdge(canvasRectangle, boardSize, row); float height = GetVerticalPositionForLowerEdge(canvasRectangle, boardSize, row) - top; return new RectangleF(left, top, width, height); }
/// <summary> /// Returns if two squares are Adjacent to each other. /// </summary> /// <param name="other">other square.</param> public bool IsAdjacentTo(Square other) { return _links.Any(l => l.Squares.Contains(other)); }
/// <summary> /// Moves player to the new position /// </summary> /// <param name="position">New position</param> public new void MoveTo(Square position) { base.MoveTo(position); }
/// <summary> /// Get all links available from particular square including jump links. /// </summary> /// <param name="square"></param> /// <returns></returns> public IEnumerable<Link> GetLinksFromSquare(Square square) { foreach (Link link in square.Links) { MoveResult linkMoveResult = GetMoveResult(square, link); if (linkMoveResult == MoveResult.Succesfull) { yield return link; } if (linkMoveResult == MoveResult.BlockedByPlayer) { foreach (var jumpLink in GetJumpLinks(square, link)) { yield return jumpLink; } } } }
public Square LinkedSquare(Square square) { return _squares.Single(s => s != square); }
/// <summary> /// /// </summary> /// <param name="from"></param> /// <param name="link"></param> /// <returns></returns> public MoveResult GetMoveResult(Square from, Link link) { JumpLink jumpLink = link as JumpLink; if (jumpLink != null) { if (GetMoveResult(from, jumpLink.Via) != MoveResult.BlockedByPlayer) { return MoveResult.Invalid; } return GetMoveResult(jumpLink.Via, jumpLink.LinkedSquare(from)); } // Blocked by fence has higher priority than blocked by player so it goes first. if (Fences.Any(f => f.SplittedLinks.Contains(link))) { return MoveResult.BlockedByFence; } if (IsSquareOccupied(link.LinkedSquare(from))) { return MoveResult.BlockedByPlayer; } return MoveResult.Succesfull; }