/// <summary> /// Check puzzle is finished. /// </summary> /// <returns>A Task to check finish of puzzle asynchrously</returns> Task CheckFinished() { return(Task.Run(() => { bool finish = true; //check all puzzle square has original position for (int row = 0; row < (int)_level; row++) { for (int col = 0; col < (int)_level; col++) { PuzzleSquare square = _puzzleSquares[row, col]; if (square != null) { if (square.OriginalX != square.PositionX || square.OriginalY != square.PositionY) { //Puzzle is not completed. finish = false; break; } } } if (!finish) { break; } } //if all puzzle is match. create finish popup. if (finish) { Device.BeginInvokeOnMainThread(() => { DisplayFinishDialog(); }); _started = false; } })); }
/// <summary> /// Move one square to a specified direction. /// If the direct == Direction.UNKNOW, it will choose an available direction automatically. /// </summary> /// <param name="square">Puzzle square object</param> /// <param name="direct">The direction will move to</param> private void MoveBlock(PuzzleSquare square, Direction direct) { //Get square's current position. Position pos = new Position(square.PositionX, square.PositionY); if (direct == Direction.UNKNOW) { if (pos.X + 1 == _blankPos.X && pos.Y == _blankPos.Y) { direct = Direction.RIGHT; } else if (pos.X - 1 == _blankPos.X && pos.Y == _blankPos.Y) { direct = Direction.LEFT; } else if (pos.X == _blankPos.X && pos.Y + 1 == _blankPos.Y) { direct = Direction.DOWN; } else if (pos.X == _blankPos.X && pos.Y - 1 == _blankPos.Y) { direct = Direction.UP; } else { return; } } //Remove old image object from Grid. _puzzleGrid.Children.Remove(square); switch (direct) { case Direction.UP: pos.Y--; _blankPos.Y++; break; case Direction.DOWN: pos.Y++; _blankPos.Y--; break; case Direction.LEFT: pos.X--; _blankPos.X++; break; case Direction.RIGHT: pos.X++; _blankPos.X--; break; } _puzzleGrid.Children.Add(square, pos.X, pos.X + 1, pos.Y, pos.Y + 1); //replace blank to moved square. _puzzleSquares[_blankPos.Y, _blankPos.X] = null; _puzzleSquares[pos.Y, pos.X] = square; square.PositionX = pos.X; //store current x position square.PositionY = pos.Y; //store current y position if (_started) { //after block is moved, checking if puzzle is completed. //if puzzle is complete. display finish dialog. if (_blankPos.X == ((int)_level - 1) && _blankPos.Y == ((int)_level - 1)) { CheckFinished(); } } }
/// <summary> /// Add image blocks in puzzle view /// </summary> /// <param name="grid">The container Grid layout</param> /// <seealso cref="Grid"> private void CreatePuzzle(Grid grid) { int level = (int)_level; int imageSize = 225; int size = imageSize / level; string folder = ""; //Clear _puzzleSquares firstly int row = 0; int col = 0; //Clear puzzle grid grid.Children.Clear(); //Initialize PuzzleSquare for (row = 0; row < MAXNUM; row++) { for (col = 0; col < MAXNUM; col++) { _puzzleSquares[row, col] = null; } } //The blank block's position at the right bottom corner. _blankPos = new Position(level - 1, level - 1); PuzzleSquare square = null; if (level == 4) { folder = "4X4"; } else { folder = "5X5"; } for (row = 0; row < level; row++) { for (col = 0; col < level; col++) { //Does not add Image in blank block. if (row == _blankPos.Y && col == _blankPos.X) { break; } //Create new square and then add puzzle grid. square = new PuzzleSquare() { Source = folder + "/" + (row + 1).ToString() + "-" + (col + 1).ToString() + ".jpg", MinimumWidthRequest = (720 - 2 * 2 * level) / level, MinimumHeightRequest = (720 - 2 * 2 * level) / level, PositionX = col, PositionY = row, OriginalX = col, OriginalY = row, }; //Add click event handler square.Clicked += (s, e) => { //Extract press square from sender. PuzzleSquare clickedSquare = (PuzzleSquare)s; MoveBlock(clickedSquare, Direction.UNKNOW); }; //Add square to _puzzleSquares array _puzzleSquares[row, col] = square; //Add created Image object to Grid grid.Children.Add(square, col, col + 1, row, row + 1); } } }