Ejemplo n.º 1
0
        /// <summary>
        /// Initializes the Fence that splits 4 adjacent squares that from a square into 2 pairs.
        /// </summary>
        /// <param name="link1"></param>
        /// <param name="link2"></param>
        public Fence(Link link1, Link link2)
        {
            // Check if they are null
            if (link1.Squares.Any(s1 => link2.Squares.All(s2 => !s1.IsAdjacentTo(s2))))
            {
                throw new InvalidOperationException("Squares should be adjacent");
            }

            _splittedLinks[0] = link1;
            _splittedLinks[1] = link2;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="link1"></param>
        /// <param name="link2"></param>
        /// <returns></returns>
        public FenceSetResult GetFenceSetResult(Link link1, Link link2)
        {
            // validate if squares are adjacent and no fence available for jump links
            if ((link1 is JumpLink) || (link2 is JumpLink) || !link1.Squares.All(s1 => link2.Squares.Any(s2 => s1.IsAdjacentTo(s2))))
            {
                return FenceSetResult.Invalid;
            }

            var allFencesLinks = _fences.SelectMany(f => f.SplittedLinks);
            if (allFencesLinks.Any(l => l == link1 || l == link2))
            {
                return FenceSetResult.OverlappedWithOtherFence;
            }

            // validate that fence is not crossing another fence (situation when all 4 squares match)
            if (_fences.Any(f => FencesCross(f, link1, link2)))
            {
                return FenceSetResult.CrossedAnotherFence;
            }

            // validate that the path to goal exists. For that move shortest path logic to the board.
            if (!Players.All(p => CanReachDestination(p)))
            {
                return FenceSetResult.BlockedPlayerGoal;
            }

            return FenceSetResult.Succesfull;
        }
Ejemplo n.º 3
0
        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;
        }
Ejemplo n.º 4
0
        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.");
            }
        }
Ejemplo n.º 5
0
        // 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;
            }
        }
Ejemplo n.º 6
0
        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.");
                }
            }
        }
Ejemplo n.º 7
0
 private bool FencesCross(Fence f, Link link1, Link link2)
 {
     HashSet<Square> squares = new HashSet<Square>(f.SplittedLinks.SelectMany(link => link.Squares).Concat(link1.Squares).Concat(link2.Squares));
     return squares.Count == 4;
 }
Ejemplo n.º 8
0
        /// <summary>
        /// Sets fence to separate 2 pairs of squares.
        /// </summary>
        /// <param name="firstSplit">Fist pair of split squares.</param>
        /// <param name="secondSplit">Second pair of split squares.</param>
        protected void SetFence(Link first, Link second)
        {
            if (_fences.Count == _maxFences)
            {
                throw new InvalidOperationException("All fences already used.");
            }

            // Check for NULL

            //TODO: Make sure that the fence is not splitting existing fence into 2 pieces
            // for this check if the square is not crossed already by existing fences

            _fences.Add(new Fence(first, second));
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Moves player in by the link. 
        /// </summary>
        /// <param name="player"></param>
        /// <param name="link"></param>
        protected void MovePlayer(Player player, Link link)
        {
            Square currentPosition = player.Position;

            // Validate current -> desired is not bloced by fence and isn't occupied
            if (GetMoveResult(currentPosition, link) != MoveResult.Succesfull)
            {
                throw new InvalidOperationException("Can not jump over the fence or step on the other player.");
            }

            Square newPosition = link.LinkedSquare(currentPosition);

            ((MovablePlayer)player).MoveTo(newPosition);
        }
Ejemplo n.º 10
0
        /// <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;
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Adds a link to other adjacent node.
        /// </summary>
        /// <param name="link">The link.</param>
        internal void AddLink(Link link)
        {
            // handle null
            if (!link.Squares.Contains(this))
            {
                throw new InvalidOperationException("Link doesn't connect to current square.");
            }

            _links.Add(link);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="link"></param>
        public void MoveCurrentPlayer(Link link)
        {
            // check link is not null

            if (!GameFinished)
            {
                if (!link.Squares.Contains(CurrentPlayer.Position))
                {
                    throw new InvalidOperationException("Invalid link provided.");
                }

                Square target = link.LinkedSquare(CurrentPlayer.Position);
                _board.MovePlayer(CurrentPlayer, link);

                GameFinished = CheckWinningConditions();
                if (!GameFinished)
                {
                    _currentPlayer = NextPlayer();
                }
            }
        }
Ejemplo n.º 13
0
 /// <summary>
 /// Sets fence to separate 2 pairs of squares.
 /// </summary>
 /// <param name="firstSplit">Fist split link.</param>
 /// <param name="secondSplit">Second split link.</param>
 internal new void SetFence(Link firstLink, Link secondLink)
 {
     base.SetFence(firstLink, secondLink);
 }
Ejemplo n.º 14
0
 /// <summary>
 /// Moves player by the link.
 /// </summary>
 internal new void MovePlayer(Player player, Link link)
 {
     base.MovePlayer(player, link);
 }
Ejemplo n.º 15
0
 private void ValidateFence(Link link1, Link link2)
 {
     switch (_board.GetFenceSetResult(link1, link2))
     {
         case FenceSetResult.Succesfull:
             break;
         case FenceSetResult.OverlappedWithOtherFence:
             throw new InvalidOperationException("Can not set a fence where another is set already.");
         case FenceSetResult.CrossedAnotherFence:
             throw new InvalidOperationException("Fences couldn't cross each other.");
         case FenceSetResult.BlockedPlayerGoal:
             throw new InvalidOperationException("Players should always be able to reach their destination.");
         default:
             throw new InvalidOperationException("Invalid links provided");
     }
 }