How to use a value from a random value set only on

2019-01-29 05:32发布

This question already has an answer here:

I'm trying to chose between 15 array values on a random base. The problem i'm facing is the fact that i want a value to only be generated once during the program. Once all 15 numbers are generated, the programs ends.

So my question is, how do you make sure a value is only generated once during the program.

       int[] ImageValues = new int[15];
       ImageValues[0] = 1;
       ImageValues[1] = 2;
       ImageValues[2] = 3;
       ImageValues[3] = 4;
       ImageValues[4] = 5;
       ImageValues[5] = 6;
       ImageValues[6] = 7;
       ImageValues[7] = 8;
       ImageValues[8] = 9;
       ImageValues[9] = 10;
       ImageValues[10] = 11;
       ImageValues[11] = 12;
       ImageValues[12] = 13;
       ImageValues[13] = 14;
       ImageValues[14] = 15;

       Random randomize = new Random();
       int initialValue = randomize.Next(0, 15);
       int finalValue = ImageValues[initialValue];

3条回答
劫难
2楼-- · 2019-01-29 06:10

First, you can also initialize your array when you declare it and the class should also have a Random object so you can reuse it rather than creating a new one each time. So, perhaps in the ctor:

rand = new Random();
int[] ImageValues = new int[15]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

You can use a one-liner to randomize/shuffle it:

ImageValues = ImageValues.OrderBy(i => rand.Next()).ToArray();

This will work fine for many cases. The standard Fisher-Yates shuffle is accepted as fast and producing an unbiased order (when used correctly), so in some cases it may be better:

private void ArrayShuffle(int[] items)
{
    // uses the Random var declared earlier 
    int tmp = 0;
    int j = 0;
    // hi to low, so the rand result is meaningful
    for (int i = items.Count() - 1; i >= 0; i += -1)
    {
        j = rand.Next(0, i + 1);     // NB max param is EXCLUSIVE

        tmp = items[j];
        // swap  j and Card i 
        items[j] = items[i];
        items[i] = tmp;
    }
}

Either way, once the array is shuffled, you can use it to create a Stack or Queue by passing the array in the constructor:

int[] ImageValues = new int[15];
 // ...
ArrayShuffle(ImageValues);
Stack<int> mystack = new Stack<int>(ImageValues);

You could just use the array and a variable pointing to the index to use. Using a collection type eliminates the need for that index var and the chance of a bug when it is/is not incremented. For something like a card game, it mimics dealing the next card from the top of the deck:

// ToDo: 
// check myStack.Count() if times used is not controlled elsewhere
int nextVal = myStack.Pop();
查看更多
爷的心禁止访问
3楼-- · 2019-01-29 06:10

A simple, efficient solution is this:

Say you have N elements from which to chose.

  1. You randomly pick an index from 0 to N-1 and remove the picked value from the array.
  2. Copy the last element of the array to the index you removed.
  3. Repeat steps 1-2 treating the array as if it's one element shorter, so on the second time you pick an index between 0 and N-2, then 0 and N-3 etc.

This guarantees that you can pick any K elements in exactly K iterations (so the algorithm is deterministic) and it guarantees a uniform distribution. One other benefit is that it doesn't require any additional memory allocation.

查看更多
做个烂人
4楼-- · 2019-01-29 06:16

The easiest solution is to first create a list of your values... 1-15, then you randomly generate a number between 0 and 14.

You then take the value from that position and remove it from the list. Then you generate a new random number that is between 0 and 13. And so on, until you have removed all numbers.

查看更多
登录 后发表回答