示例#1
0
        /// <summary> Найти пустой пазл среди соседних к текущему пазлу </summary>
        /// <param name="puzzleTile">Пазл для которого осуществляем поиск</param>
        /// <returns>Пустой соседний пазл или null</returns>
        private AbstractPuzzleTileFacade GetEmptyNeighbor(AbstractPuzzleTileFacade puzzleTile)
        {
            int currentRow = puzzleTile.CurrentCoordinates.Row;
            int currentCol = puzzleTile.CurrentCoordinates.Column;

            int topNeighborRow    = currentRow - 1;
            int bottomNeighborRow = currentRow + 1;
            int leftNeighborCol   = currentCol - 1;
            int rightNeighborCol  = currentCol + 1;

            AbstractPuzzleTileFacade emptyPuzzleTile = null;

            if (topNeighborRow >= 0 && virtualFieldOfPuzzles[topNeighborRow, currentCol].IsEpmty)
            {
                emptyPuzzleTile = virtualFieldOfPuzzles[topNeighborRow, currentCol];
            }
            else if (bottomNeighborRow < VIRTUAL_FIELD_SIZE && virtualFieldOfPuzzles[bottomNeighborRow, currentCol].IsEpmty)
            {
                emptyPuzzleTile = virtualFieldOfPuzzles[bottomNeighborRow, currentCol];
            }
            else if (leftNeighborCol >= 0 && virtualFieldOfPuzzles[currentRow, leftNeighborCol].IsEpmty)
            {
                emptyPuzzleTile = virtualFieldOfPuzzles[currentRow, leftNeighborCol];
            }
            else if (rightNeighborCol < VIRTUAL_FIELD_SIZE && virtualFieldOfPuzzles[currentRow, rightNeighborCol].IsEpmty)
            {
                emptyPuzzleTile = virtualFieldOfPuzzles[currentRow, rightNeighborCol];
            }

            return(emptyPuzzleTile);
        }
示例#2
0
 /// <summary> Заполнить виртуальное поле пазлов и инициализировать виртуальные координаты пазлов </summary>
 private void FillVirtualField()
 {
     virtualFieldOfPuzzles = new AbstractPuzzleTileFacade[VIRTUAL_FIELD_SIZE, VIRTUAL_FIELD_SIZE];
     for (int i = 0; i < VIRTUAL_FIELD_SIZE; i++)
     {
         for (int j = 0; j < VIRTUAL_FIELD_SIZE; j++)
         {
             int rowNum    = i;
             int columnNum = j;
             //Переводим координаты строки и столбца в индекс массива элементов
             int flatIndex = rowNum * 4 + columnNum;
             //Иницализируем виртуальные координаты
             AbstractPuzzleTileFacade currentPuzzleTile = AllPuzzleTiles[flatIndex];
             currentPuzzleTile.StartCoordinates   = new PuzzleVirtualCoordinates(rowNum, columnNum);
             currentPuzzleTile.CurrentCoordinates = currentPuzzleTile.StartCoordinates.Clone();
             //Сохраняем пазл на виртуальное поле
             virtualFieldOfPuzzles[rowNum, columnNum] = currentPuzzleTile;
             //Если текущий пазл не пустой
             if (!currentPuzzleTile.IsEpmty)
             {
                 //Привязываем обработку нажатия на пазл
                 currentPuzzleTile.ClickСontroller.OnClicked += PuzzleWasClicked;
             }
         }
     }
 }
示例#3
0
        /// <summary> Обработка нажатия на пазл </summary>
        /// <param name="puzzleTile">Пазл, по которому произошло нажатие</param>
        private void PuzzleWasClicked(AbstractPuzzleTileFacade puzzleTile)
        {
            virtualFieldLock.EnterReadLock();
            //Если состояние игры - заблокирована
            if (isLocked)
            {
                //То не обрабатываем нажатия на пазлы
                virtualFieldLock.ExitReadLock();
                return;
            }
            virtualFieldLock.ExitReadLock();

            var emptyPuzzleTile = GetEmptyNeighbor(puzzleTile);

            //Если среди соседних пазлов нет пустого
            if (emptyPuzzleTile == null)
            {
                //Завершаем обработку нажатия
                return;
            }

            //Иначе входим в цикл обмена местами нажатого пазла и соседнего пустого
            virtualFieldLock.EnterWriteLock();
            isLocked = true;
            virtualFieldLock.ExitWriteLock();

            //Привязываем обработчик завершения обмена местами пазлов
            puzzleTile.OnSwapEndedEvent += PuzzlesSwaped;
            //Начинаем обмен местами
            puzzleTile.SwapWithEmptyTile(emptyPuzzleTile);
        }
示例#4
0
        /// <summary> Обмен местами на виртуальной и визуальной доске двух пазлов </summary>
        private void SwapToPuzzles(AbstractPuzzleTileFacade firstPuzzle, AbstractPuzzleTileFacade secondPuzzle)
        {
            Vector3 firstPuzzleVector = firstPuzzle.transform.position;
            PuzzleVirtualCoordinates firstPuzzleCoordinates = firstPuzzle.CurrentCoordinates;

            firstPuzzle.transform.position = secondPuzzle.transform.position;
            firstPuzzle.CurrentCoordinates = secondPuzzle.CurrentCoordinates;

            secondPuzzle.transform.position = firstPuzzleVector;
            secondPuzzle.CurrentCoordinates = firstPuzzleCoordinates;

            virtualFieldOfPuzzles[GetPuzzleRow(firstPuzzle), GetPuzzleCol(firstPuzzle)]   = firstPuzzle;
            virtualFieldOfPuzzles[GetPuzzleRow(secondPuzzle), GetPuzzleCol(secondPuzzle)] = secondPuzzle;
        }
示例#5
0
        /// <summary> Настроить обработку события обмена мест с пустым пазлом </summary>
        /// <param name="otherPuzzleTile">Пустой пазл, с которым меняемся местами</param>
        private void SetupEventHandler(AbstractPuzzleTileFacade otherPuzzleTile)
        {
            //Экшены - обертки для подписки и одписки на события перемещения пустой ячейки
            Action <MovementEndedEvent> subscribeForFirstMoveEnded    = (sunscriber) => otherPuzzleTile.MoveController.OnNextMovementFinished += sunscriber;
            Action <MovementEndedEvent> unsubscribeFromFirstMoveEnded = (sunscriber) => otherPuzzleTile.MoveController.OnNextMovementFinished -= sunscriber;
            //Экшены - обертки для подписки и одписки на события перемещения текущей ячейки
            Action <MovementEndedEvent> subscribeForSecondMoveEnded    = (sunscriber) => this.MoveController.OnNextMovementFinished += sunscriber;
            Action <MovementEndedEvent> unsubscribeFromSecondMoveEnded = (sunscriber) => this.MoveController.OnNextMovementFinished -= sunscriber;

            //Создание хэндлера этих двух перемещений
            TwoEventAdapter.GetTwoMoveToSwipeAdapter()
            .BindFirst(subscribeForFirstMoveEnded, unsubscribeFromFirstMoveEnded)
            .BindSecond(subscribeForSecondMoveEnded, unsubscribeFromSecondMoveEnded)
            .BindFinal(RaiseOnSwapEnded(otherPuzzleTile));
        }
示例#6
0
        /// <summary> Обменяться местами с пустым пазлом </summary>
        /// <param name="otherPuzzleTile">Пустой пазл, с которым необходимо обменяться местами</param>
        public override void SwapWithEmptyTile(AbstractPuzzleTileFacade otherPuzzleTile)
        {
            if (!otherPuzzleTile.IsEpmty)
            {
                throw new Exception("Невозможно обменяться местами с непустой ячейкой");
            }

            SetupEventHandler(otherPuzzleTile);

            Vector3 emptyPuzzleDestination = this.transform.position;
            Vector3 thisPuzzleDestination  = otherPuzzleTile.transform.position;

            this.MoveController.MoveToPoint(thisPuzzleDestination);
            otherPuzzleTile.MoveController.MoveToPoint(emptyPuzzleDestination);
        }
示例#7
0
 /// <summary> Обработка завершения обмена местами пазлов по нажатию на один из них </summary>
 private void PuzzlesSwaped(AbstractPuzzleTileFacade notEmptyPuzzle, AbstractPuzzleTileFacade emptyPuzzle)
 {
     try
     {
         //обновляем координаты на виртуальном поле
         virtualFieldOfPuzzles[GetPuzzleRow(notEmptyPuzzle), GetPuzzleCol(notEmptyPuzzle)] = notEmptyPuzzle;
         virtualFieldOfPuzzles[GetPuzzleRow(emptyPuzzle), GetPuzzleCol(emptyPuzzle)]       = emptyPuzzle;
         UiManager.StepsCount++;
         CheckIsItWin();
     }
     finally
     {
         //высвобождаем флаг
         virtualFieldLock.EnterWriteLock();
         isLocked = isWin; //isLocked = false, только если не была завершена игра этим ходом
         virtualFieldLock.ExitWriteLock();
     }
 }
示例#8
0
        /// <summary> Вызвать евент об окончании обмена мест с пустым пазлом </summary>
        private Action RaiseOnSwapEnded(AbstractPuzzleTileFacade otherPuzzleTile)
        {
            Action newOnSwaped = () =>
            {
                //После завершения физического перемещения, необходимо обновить координаты
                PuzzleVirtualCoordinates emptyPuzzleCoordinates = otherPuzzleTile.CurrentCoordinates;
                otherPuzzleTile.CurrentCoordinates = this.CurrentCoordinates;
                this.CurrentCoordinates            = emptyPuzzleCoordinates;

                //Вызываем соответствующее событие
                if (OnSwapEndedEvent != null)
                {
                    OnSwapEndedEvent.Invoke(this, otherPuzzleTile);
                    OnSwapEndedEvent = null;
                }
            };

            return(newOnSwaped);
        }
示例#9
0
        /// <summary> Перемешать пазлы </summary>
        private void ShuffleVirtualField()
        {
            int maxPuzzleIndex = PUZZLES_COUNT;

            //На последнем месте на виртуальном поле всегда должен стоять пустой пазл
            AbstractPuzzleTileFacade lastPuzzleTile = virtualFieldOfPuzzles[VIRTUAL_FIELD_SIZE - 1, VIRTUAL_FIELD_SIZE - 1];

            if (!lastPuzzleTile.IsEpmty)
            {
                AbstractPuzzleTileFacade emptyPuzzleTile = AllPuzzleTiles.First(puzzle => puzzle.IsEpmty);
                SwapToPuzzles(lastPuzzleTile, emptyPuzzleTile);
            }
            //В одномерном списке пазлов пустой так же должен стоять на последнем месте
            lastPuzzleTile = AllPuzzleTiles.Last();
            if (!lastPuzzleTile.IsEpmty)
            {
                for (int i = 0; i < PUZZLES_COUNT; i++)
                {
                    if (AllPuzzleTiles[i].IsEpmty)
                    {
                        AllPuzzleTiles[PUZZLES_COUNT - 1] = AllPuzzleTiles[i];
                        AllPuzzleTiles[i] = lastPuzzleTile;
                        break;
                    }
                }
            }
            //т.к. последний пазл пустой, его мы трогать не будем - уменьшаем максимальный индекс элементов, которые будем перемешивать
            maxPuzzleIndex--;

            Random random = new Random();

            //для всех оставшихся пазлов - 1
            for (int oldIndex = 0; oldIndex < maxPuzzleIndex - 1; oldIndex++)
            {
                //определяем новый индекс, больший, чем текущий
                int newIndex = random.Next(oldIndex + 1, maxPuzzleIndex);

                //меняем местами, соответствующие элементы пазла
                SwapToPuzzles(AllPuzzleTiles[oldIndex], AllPuzzleTiles[newIndex]);
            }
        }
示例#10
0
 /// <summary> Обменяться местами с пустым пазлом </summary>
 /// <param name="otherPuzzleTile">Пустой пазл, с которым необходимо обменяться местами</param>
 public abstract void SwapWithEmptyTile(AbstractPuzzleTileFacade otherPuzzleTile);
示例#11
0
 /// <summary> Номер столбца из текущей координаты пазла </summary>
 private int GetPuzzleCol(AbstractPuzzleTileFacade puzzleTile)
 {
     return(puzzleTile.CurrentCoordinates.Column);
 }
示例#12
0
 /// <summary> Номер строки из текущей координаты пазла </summary>
 private int GetPuzzleRow(AbstractPuzzleTileFacade puzzleTile)
 {
     return(puzzleTile.CurrentCoordinates.Row);
 }