How can I create a random deck of 7 cards every time they are all used?

How can I create a random deck of 7 cards every time they are all used?

I'm trying to create a Tetris like game in C# (Unity) and I've run into quite a problem on how I can generate 7 cards (tetrominoes) of which none are the same and when I run out of cards, I regenerate more.  
I can kind of see how I could do the regeneration part but I'm very unsure on getting 7 cards for which none are the same.

Solutions/Answers:

Answer 1:

As it happens, I was showing this method to my game mechanics students just this week. 🙂

One of my favourite ways to work with a deck is using an online version of a Fisher-Yates Shuffle (also called a Knuth shuffle)

IEnumerator<T> ShuffleBag<T>(params T[] items) {
    int remaining = items.Length;

    while(true) {
        // Choose a random item from what remains of our deck.
        // (That is, the entries 0...remaining-1)
        int drawIndex = Random.Range(0, remaining);
        T drawnItem = items[drawIndex];

        // Remove the item from the deck by swapping it to the end.
        remaining--;
        items[drawIndex] = items[remaining];
        items[remaining] = drawnItem;

        // Yield the drawn item as our new .Current item,
        // and wait until we're asked to draw again.
        yield return drawnItem;

        // If we're out of cards when we ask for a new one,
        // reshuffle the discards to make a fresh deck.
        if (remaining == 0)
            remaining = items.Length;
    }
}

You can set this up like so:

var bag = ShuffleBag(
             Tetromino.I,
             Tetromino.O,
             Tetromino.T,
             Tetromino.J, 
             Tetromino.L, 
             Tetromino.S, 
             Tetromino.Z
         );

Then draw a new tetromino from the bag like so:

bag.MoveNext();
var tetromino = bag.Current;

There will always be a new tetromino ready: the bag will automatically reshuffle the discards whenever it gets empty, and give them out in a new random order.

Answer 2:

Create a list of your tetrominoes, then get a random one out of it, do something with it, then remove it from the list:

List<Tetromino> m_list = new List<Tetromino>();

m_list.add(/* put tetromino #1 here*/);
m_list.add(/* put tetromino #2 here*/);
m_list.add(/* put tetromino #3 here*/);
m_list.add(/* put tetromino #4 here*/);
m_list.add(/* put tetromino #5 here*/);
m_list.add(/* put tetromino #6 here*/);
m_list.add(/* put tetromino #7 here*/);

while(m_list.count > 0)
{
    int rndNumber = Random.Range(0, m_list.count - 1);
    // do something with m_list[rndNumber]
    m_list.remove(rndNumber);
}

This way, each item can be used only once, and when the while loop exits, you’re sure you’ve used each one once.

References