/// <summary>
        /// 스도쿠 보드의 빈 셀을 스도쿠 기본 규칙에 따라 해결합니다.
        /// </summary>
        /// <param name="sudokuBoard">9*9 가변 배열</param>
        /// <returns>스도쿠가 해결이 가능한지를 반환합니다.</returns>
        public bool SolveSudoku(byte[][] sudokuBoard)
        {
            if (!SudokuUtils.IsSudokuBoardValid(sudokuBoard))
            {
                throw new ArgumentException(InvalidSudokuBoardMessage);
            }

            return(SolveSudokuRec(sudokuBoard));
        }
Esempio n. 2
0
        /// <summary>
        /// 섞으면서 유효한 스도쿠로 부터 다른 스도쿠를 생성합니다.
        /// </summary>
        /// <param name="sudokuBoard">9*9 가변 배열</param>
        public void ShuffleSudoku(byte[][] sudokuBoard)
        {
            if (!SudokuUtils.IsSudokuBoardValid(sudokuBoard))
            {
                throw new ArgumentException(InvalidSudokuBoardMessage);
            }

            // 최소 20번, 최대 31번 중의 값만큼 스도쿠를 변환
            int transformationsToPerform = random.Next(20, 31);

            // 시스템 Random() 함수로 선택된 값만큼 0부터 1씩 증가하며 For문을 돌린다.
            for (int transformationsCount = 0; transformationsCount < transformationsToPerform; transformationsCount++)
            {
                var transformationType = (SudokuBoardTransformationType)random.Next(0, 6);
                TransformSudokuBoard(sudokuBoard, transformationType);
            }
        }
        /// <summary>
        /// 새로운 셀이 스도쿠 기본 규칙을 따르는지, 유효한지를 검사합니다.
        /// </summary>
        /// <param name="sudokuBoard">9x9 가변 배열</param>
        /// <param name="row">새로운 셀의 행</param>
        /// <param name="column">새로운 셀의 행</param>
        /// <param name="value">새로운 셀의 행</param>
        /// <returns>새로운 셀이 유효한지를 반환합니다.</returns>
        public bool IsNewCellValid(byte[][] sudokuBoard, byte row, byte column, byte value)
        {
            if (!SudokuUtils.IsSudokuBoardValid(sudokuBoard))
            {
                throw new ArgumentException(InvalidSudokuBoardMessage);
            }

            if ((row < 0 || row > 8) || (column < 0 || column > 8))
            {
                throw new IndexOutOfRangeException("행과 열의 값은 반드시 0부터 8사이 이여야 합니다!");
            }

            for (int i = 0; i < 9; i++)
            {
                // 행 검사
                if (sudokuBoard[row][i] == value && i != column)
                {
                    return(false);
                }

                // 열 검사
                if (sudokuBoard[i][column] == value && i != row)
                {
                    return(false);
                }

                // 3*3 보드 검사
                int groupRow = row / 3 * 3 + i / 3;
                int groupCol = column / 3 * 3 + i % 3;
                if (sudokuBoard[groupRow][groupCol] == value && (groupRow != row || groupCol != column))
                {
                    return(false);
                }
            }

            // 유효하다면
            return(true);
        }
Esempio n. 4
0
        /// <summary>
        /// 유효한 스도쿠에서 난이도에 알맞게 셀을 삭제하여 플레이어가 해결할 수 있도록 합니다.
        /// </summary>
        /// <param name="sudokuBoard">9*9 가변 배열</param>
        public void EraseCells(byte[][] sudokuBoard, SudokuDifficultyType sudokuDifficulty)
        {
            if (!SudokuUtils.IsSudokuBoardValid(sudokuBoard))
            {
                throw new ArgumentException(InvalidSudokuBoardMessage);
            }

            // 지울 셀의 개수를 0으로 초기화
            int cellsToErase = 0;

            // 지울 셀의 개수를 난이도에 따라 지정
            if (sudokuDifficulty == SudokuDifficultyType.데모)
            {
                cellsToErase = CellsToEraseOnDemo;
            }
            if (sudokuDifficulty == SudokuDifficultyType.Easy)
            {
                cellsToErase = CellsToEraseOnEasyDifficulty;
            }
            else if (sudokuDifficulty == SudokuDifficultyType.Medium)
            {
                cellsToErase = CellsToEraseOnMediumDifficulty;
            }
            else if (sudokuDifficulty == SudokuDifficultyType.Hard)
            {
                cellsToErase = CellsToEraseOnHardDifficulty;
            }
            else if (sudokuDifficulty == SudokuDifficultyType.Expert)
            {
                cellsToErase = CellsToEraseOnImpossibleDifficulty;
            }
            else if (sudokuDifficulty == SudokuDifficultyType.Custom)
            {
                cellsToErase = CustomMode;
            }
            else
            {
                cellsToErase = 20;                 // 오류 발생시 빈칸 20개 뚫기 (Demo 와 Easy 사이 난이도)
            }

            // 셀 지우는 방법:
            // 1. 행에서 시스템의 Random() 함수로 선택된 셀을 지운다.
            // 2. 반 대각선 (Minor Diagonal) 에 있는 셀을 지운다.
            // 3. 반복한다.
            while (cellsToErase > 0)
            {
                // 0 부터 8 까지의 행, 1씩 증가
                for (int row = 0; row < 9; row++)
                {
                    // 최소 0, 최대 9 의 열 중 하나를 선택 (시스탬이 Random() 함수로 선택)
                    int col = random.Next(0, 9);
                    if (sudokuBoard[row][col] != 0)             // 선택받은 (?) sudokuBoard[행][열] 이 0이 아니라면 (빈칸이 아니라면)
                    {
                        sudokuBoard[row][col] = 0;              // 빈칸으로 전환
                        cellsToErase--;                         // 지울 셀의 개수 - 1
                    }

                    if (cellsToErase <= 0)              // 지울 셀의 개수가 0 이하가 되면
                    {
                        return;                         // 멈춤
                    }

                    int oppositeRow = 9 - col - 1;                  // 반대편 행 선택
                    int oppositeCol = 9 - row - 1;                  // 반대편 열 선택
                    if (sudokuBoard[oppositeRow][oppositeCol] != 0) // sudokuBoard[반대편 행][반대편 열] 이 0이 아니라면 (빈칸이 아니라면)
                    {
                        sudokuBoard[oppositeRow][oppositeCol] = 0;  // 빈칸으로 전환
                        cellsToErase--;                             // 지울 셀의 개수 - 1
                    }

                    if (cellsToErase <= 0)              // 지울 셀의 개수가 0 이하가 되면
                    {
                        return;                         // 멈춤
                    }
                }
            }
        }