Page 1 of 1

Random item selection with exclusion?

PostPosted: Fri Jan 04, 2013 2:06 pm
by Lacotemale
Hi all,

Recently I have been having trouble coming up with a way to select a random item but excluding an item that is already used.

Currently I have this:

Selected = GetRandomBetween(1,6);

and if statements to handle is something is used. However this seems unreliable. :?

Is there a better system?

Re: Random item selection with exclusion?

PostPosted: Fri Jan 04, 2013 9:27 pm
by lcl
It would be a good idea to make an array where to store the numbers of the items that you have not chosen, and then pick item from there and take its number away from the array.
Do you understand this or should I write an example? :)

Re: Random item selection with exclusion?

PostPosted: Sat Jan 05, 2013 5:07 pm
by Lacotemale
Right so I can declare an array like this:

Code: Select all
int myArray[5] = { 1, 2, 3, 4, 5 };


To remove the number 3 I would do:

Code: Select all
myArray[3] = 0;  //zero meaning the item is used


Then do something like this for random selection?

Code: Select all
if (Selected = GetRandomBetween(1,6)==3 && myArray[3]==0)
{
  Selected = GetRandomBetween(1,6); //run it again?
}


Am I doing it correctly?

Re: Random item selection with exclusion?

PostPosted: Sat Jan 05, 2013 7:28 pm
by lcl
No, that's not what I meant.

I meant that you create an array where you store the numbers of your items still available, and then when you want to choose a random item,
choose randomly from that array and take the number away. When doing this it is required that when number is taken away from array, the numbers after it are moved to fill the hole.
Example:
Items that can be selected randomly:
1 2 3 4 5 6
Game randomly selects number 3
So now 3 can't be used again and removing it from the array results to this:
1 2 0 4 5 6
We can't have that 0 there, so we have to move the numbers after it, so:
1 2 4 5 6 0
And now the next time we choose a number we limit it to choose the number from the five first numbers, which means excluding the number 0. :)

Here's how I wrote it:

Global Code:
Code: Select all
int selected;
int selectableItemsLeft = 6;
int selectableItems[6] = {1, 2, 3, 4, 5, 6};

These variables are needed. I think you already have the variable selected, because you used it in your code.
The integer selectableItemsLeft holds the amount of items not used, so that we know where we have to limit the GetRandomBetween maximum value.
And selectableItems[6] is the array that holds the numbers of the items possible to be selected.

And this code goes to where ever you want to select a random item, which has not been used yet:
Code: Select all
int i, move = 0;
int selectRandom;

if (selectableItemsLeft > 0)
{
    selectRandom = GetRandomBetween(0, selectableItemsLeft);
    selected = selectableItems[selectRandom];

    selectableItemsLeft -= 1;

    for (i = 0; i <= 6; i ++)
    {
        if (i == selectRandom){move = 1; selectableItems[i] = 0;}
        if (move == 1 && i < 5)
        {
            selectableItems[i] = selectableItems[i + 1];
            selectableItems[i + 1] = 0;
        }
    }
}

The code explained:
Line number - explanation
1 - make local variables i and move. i is for the 'for'-loop, move for controlling when the numbers have to be shifted down (this has to be set to 0, or otherwise it'll shift on its own :P ).
2 - make local variable selectRandom, which is used for storing the randomly selected array index.
4 - check if there is still some unused items left
6 - set selectRandom to point to some of the numbers in the selectableItems[] -array. The min limit must be 0 so that we can get the first value too. (Array cell indexes start from 0)
7 - set selected to be the number in the array selectableItems[] in which the selectRandom points to.
9 - reduce one from selectableItemsLeft. We need to do this so that next time when GetRandomBetween() gets number from the array we don't select the 0 we are going to put to the end of it.
11 - start for loop for going through all the array cells of the array selectableItems[]
13 - if we are in the cell that contains the number which we just selected, set move to 1 (for knowing that now we need to shift down all the numbers to come) and replace the selected number with 0.
14 - if move is equal to 1 and i is less than 5 (i must be less than five because inside this if statement we are going to modify the array cell numbered with the value of i + 1, and if i = 5, we would be modifying array cell number 6, which doesn't exist, since our array has just 6 cells (indexing begins from 0). And doing that would result to an error.)
16 - copy the number from next array cell to the current one
17 - reset the next array cell

And now, it works!
Here's a demo, too. Read the instructions in the demo.

If you still don't understand this, just ask! :)

Re: Random item selection with exclusion?

PostPosted: Mon Jan 07, 2013 2:49 pm
by Lacotemale
Thanks for the excellent example!

However when I used this in my game it doesn't work but the example does. I will work more on it today and try to figure it out.

Re: Random item selection with exclusion?

PostPosted: Mon Jan 07, 2013 5:44 pm
by lcl
Ok. Ask me if you can't find a way to make it work, and I'll help you. :)

Re: Random item selection with exclusion?

PostPosted: Fri Jan 25, 2013 4:03 pm
by Lacotemale
Ok.. so I still haven't managed to get this working. Here is what I have currently:

Code: Select all
int selectableItemsLeft = 6;
int selectableItems[6] = {1, 2, 3, 4, 5, 6};

if (selectableItemsLeft > 0)
{
    selectRandom = GetRandomBetween(1,selectableItemsLeft);

    enemyCardSelected = selectableItems[selectRandom];

    selectableItemsLeft -= 1;

    for (i = 0; i <= 6; i ++)
    {
        if (i == selectRandom){move = 1; selectableItems[i] = 0;
    }
        if (move && i < 5)
        {
            selectableItems[i] = selectableItems[i + 1];
            selectableItems[i + 1] = 0;
        }
}


And the GetRandomBetween function is here:

Code: Select all
int GetRandomBetween(int ii,int jj)
{
    int ij=rand(max(ii,jj)-min(ii,jj));
    return ij+min(ii,jj);
}


On a few tests here are the results when I execute the code 5 times:

Test 1: - 3, 5, 4, 3, 5.
Test 2: - 5, 5, 5, 3, 4.
Test 3: - 2, 2, 4, 5, 4.

:?

Re: Random item selection with exclusion?

PostPosted: Sat Jan 26, 2013 1:01 pm
by lcl
These:
Code: Select all
int selectableItemsLeft = 6;
int selectableItems[6] = {1, 2, 3, 4, 5, 6};

Have to be put in Global Code.

Re: Random item selection with exclusion?

PostPosted: Sat Jan 26, 2013 1:51 pm
by Lacotemale
How? :oops:

Re: Random item selection with exclusion?

PostPosted: Sun Jan 27, 2013 6:51 pm
by lcl
Just like you have set up your GetRandomBetween() -function.
Go to Global Code, write the variables there, name the 'page' and click Add.

Re: Random item selection with exclusion?

PostPosted: Mon Jan 28, 2013 12:56 pm
by Lacotemale
Alright I put them into a page called Vars. Still doesn't work and gives wrong results. :?

Re: Random item selection with exclusion?

PostPosted: Mon Jan 28, 2013 2:58 pm
by lcl
Then you probably have them left somewhere in the .ged of yours and that's causing it to mess up.

Do this:
- Clear ALL the variables and codes about this thing (ALSO the variables generated via the GE gui!)
- Then add the variables to the global code as I said
- Then write the code to where you want to use it

I'd like to help you, but your ged has so much going on that I can't find the places where you have added the codes and variables to.