Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Randomly select element from array

Status
Not open for further replies.

spelltwister

Programmer
May 12, 2005
36
0
0
US
Hey everyone,

I was wondering, just for efficiency, is there a way to randomly select a non-zero element in an array.

Here's what I got:

$offense_infantry = array( "number" => array(), "nation" => array() );
$defense_infantry = array( "number" => array(), "nation" => array() );
for($k=0;$k<$defHits;){
if($attInfantry>0){
$upper = sizeof($offense_infantry["nation"]);
$index = rand(0,$upper-1);
if($offense_infantry["number"][$index] > 0){
$attInfantry--;
$offense_infantry["number"][$index] -= 1;
$k+=1;
echo 'Attacker lost an infantry to artillery</br>';
}else{
echo 'empty attacker infantry to artillery</br>';
}...

Essentially, this is very unefficient as I look at my turn results there are many cases where it falls into the else part of that if statement. As you can see, it will not leave the for loop until enough hits have been done (the k+=1 has to reach the target $defHits var) and this sometimes takes a while.

Is there a better way to randomly select a non-zero element from the array?

If you need more info/clarification, please ask.

Thanks,

Mike
 
I think I'd change my data structure to something like:

[tt]$offense_infantry = array
(
'active' => array
{
0 => array
(
'number' => 3,
'nation' => 'Freedonia'
),
1 => array
(
'number' => 11,
'nation' => 'Epsilon'
),
.
.
.
),
'inactive' => array
(
0 => array
(
'number' => 0,
'nation' => 'Stanstanistan'
),
1 => array
(
'number' => 0,
'nation' => 'PDR of Gleep'
),
.
.
.
)
);[/tt]

And add code to move an active unit to the inactive array when that unit's number value hits zero. That way, I only have to randomly select one element from the active units, knowing that they all have non-zero units.




Want the best answers? Ask the best questions! TANSTAAFL!
 
Hey,

First, I'm not really sure what you did there. lol

Second, I had thought of something like that and origianlly was trying to unset that element or something similar to that, but couldn't figure out how to get rid of that element from the array. Thinking now, I could have yet another array with all the empty positions and cycle through that until I get a number for a good position...

Is there a way to just get rid of an element and push the rest together so that the sizeof() represents the new size of and all element references adjust as well?

Thanks a bunch.

Online multiplayer strategy games huh? Try, 1483online.com where the games are FREE and the community drives enhancements to the game. ;-D
 
I am assuming that in your datastructure, that $offense_infantry['number'][x] is the current number for the infantry unit of nation $offense_infantry['nation'][x].

My datastructure puts the number and nation together into something approaching an object.

$offense_infantry['active'][x] describes a unit. That array element is itself an array containing the elements 'number' and 'nation'. I think my datastructure allows you to manipulate the data a little more meaningfully:

Take a look at:
Code:
php
$offense_infantry = array
(
    'active' => array
   	(
        0 => array
        (
            'number' => 3,
            'nation' => 'Freedonia'
        ),
        1 => array
        (
            'number' => 11,
            'nation' => 'Epsilon'
        ),
    ),
    'inactive' => array
    (
        0 => array
        (
            'number' => 0,
            'nation' => 'Stanstanistan'
        ),
        1 => array
        (
            'number' => 0,
            'nation' => 'PDR of Gleep'
        ),
    )
);

print '<pre>';
print_r ($offense_infantry);
print '</pre><br><hr>';

//drop one unit to zero
$offense_infantry['active'][0]['number'] = 0;

//copy the "empty" unit to the inactive list
$offense_infantry['inactive'][] = $offense_infantry['active'][0];

//remove the "empty" unit from the active list
unset ($offense_infantry['active'][0]);

//run sort on the list so that the array is numbered starting at zero
sort($offense_infantry['active']);

print '<pre>';
print_r ($offense_infantry);
print '</pre>';
?>



Want the best answers? Ask the best questions! TANSTAAFL!
 
Thanks, I'll try to get the code working using the sort to renumber it, but I'm still not sure how yours is more meaningful. Once it reaches 0, I don't care about it anymore and it's not necessary to store.

Also, I had tried this:

// if($offense_artillery["number"][$index] ==0){
// unset($offense_artillery["number"][$index]);
//unset($offense_artillery["nation"][$index]);
// }
... which I can now see where you are more efficient. Thanks. :-D

But the point was that the above code caused it to hit an endless loop of misses. Now, I understand that there would be an index where there is nothing, meaning a miss, but why would it become endless? I'm assuming that the sort will fix this?

Thanks

Online multiplayer strategy games huh? Try, 1483online.com where the games are FREE and the community drives enhancements to the game. ;-D
 
If you don't need to store the depleted units, ignore that part of the code.

I'm using sort() to get rid of gaps in the array. If there are 5 elements with indices 0, 1, 2, 3, 4 and you unset() the element with index 2, you are left with array elements with indeces 0, 1, 3, 4. Using sort() on the array will instead leave you indeces 0, 1, 2, 3. That way, you don't have to worry about dealing with randomly picking a unit, the previous index of which is no longer there.



Want the best answers? Ask the best questions! TANSTAAFL!
 
I understand why you are using sort, but why did my code go into an endless loop. I've never been able to figure that out... :-/

Online multiplayer strategy games huh? Try, 1483online.com where the games are FREE and the community drives enhancements to the game. ;-D
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top