/// <summary>
        /// Removes numbers from an existing <see cref="SudokuPuzzle"/> according to its difficulty.
        /// </summary>
        /// <param name="sudoku">The <see cref="SudokuPuzzle"/> to remove numbers from.</param>
        /// <exception cref="ArgumentNullException"><c><paramref name="sudoku"/></c> is <c>null</c>.</exception>
        public static void RemoveNumbers(SudokuPuzzle sudoku)
        {
            if (sudoku is null)
            {
                throw new ArgumentNullException(nameof(sudoku));
            }

            sudoku.ClearReadOnlyProperties();
            int attempts = 45;

            switch (sudoku.Difficulty)
            {
            case SudokuDifficulty.Medium:
                attempts = 60;
                break;

            case SudokuDifficulty.Hard:
                attempts = 75;
                break;
            }

            do
            {
                int row, column;

                do
                {
                    row    = SudokuGenerator.Random.Next(sudoku.Size);
                    column = SudokuGenerator.Random.Next(sudoku.Size);
                } while (sudoku[row, column] == 0);

                int value = sudoku[row, column];
                sudoku[row, column] = 0;
                bool solvable = SudokuSolver.CheckSolvable(sudoku, out bool multipleSolutions);

                if (!solvable || multipleSolutions)
                {
                    sudoku[row, column] = value;
                }
            } while (attempts-- > 0);

            sudoku.SetReadOnlyProperties();
        }