Beispiel #1
0
        /// <summary>
        /// Попытка хода игрока
        /// </summary>
        /// <param name="newCellValue">Ячейка с новым значением</param>
        /// <param name="winnerId">Если в результате этого хода определился игрок, возвращаем его Id</param>
        /// <returns>true, если этот ход может быть совершен, иначе false</returns>
        public bool TrySetValue(CSudokuCell newCellValue, out int?winnerId)
        {
            winnerId = null;
            if (newCellValue.X < 0 || newCellValue.X > cellGrid.GetUpperBound(0) ||
                newCellValue.Y < 0 || newCellValue.Y > cellGrid.GetUpperBound(1))
            {
                return(false);
            }

            // Определение в серверной таблице изменяемой ячейки по координатам
            CSudokuCell serverCell = cellGrid[newCellValue.X, newCellValue.Y];

            if (serverCell.IsTask)
            {
                // Если эта ячейка является условием, игнорируем запрос на её изменение
                return(false);
            }

            // Нельзя допустить, чтобы два хода произошли одновременно
            lock (cellGrid)
            {
                // Можно поставить значение в ошибочную ячейку, или в пустую или ту, в которой значение было установлено этим же игроком, в противном случае ход не происходит
                if (serverCell.Error ||
                    null == serverCell.Owner ||
                    newCellValue.Owner == serverCell.Owner)
                {
                    if (newCellValue.Value == 0)
                    {
                        // Если игрок стирает значение в ячейке, она вновь становится "ничьей"
                        serverCell.Owner = null;
                        serverCell.Value = 0;
                    }
                    else
                    {
                        // В ячейку поставлено реальное значение, она помечается занятой этим игроком
                        serverCell.Owner = newCellValue.Owner;
                        serverCell.Value = newCellValue.Value;

                        if (TestForWin())
                        {
                            // Игра окончена, победитель определён
                            winnerId = newCellValue.Owner;
                        }
                    }

                    // Пометка ошибочных ячеек: тех, которые имеют значение такое же, как и устанавливаемое значение, и находятся в той же строке, столбце или регионе. В ошибочную ячейку пожет поставить своё значение другой игрок.
                    TestForError(serverCell);
                    return(true);
                }
            }

            return(false);
        }
Beispiel #2
0
        /// <summary>
        /// Возвращает текущее состояние игры, для передачи его игрокам.
        /// </summary>
        /// <param name="realGame">При false возвращает пустое поле. Используется для очистки поля у игрока, покинувшего турнир.</param>
        /// <returns>Текущее состояние игры</returns>
        public CSudokuState GetGameState(bool realGame = true)
        {
            CSudokuCell[] array = new CSudokuCell[cellGrid.Length];

            int i = 0;

            foreach (CSudokuCell cell in cellGrid)
            {
                array[i++] = realGame
                    ? cell
                    : CSudokuCell.NULL(cell.X, cell.Y);
            }

            return(new CSudokuState
            {
                Level = realGame ? GameLevel : SudokuLevel.Unknown,
                Values = array
            });
        }
Beispiel #3
0
        /// <summary>
        /// Проверка нового значения в ячейки на то, что оно - ошибочно. Ошибочные ячейки помечаются.
        /// </summary>
        /// <param name="testingCell">Проверяемая ячейка</param>
        private void TestForError(CSudokuCell testingCell)
        {
            for (int i = 0; i < 9; i++)
            {
                // Проверка по строке
                if (i != testingCell.Y)
                {
                    cellGrid[testingCell.X, i].TestError(testingCell);
                }

                // Проверка по столбцу
                if (i != testingCell.X)
                {
                    cellGrid[i, testingCell.Y].TestError(testingCell);
                }
            }

            // Проверка по региону 3х3

            // Определение "координат" региона
            int regX = testingCell.X / 3;
            int regY = testingCell.Y / 3;

            for (int x = 0; x < 3; x++)
            {
                // Координата Х проверяемой ячейки в регионе
                int realX = regX * 3 + x;

                for (int y = 0; y < 3; y++)
                {
                    // Координата Y проверяемой ячейки в регионе
                    int realY = regY * 3 + y;

                    // Не сравниваем ячейку саму с собой
                    if (realX != testingCell.X || realY != testingCell.Y)
                    {
                        cellGrid[realX, realY].TestError(testingCell);
                    }
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Перенос сформированного условия в ячейки игры
        /// </summary>
        /// <param name="grid"></param>
        private void FillSudokuCells(byte[,] grid)
        {
            cellGrid = new CSudokuCell[grid.GetLength(0), grid.GetLength(1)];
            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++)
                {
                    cellGrid[i, j] = new CSudokuCell
                    {
                        Value = grid[i, j],
                        X     = i,
                        Y     = j,
                    };

                    if (grid[i, j] > 0)
                    {
                        // Пометка ячейки со значением как "принадлежащей серверу". В неё не может поставить своё значение никакой игрок.
                        cellGrid[i, j].Owner = CSudokuCell.ServerId;
                    }
                }
            }
        }