Could anyone say if this is a reliable shuffling code? I am trying to prove the famous "Monty Hall Paradox": 


  The Monty Hall problem is a probability puzzle named after Monty Hall, the original host of the TV show Let’s Make a Deal. It’s a famous paradox that has a solution that is so absurd, most people refuse to believe it’s true.


private static void suffle(ulong numberOfTries)
    {
        int correctHits = 0;
        int wrongHits = 0;

        var prizeIndex = new Random();

        for (ulong i = 1; i &lt;= numberOfTries; i++)
        {
            int[] doors = { 1, 2, 3 };

            var prizeDoor = doors[prizeIndex.Next(0, doors.Length)] ;

            var selectedDoor = doors[prizeIndex.Next(0, doors.Length)];               

            int discardedDoor = doors[prizeIndex.Next(0, doors.Length)];

            while (discardedDoor == prizeDoor || discardedDoor == selectedDoor)
            {
                discardedDoor = doors[prizeIndex.Next(0, doors.Length)];
            }

            var correctGuess = selectedDoor == prizeDoor;

            if (correctGuess) correctHits++;
            else wrongHits++;

            Console.WriteLine($"Prize Door: {prizeDoor}\nSelected Door: {selectedDoor}\nDiscarded Door: {discardedDoor}\nRight Guess? {correctGuess}\n\n");
        }

        Console.WriteLine($"Right Guesses: {correctHits} / {numberOfTries}\nWrong Guesses: {wrongHits} / {numberOfTries}");
    }
your code is pretty neat and readable. Shuffling algorithm looks reliable to me, however I have a few comments to your C# code.


You pass the argument numberOfTries as ulong type, but correctHits and wrongHits are int. It could lead to wrong output if the numberOfTries is large enough to overflow int.MaxValue.
Variable doors are initialized in each loop. It could be initialized once in higher scope, e.g. before the for loop.
I can see repetetive code doors[prizeIndex.Next(0, doors.Length)]. This piece of code could be refactored to isolated method. For example:

private static int GetDoorNumber() => _doors[_prizeIndex.Next(0, _doors.Length)];
You can save couple of code lines introducing ternary operator. Then you do not need variable correctGuess.

correctHits += (selectedDoor == prizeDoor) ? 1 : 0;


You can calculate wrongHits as a difference of numberOfTries and correctHits. But your solution works too.