Exemple #1
0
        protected override bool Update()
        {
            // Convert Next
            Tip   tip      = _model.GetTip(); // Get raw Tip
            Tuple tipTuple = tip.Tuple;

            _model.AcquireResourceMutex(Model.Model.MutexType.TIP);
            if (tipTuple == null)
            {
                // No path node existed, release & return
                _model.ReleaseResourceMutex(Model.Model.MutexType.TIP);
                return(false);
            }
            if (tip.IsActive == false)
            {
                // Tip is not activated, release & return
                _model.ReleaseResourceMutex(Model.Model.MutexType.TIP);
                return(false);
            }
            // Convert
            _pairList    = new Point[2];
            _pairList[0] = new Point(tipTuple.GetFirst().X, tipTuple.GetFirst().Y);
            _pairList[1] = new Point(tipTuple.GetSecond().X, tipTuple.GetSecond().Y);
            _model.ReleaseResourceMutex(Model.Model.MutexType.TIP);

            return(true);
        }
        /// <summary>
        /// Check is there a path by give line segment
        /// </summary>
        /// <param name="line"></param>
        /// <param name="grid"></param>
        /// <returns></returns>
        private bool _isExistedPath(Tuple line, Grid grid)
        {
            bool     isHorizontalLine = _isHorizontal(line);
            Position start            = line.GetFirst();
            Position end = line.GetSecond();

            if (isHorizontalLine)
            {
                // Horizontal Line
                for (int i = start.X; i <= end.X; ++i)
                {
                    if (!grid.GetBlock(new Position(i, start.Y)).IsNull())
                    {
                        return(false);
                    }
                }
            }
            else
            {
                // Vertical Line
                for (int i = start.Y; i <= end.Y; ++i)
                {
                    if (!grid.GetBlock(new Position(start.X, i)).IsNull())
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
Exemple #3
0
        public override void Paint(Graphics g)
        {
            // Determine the game state
            if (_model.GetState() == Model.Model.GameState.PLAYING)
            {
                // Paint all blocks
                Block[][] map = _model.GetMap();
                for (int i = 1; i <= 10; ++i)
                {
                    for (int j = 1; j <= 8; ++j)
                    {
                        _paintBlock(g, i, j, map[i][j].GetImageId());
                    }
                }

                // Paint boarder of selected blocks
                Tuple    tuple     = _model.GetSelectedBlocksTuple();
                Position firstPos  = tuple.GetFirst();
                Position secondPos = tuple.GetSecond();
                if (firstPos != null)
                {
                    PaintBoarder(g, _boarderPen, firstPos.X, firstPos.Y);
                }
                if (secondPos != null)
                {
                    PaintBoarder(g, _boarderPen, secondPos.X, secondPos.Y);
                }
            }
        }
        /// <summary>
        /// Find a Block Pair that can be merged
        /// </summary>
        /// <returns></returns>
        private Tuple _findMergableBlockPair()
        {
            HashSet <int> remainedBlockPair = _grid.GetAllRemaindBlockID();

            foreach (int id in remainedBlockPair)
            {
                Tuple tuple = _grid.FindBlockPair(id);
                if (tuple != null)
                {
                    Position   intersection;
                    Position[] intersections;
                    Position   startPos = tuple.GetFirst();
                    Position   endPos   = tuple.GetSecond();
                    Block      start    = _grid.GetBlock(startPos);
                    Block      end      = _grid.GetBlock(endPos);
                    // Check
                    // Expand vertically and horizontally
                    Tuple hStartTuple = _expandHorizontal(startPos, _grid, start.GetImageId());
                    Tuple vStartTuple = _expandVertical(startPos, _grid, start.GetImageId());
                    Tuple hEndTuple   = _expandHorizontal(endPos, _grid, end.GetImageId());
                    Tuple vEndTuple   = _expandVertical(endPos, _grid, end.GetImageId());
                    // #1 No turing
                    if (_isIntersect(hStartTuple, hEndTuple, out intersection))
                    {
                        return(tuple);
                    }
                    if (_isIntersect(hStartTuple, hEndTuple, out intersection))
                    {
                        return(tuple);
                    }
                    // #2 Turing once
                    if (_isIntersect(hStartTuple, vEndTuple, out intersection))
                    {
                        return(tuple);
                    }
                    if (_isIntersect(vStartTuple, hEndTuple, out intersection))
                    {
                        return(tuple);
                    }
                    // #3 Turing twice
                    if (_isTuringTwice(
                            hStartTuple,
                            vStartTuple,
                            hEndTuple,
                            vEndTuple,
                            _grid,
                            out intersections
                            ))
                    {
                        return(tuple);
                    }
                }
            }
            return(null);
        }
        /// <summary>
        /// Determine given line is horizontal line or vertical
        /// </summary>
        /// <param name="line">Tuple of line</param>
        /// <returns></returns>
        private bool _isHorizontal(Tuple line)
        {
            Position first  = line.GetFirst();
            Position second = line.GetSecond();

            if (first.X == second.X)
            {
                return(false);
            }
            else if (first.Y == second.Y)
            {
                return(true);
            }
            throw new Exception();
        }
        /// <summary>
        /// Mouse Left Click Handler For Game Round
        /// </summary>
        /// <param name="xMouse"></param>
        /// <param name="yMouse"></param>
        public void GameRoundLeftClickHandler(int xMouse, int yMouse)
        {
            // Check the game state
            if (_gameState != GameState.PLAYING)
            {
                return;
            }

            // Select a block
            int      x             = xMouse / (Model.BLOCK_SIZE_X + Model.BLOCK_MARGIN);
            int      y             = yMouse / (Model.BLOCK_SIZE_Y + Model.BLOCK_MARGIN);
            Position blockPosition = new Position(x, y);

            // Check selected block is valid
            if (_grid.GetBlock(blockPosition).IsNull())
            {
                return;
            }
            // Check tuple is selectable
            if (!_tuple.Select(blockPosition))
            {
                return;
            }

            // Check is connected AND required to merge
            if (_tuple.IsTuple())
            {
                Position startPos = _tuple.GetFirst();
                Position endPos   = _tuple.GetSecond();
                _tuple.Clear(); // Clear tuple

                if (_isConnected(startPos, endPos, _grid))
                {
                    // Connected, need to be merged
                    _grid.Merge(startPos, endPos);

                    _score.Merged();
                    _sePlayer.Merged(); // Merged SE

                    // Goto check game end
                    if (_gameEnd())
                    {
                        return;
                    }

                    // Check is there any block can be merged
                    AcquireResourceMutex(MutexType.TIP);
                    _mergableTuple       = new Tip();
                    _mergableTuple.Tuple = _findMergableBlockPair();
                    while (_mergableTuple.Tuple == null)
                    {
                        _grid.Randomize();
                        _sePlayer.Refresh(); // Refresh SE
                        _mergableTuple.Tuple = _findMergableBlockPair();
                    }
                    ReleaseResourceMutex(MutexType.TIP);
                }
                else
                {
                    _score.ComboInterrupted();
                    _sePlayer.Failed(); // Failed SE
                }
            }
            else
            {
                _sePlayer.Clicked(); // Click SE
            }
        }
        /// <summary>
        /// Check is there a path with 2 turning points
        /// </summary>
        /// <param name="hStartTuple"></param>
        /// <param name="vStartTuple"></param>
        /// <param name="hEndTuple"></param>
        /// <param name="vEndTuple"></param>
        /// <param name="grid"></param>
        /// <param name="intersections"></param>
        /// <returns></returns>
        private bool _isTuringTwice(
            Tuple hStartTuple,
            Tuple vStartTuple,
            Tuple hEndTuple,
            Tuple vEndTuple,
            Grid grid,
            out Position[] intersections)
        {
            Tuple lineSegment;

            intersections = null;

            // Both horizontal lines - Base: hStartTuple
            Position hStartA = hStartTuple.GetFirst();
            Position hStartB = hStartTuple.GetSecond();
            Position hEndA   = hEndTuple.GetFirst();
            Position hEndB   = hEndTuple.GetSecond();

            // Validation
            if (hStartA.X > hStartB.X)
            {
                throw new Exception();
            }
            if (hEndA.Y > hEndB.Y)
            {
                throw new Exception();
            }
            // Enumerate all possible line segments between lines: hStart and hEnd
            lineSegment = new Tuple(grid);
            for (int i = hStartA.X; i <= hStartB.X; ++i)
            {
                lineSegment.Clear();
                if (i >= hEndA.X && i <= hEndB.X)
                {
                    // Existed that path
                    if (hStartA.Y <= hEndA.Y)
                    {
                        // hStartA is upper line
                        lineSegment.Select(new Position(i, hStartA.Y));
                        lineSegment.Select(new Position(i, hEndA.Y));
                    }
                    else
                    {
                        // hEndA is upper line
                        lineSegment.Select(new Position(i, hEndA.Y));
                        lineSegment.Select(new Position(i, hStartA.Y));
                    }
                    // Check this line segment is a valid path
                    if (_isExistedPath(lineSegment, grid))
                    {
                        intersections    = new Position[2];
                        intersections[0] = lineSegment.GetFirst();
                        intersections[1] = lineSegment.GetSecond();
                        return(true);
                    }
                }
            }

            // Both vertical lines - Base: vStartTuple
            Position vStartA = vStartTuple.GetFirst();
            Position vStartB = vStartTuple.GetSecond();
            Position vEndA   = vEndTuple.GetFirst();
            Position vEndB   = vEndTuple.GetSecond();

            // Validation
            if (vStartA.X > vStartB.X)
            {
                throw new Exception();
            }
            if (vEndA.Y > vEndB.Y)
            {
                throw new Exception();
            }
            // Enumerate all possible line segments between lines: vStart and vEnd
            lineSegment = new Tuple(grid);
            for (int i = vStartA.Y; i <= vStartB.Y; ++i)
            {
                lineSegment.Clear();
                if (i >= vEndA.Y && i <= vEndB.Y)
                {
                    // Existed that path
                    if (vStartA.X <= vEndA.X)
                    {
                        // vStartA is left line
                        lineSegment.Select(new Position(vStartA.X, i));
                        lineSegment.Select(new Position(vEndA.X, i));
                    }
                    else
                    {
                        // vEndA is left line
                        lineSegment.Select(new Position(vEndA.X, i));
                        lineSegment.Select(new Position(vStartA.X, i));
                    }
                    // Check this line segment is a valid path
                    if (_isExistedPath(lineSegment, grid))
                    {
                        intersections    = new Position[2];
                        intersections[0] = lineSegment.GetFirst();
                        intersections[1] = lineSegment.GetSecond();
                        return(true);
                    }
                }
            }

            return(false);
        }
        /// <summary>
        /// Check intersection between 2 lines
        /// </summary>
        /// <param name="lineA">Line A</param>
        /// <param name="lineB">Line B</param>
        /// <param name="intersection">Intersection point</param>
        /// <returns></returns>
        private bool _isIntersect(Tuple lineA, Tuple lineB, out Position intersection)
        {
            intersection = null;
            bool     isHorizontalLineA = _isHorizontal(lineA);
            bool     isHorizontalLineB = _isHorizontal(lineB);
            Position startA            = lineA.GetFirst();
            Position endA   = lineA.GetSecond();
            Position startB = lineB.GetFirst();
            Position endB   = lineB.GetSecond();

            // Validation
            if (startA.X > endA.X)
            {
                throw new Exception();
            }
            if (startA.Y > endA.Y)
            {
                throw new Exception();
            }
            if (startB.X > endB.X)
            {
                throw new Exception();
            }
            if (startB.Y > endB.Y)
            {
                throw new Exception();
            }

            if (isHorizontalLineA == isHorizontalLineB)
            {
                // Same direction
                if (isHorizontalLineA)
                {
                    // Horizontally - Y is fixed, X is varying
                    if (startA.Y != startB.Y)
                    {
                        return(false);                      // Parallel but not overlap
                    }
                    // On the same line
                    if (startA.X <= startB.X && endA.X >= startB.X)
                    {
                        intersection = new Position(startB.X, startB.Y);
                        return(true);
                    }
                    else if (startA.X <= endB.X && endA.X >= endB.X)
                    {
                        intersection = new Position(endB.X, endB.Y);
                        return(true);
                    }
                    return(false);
                }
                else
                {
                    // Vertically - X is fixed, Y is varying
                    if (startA.X != startB.X)
                    {
                        return(false);                      // Parallel but not overlap
                    }
                    // On the same line
                    if (startA.Y <= startB.Y && endA.Y >= startB.Y)
                    {
                        intersection = new Position(startB.X, startB.Y);
                        return(true);
                    }
                    else if (startA.Y <= endB.Y && endA.Y >= endB.Y)
                    {
                        intersection = new Position(endB.X, endB.Y);
                        return(true);
                    }
                    return(false);
                }
            }
            else
            {
                // Different directions
                if (isHorizontalLineA == false)
                {
                    // Line A is Vertical, Line B is Horizontal
                    intersection = new Position(startA.X, startB.Y);
                }
                else
                {
                    // Line A is Horizontal, Line B is Vertical
                    intersection = new Position(startB.X, startA.Y);
                }
                // Check the intersection is on both lines
                if (!(startA.X <= intersection.X && endA.X >= intersection.X))
                {
                    return(false);
                }
                if (!(startB.X <= intersection.X && endB.X >= intersection.X))
                {
                    return(false);
                }
                if (!(startA.Y <= intersection.Y && endA.Y >= intersection.Y))
                {
                    return(false);
                }
                if (!(startB.Y <= intersection.Y && endB.Y >= intersection.Y))
                {
                    return(false);
                }
                return(true);
            }
        }