So, the main purpose of this tutorial is to show how to retrieve values from an array from random slots, without ever getting the same slot twice.
Note: This is intended for AMX Mod X scripters who are fluent in scripting plugins. (No learners, please.)
Code:
// Overview of the tutorial:
// players[] = all players in the server
// total = amount of players in the players[] array
// retreive = amount of players to retrieve from the players[] array
// selected[] = random players taken from players[] array
// count = amount of players saved in the selected[] array
// rand = random loop number to retrieve random players
// I will just use the players array,
// since this is what most people want this for
new players[32], total;
get_players(players, total);
// this will be how many random we want
new retrieve = 5;
// check if it is larger than total
// because you cannot get more players than the ones that exist
if( retrieve > total ) retrieve = total;
// this will be the counter of how many random we have gotten
new count;
// this will hold all the random players
// note: if this isn't for players,
// make sure that this array size is the same as the array you are getting values from
new selected[32];
// lets start a loop
// we get a random number each time to randomize the selected
// then, we delete the random index from the original players list
new rand;
do
{
rand = random(total);
// save the player id in the selected array,
// and increase the amount we saved
selected[count++] = players[rand];
// this replaces the random one we used with the last one in the array
// also, it decreases the total since we got rid of the random one
players[rand] = players[--total];
}
while( count < retrieve );
// you now have an array (selected[]) that holds "count" number of players
// they are all random players that are currently in the server
// Note: this is only an example, and can be used for any random array retrieving.
Now, for all you people that want to know how to use this with the dynamic array system.
Code:
// Overview of the tutorial:
// players = all players in the server
// total = amount of players in the players array
// retreive = amount of players to retrieve from the players array
// selected = random players taken from players array
// count = amount of players saved in the selected array
// rand = random loop number to retrieve random players
// player = random player selected from players array
new Array:players = ArrayCreate(1, 32);
new total;
// this code will fill the players array will all players in the server
// if you aren't using this tutorial for players, skip this part, assuming your array is filled
new max_players = get_maxplayers();
for( new id = 1; id <= max_players; id++ )
{
if( is_user_connected(id) )
{
ArrayPushCell(players, id);
total++;
}
}
// this will be how many random we want
new retrieve = 5;
// check if it is larger than total
// because you cannot get more players than the ones that exist
if( retrieve > total ) retreive = total;
// this will be the counter of how many random we have gotten
new count;
// this will hold all the random players
new Array:selected = ArrayCreate(1, retrieve);
new player;
// lets start a loop
// we get a random number each time to randomize the selected
// then, we delete the random index from the original players list
new rand;
do
{
rand = random(total);
player = ArrayGetCell(players, rand);
// save the player id in the selected array,
// and increase the amount we saved
ArrayPushCell(selected, player);
count++;
// now we need to remove the index from the list
// so, we will shift all slots above the player id slot down 1
ArrayDeleteItem(players, rand);
// decrease total player ids since we removed one
total--;
}
while( count < retrieve );
// you now have an array (selected) that holds "count" number of players
// they are all random players that are currently in the server
// Note: this is only an example, and can be used for any random array retrieving.
This is a more advanced way which uses the Sort*() functions from AMXX.
I'm not experienced in this area. This was shown by P34nut and arkshine (a few posts after this one).
Code:
YourFunction()
{
new players[32], pnum;
get_players(players, pnum); // you can use any flags you wish
SortCustom1D(players, pnum, "HandleRandomSort");
}
HandleRandomSort(elem1, elem2, const array[], const data[], const dataSize)
{
switch( random(61) )
{
case 0 .. 29: return -1;
case 30: return 0;
}
return 1;
}
Here is an example for a function that retrieves a random player.
Code:
YourFunction()
{
new player = GetRandomPlayer("a");
}
GetRandomPlayer(const flags[]="", const teamORname[]="")
{
new players[32], pnum;
get_players(players, pnum, flags, teamORname);
return (pnum > 0) ? players[random(pnum)] : 0;
}
Here is an example for a function that retrieves an array of random players.
Code:
YourFunction()
{
new players[32], pnum;
GetRandomPlayers(players, pnum, "a");
}
GetRandomPlayers(players[32], &pnum, const flags[]="", const teamORname[]="")
{
new original[32], total;
get_players(original, total, flags, teamORname);
pnum = 0;
new rand, i;
do
{
rand = random(total);
players[pnum++] = original[rand];
original[rand] = original[--total];
}
while( total > 0 );
}
EDIT:
Here are some useful functions that I wrote up.
It allows you to just copy these functions and implement anything you needed from the first post.
Code:
GetRandomNumberRange( const minn, const maxx );
GetRandomNumbersRange( numbers[ ], const size, const minn, const maxx );
any:GetRandomNumberCArray( const Array:array );
GetRandomNumbersCArray( any:numbers[ ], const size, const Array:array, bool:dont_modify );
any:GetRandomNumberArray( const any:array[ ], const array_size = sizeof( array ) );
GetRandomNumbersArray( any:numbers[ ], const size, const any:array[ ], const array_size = sizeof( array ) );
Code:
// Returns a random number from 'minn' to 'maxx'
// Note: Only works for integers
#define GetRandomNumberRange random_num
//#define GetRandomNumberRange(%1,%2) random_num(%1, %2)
/*stock GetRandomNumberRange( const minn, const maxx )
{
return random_num( minn, maxx );
}*/
// Gives an array of random numbers ranging from 'minn' to 'maxx'
// Note: Only works for a integers
// Note2: If the size of the array is larger than the range, the array will not be completely filled, since numbers are not duplicated.
// Note3: If the size of the array is smaller than the range, not all of the numbers in the range will be given.
// Note4: Requires GetRandomNumbersCArray() to work.
stock GetRandomNumbersRange( numbers[ ], const size, const minn, const maxx )
{
new Array:array = ArrayCreate( 1 );
for( new i = minn; i <= maxx; i++ )
{
ArrayPushCell( array, i );
}
new count = GetRandomNumbersCArray( numbers, size, array, .dont_modify = false );
ArrayDestroy( array );
return count;
}
// Returns the value from a random index in a cell array
#define GetRandomNumberCArray(%1) ArrayGetCell( %1, random( ArraySize( %1 ) ) )
/*stock any:GetRandomNumberCArray( const Array:array )
{
return any:ArrayGetCell( array, random( ArraySize( array ) ) );
}*/
// Gives an array of values from random indexes in a cell array
// Note: dont_modify - true: don't delete items from the array that were used, false: delete items that were used
// Note2: If the size of the array is larger than the size of the cell array, the array will not be completely filled, since indexes are not duplicated.
// Note3: If the size of the array is smaller than the size of the cell array, not all of the indexes will be given.
stock GetRandomNumbersCArray( any:numbers[ ], const size, const Array:array, bool:dont_modify )
{
new Array:temp;
new array_size = ArraySize( array );
if( dont_modify )
{
temp = ArrayCreate( 1 );
for( new i = 0; i < array_size; i++ )
{
ArrayPushCell( temp, any:ArrayGetCell( array, i ) );
}
}
else
{
temp = array;
}
new count;
new rrandom;
while( count < size && array_size > 0 )
{
rrandom = random( array_size );
numbers[ count++ ] = any:ArrayGetCell( temp, rrandom );
ArrayDeleteItem( temp, rrandom );
array_size--;
}
if( dont_modify )
{
ArrayDestroy( temp );
}
return count;
}
// Returns a random number from an array of numbers
// Note: If your given array size is undefined (like from a function), then don't pass the 'array_size' argument and it will be auto-determined.
//#define GetRandomNumberArray(%1) %1[ random( sizeof( %1 ) ) ]
stock any:GetRandomNumberArray( const any:array[ ], const array_size = sizeof( array ) )
{
// this is not a #define because using a function can always find the array size
// but in a #define, it replaces the function with it's defined action
// if it is used on an array that is passed to a function with no size, it will give a compiler error
// this will prevent that
return any:array[ random( array_size ) ];
}
// Gives an array of values from random indexes in a given array
// Note: If your given array size is undefined (like from a function), then don't pass the 'array_size' argument and it will be auto-determined.
// Note2: If the size of the array is larger than the size of the given array, the array will not be completely filled, since indexes are not duplicated.
// Note3: If the size of the array is smaller than the size of the given array, not all of the indexes will be given.
// Note4: Requires GetRandomNumbersCArray() to work.
stock GetRandomNumbersArray( any:numbers[ ], const size, const any:array[ ], const array_size = sizeof( array ) )
{
new Array:CArray = ArrayCreate( 1 );
for( new i = 0; i < array_size; i++ )
{
ArrayPushCell( CArray, array[ i ] );
}
new count = GetRandomNumbersCArray( numbers, size, CArray, .dont_modify = false );
ArrayDestroy( CArray );
return count;
}
Here is an example for those people who want random players.
Code:
// only used for readability
const MAX_PLAYERS = 32;
new iPlayers[ MAX_PLAYERS ], iNum;
// get your players how you want them
// example for all:
get_players( iPlayers, iNum );
// example for all alive:
get_players( iPlayers, iNum, "a" );
// look here for more possibilities
//http://www.amxmodx.org/funcwiki.php?go=func&id=174
new iRandomPlayers[ MAX_PLAYERS ];
GetRandomNumbersFromArray( iRandomPlayers, MAX_PLAYERS, iPlayers, iNum );
for( new i = 0; i < iNum; i++ )
{
log_amx( "iPlayers[%i] = %i, iRandomPlayers[%i] = %i", i, iPlayers[ i ], i, iRandomPlayers[ i ] );
}
That is all!
Feel free to point out any suggestions/errors.
__________________