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); }
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); } }