bool SwapBlank()

in Games/Fifteen/GamePage.xaml.cs [206:298]


        bool SwapBlank(int row, int col)
        {
            //Prevent tile slides once puzzle is solved
            if (DialogGrid.Visibility == Visibility.Visible || _gameOver)
            {
                return false;
            }

            if (!((((row == _blankRow - 1) || (row == _blankRow + 1)) && (col == _blankCol)) ||
                 (((col == _blankCol - 1) || (col == _blankCol + 1)) && (row == _blankRow))))
            {
                return false;
            }
            GazeInput.DwellFeedbackProgressBrush = new SolidColorBrush(Colors.Transparent);

            _animationActive = true;
            GazeInput.SetInteraction(GameGrid, Interaction.Disabled);
            //Slide button visual
            Button btn = _buttons[row, col];
            Button blankBtn = _buttons[_blankRow, _blankCol];

            //Get Visuals for the selected button that is going to appear to slide and for the blank button
            var btnVisual = ElementCompositionPreview.GetElementVisual(btn);
            var compositor = btnVisual.Compositor;
            var blankBtnVisual = ElementCompositionPreview.GetElementVisual(blankBtn);

            var easing = compositor.CreateLinearEasingFunction();

            if (_slideBatchAnimation != null)
            {
                _slideBatchAnimation.Completed -= SlideBatchAnimation_Completed;
                _slideBatchAnimation.Dispose();
            }

            _slideBatchAnimation = compositor.CreateScopedBatch(CompositionBatchTypes.Animation);
            _slideBatchAnimation.Completed += SlideBatchAnimation_Completed;

            //Create an animation to first move the blank button with its updated contents to
            //instantly appear in the position position of the selected button
            //then slide that button back into its original position
            var slideAnimation = compositor.CreateVector3KeyFrameAnimation();
            slideAnimation.InsertKeyFrame(0f, btnVisual.Offset);
            slideAnimation.InsertKeyFrame(1f, blankBtnVisual.Offset, easing);
            slideAnimation.Duration = TimeSpan.FromMilliseconds(500);
            
            //Apply the slide animation to the blank button            
            blankBtnVisual.StartAnimation(nameof(btnVisual.Offset), slideAnimation);
            
            //Pulse after slide if sliding to correct position
            if (((_blankRow * _boardSize) + _blankCol + 1).ToString() == btn.Content.ToString())
            {               
                var springSpeed = 50;

                blankBtnVisual.CenterPoint = new System.Numerics.Vector3((float)blankBtn.ActualWidth / 2, (float)blankBtn.ActualHeight / 2, 0f);

                var scaleAnimation = compositor.CreateSpringVector3Animation();
                scaleAnimation.InitialValue = new System.Numerics.Vector3(0.9f, 0.9f, 0f);
                scaleAnimation.FinalValue = new System.Numerics.Vector3(1.0f, 1.0f, 0f);
                scaleAnimation.DampingRatio = 0.4f;
                scaleAnimation.Period = TimeSpan.FromMilliseconds(springSpeed);
                scaleAnimation.DelayTime = TimeSpan.FromMilliseconds(500);

                blankBtnVisual.StartAnimation(nameof(blankBtnVisual.Scale), scaleAnimation);
            }

            _slideBatchAnimation.End();

            //Swap content of the selected button with the blank button and clear the selected button
            _buttons[_blankRow, _blankCol].Content = _buttons[row, col].Content;
            _buttons[row, col].Content = "";
            _blankRow = row;
            _blankCol = col;


            //Note there is some redunancy in the following settings that corrects the UI at board load as well as tile slide 
            //Force selected button to the bottom and the blank button to the top
            Canvas.SetZIndex(btn, -_boardSize);
            Canvas.SetZIndex(blankBtn, 0);

            //Update the background colors of the two buttons to reflect their new condition
            btn.Background = _blankTileBrush;
            blankBtn.Background = _solidTileBrush;

            //Update the visibility to collapse the selected button that is now blank
            btn.Visibility = Visibility.Collapsed;
            blankBtn.Visibility = Visibility.Visible;

            //Disable eye control for the new empty button so that there are no inappropriate dwell indicators
            GazeInput.SetInteraction(blankBtn, Interaction.Inherited);          
            GazeInput.SetInteraction(btn, Interaction.Disabled);

            return true;
        }