/// <summary> /// Find Block Pair /// </summary> /// <param name="id"></param> /// <returns></returns> public Tuple FindBlockPair(int id) { Tuple tuple = new Tuple(this); for (int j = 1; j < Model.TOT_BLOCK_CNT_Y - 1; ++j) { for (int i = 1; i < Model.TOT_BLOCK_CNT_X - 1; ++i) { if (_map[i][j].GetImageId() == id) { tuple.Select(new Position(i, j)); if (tuple.IsTuple()) { return(tuple); } } } } return(null); }
/// <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> /// Get binary tuple of start and end positions given current position by expanding vertically /// </summary> /// <param name="curPos">Current position</param> /// <param name="grid">Grid</param> /// <param name="curType">Current block type</param> /// <returns></returns> private Tuple _expandVertical(Position curPos, Grid grid, int curType) { int startPos, endPos; int i, j; i = curPos.X; Tuple tuple = new Tuple(grid); // From current to upmost startPos = curPos.Y; j = startPos - 1; while (j >= 0) { Block curExploredBlock = grid.GetBlock(new Position(i, j)); if (curExploredBlock.IsNull()) { // Null block can be passed startPos = j; } else if (curExploredBlock.GetImageId() == curType) { // Block with same type can be passed startPos = j; } else { // Cannot passed, terminated break; } --j; } // From current to downmost endPos = curPos.Y; j = endPos + 1; while (j < Model.TOT_BLOCK_CNT_Y) { Block curExploredBlock = grid.GetBlock(new Position(i, j)); if (curExploredBlock.IsNull()) { // Null block can be passed endPos = j; } else if (curExploredBlock.GetImageId() == curType) { // Block with same type can be passed endPos = j; } else { // Cannot passed, terminated break; } ++j; } bool ret = true; ret = ret && tuple.Select(new Position(i, startPos)); ret = ret && tuple.Select(new Position(i, endPos)); if (!ret) { throw new Exception(); } return(tuple); }
/// <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); }
// =================================================== Game Internal Logic Processing Functions =================================================== /// <summary> /// Get binary tuple of start and end positions given current position by expanding horizontally /// </summary> /// <param name="curPos">Current position</param> /// <param name="grid">Grid</param> /// <param name="curType">Current block type</param> /// <returns></returns> private Tuple _expandHorizontal(Position curPos, Grid grid, int curType) { int startPos, endPos; int i, j; j = curPos.Y; Tuple tuple = new Tuple(grid); // From current to leftmost startPos = curPos.X; i = startPos - 1; while (i >= 0) { Block curExploredBlock = grid.GetBlock(new Position(i, j)); if (curExploredBlock.IsNull()) { // Null block can be passed startPos = i; } else if (curExploredBlock.GetImageId() == curType) { // Block with same type can be passed startPos = i; } else { // Cannot passed, terminated break; } --i; } // From current to rightmost endPos = curPos.X; i = endPos + 1; while (i < Model.TOT_BLOCK_CNT_X) { Block curExploredBlock = grid.GetBlock(new Position(i, j)); if (curExploredBlock.IsNull()) { // Null block can be passed endPos = i; } else if (curExploredBlock.GetImageId() == curType) { // Block with same type can be passed endPos = i; } else { // Cannot passed, terminated break; } ++i; } bool ret = true; ret = ret && tuple.Select(new Position(startPos, j)); ret = ret && tuple.Select(new Position(endPos, j)); if (!ret) { throw new Exception(); } return(tuple); }