I'll use a deck of cards as an example here.
What your current code does is draw a random card from a deck. Then, the second time, it draws a random card from a complete deck, which means that there's a change you draw the same card twice. The problem persists for all subsequent draws.
What you want to do is when you draw a second card is that you want to draw it from the same deck, i.e. the 51 card deck (because you already drew a card earlier).
In a deck of cards, when you draw a random card, you inherently remove it from the deck. But that's not how it works in code. You copy a random value from the array, but you don't automatically remove it from the array.
There are two ways of doing this.
1. Remove the drawn card from the deck before drawing the next card.
In other words, when you get a random letter, you remove that letter from
lettersArr so that you can't get the same letter again.
string remainingLetters = "abcdefghijklmnopqrstuvwxyz";
// draw the first "card"
var firstLetter = remainingLetters[rdm.Next(remainingLetters.Length)];
// remove it from the "deck"
remainingLetters = remainingLetters.Replace(firstLetter, String.Empty);
// draw the second "card"
var secondLetter = remainingLetters[rdm.Next(remainingLetters.Length)];$
This can of course be improved by an iterative approach. Also, beware that this makes it impossible for you to get more than 26 letters as your deck will be empty.
There are more performant variation of this algorithm, but this is just an example. I'm skipping the optimalizations because I suggest using the second approach as I find it far better to use:
2. Shuffle the deck
What I mean by shuffling the deck is that you (randomly) rearrange the letters rather than extracting them from the array one by one. This is very analogous to what you'd do to a deck of cards, and it makes a lot more intuitive sense.
I much prefer this method because it's so much cleaner, and you can use LINQ
var orderedAlphabet = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
var shuffledAlphabet = orderedAlphabet.OrderBy(letter => rdm.Next()).ToArray();
Basically, LINQ will generate a random number (
rdm.Next()) for every letter, and will then sort the letters by the numerical value of the random number.
The end result is a string (or character array) with the exact same 26 letters, but the order is randomized.
If you then want to fetch letters from the randomized array, just read from left to right. You can either use a substring to get a chunk of a certain size all at once:
var chunk = shuffledAlphabet.Substring(0,5); // 5 letters
or read it letter by letter using a counter that you increment:
private int counter = 0;
private char GetNextLetter()
Don't forget to check your upper bound too!
Or if you need all 26, you don't need to process it any further and can just return
shuffledAlphabet as is.
private char GetShuffledAlphabet()