Jump to content

Shuffle Array


bholaday

Recommended Posts

Hi,

 

I am writing a script for a game that needs players to randomly be assigned a target (another player) in a loop so that each player is matched with someone other than who has them. See below:

 

Andy matched with Jan

Jan matched with Alex

Alex matched with Sue

Sue matched with Andy

 

My code retrieves name from the database in the order they sign up to play. I need to randomize the pairings for fairness.

 

<?
$targets = array("Andy","Jan","Alex","Sue"); //names from DB in order of signup
?>

 

I make a copy of the array, shuffle it and check to make sure that two players are not paired with each other.

 

<?
$targets = array("Andy","Jan","Alex","Sue"); //names from DB in order of signup
$targets_shuffled = $targets; //copy array
shuffle($targets_shuffled); //shuffle targets
?>

 

I am having trouble figuring out how to check for duplicate pairings and then reshuffling until it works. Originally I had looped through the arrays to check each pairing:

<?
if($targets[$i] == $targets_shuffled[$i]){
  echo "same!";
}
?>

 

Then I realized when one pair was matched incorrectly the whole pairing would need to be reshuffled. I tried to flag it, break out, and reshuffle, but could never get anything that worked.

 

Any ideas?

-Blake

 

Code currently:

<?
shuffle($targets_shuffled);
echo "<br /><br />";

$retry = true;
$tries = 1;

while($retry == true){
	echo "try: $tries<br />";
	$retry = false;
	$i = 0;
	while($i < count($targets)){
		if($targets[$i] == $targets_shuffled[$i]){
			echo "found match!<br />";
			$retry = true;
			echo "breaking<br />";
			break;
		}
		$i++;
	}
	$tries++;
}

?>

Link to comment
Share on other sites

You could do something like this:

 

$targets = array("Andy","Jan","Alex","Sue");
$available = $targets;
foreach($targets as $target)
{
do
{
	$rand = $targets[array_rand($available)];
} while ($rand == $target || $pairs[$rand] == $target);
$pairs[$target] = $rand;
$index = array_search($rand, $available);
unset($available[$index]);
}

foreach($pairs as $player1 => $player2)
{
echo "$player1 matched with $player2<br />\n";
}

 

Example output:

 

Andy matched with Sue
Jan matched with Alex
Alex matched with Andy
Sue matched with Jan

Link to comment
Share on other sites

That works well at matching, but I also need it to be a continuous loop. In the game players try to eliminate each other. They need to be in a loop so the last two people alive are trying to eliminate each other.

 

I tried it with more names and got this result (reformatted to easily see multiple loops within the results)

 

--loop1--

Allison matched with Kara

Kara matched with Jon

Jon matched with Chelsea

Chelsea matched with Quinn

Quinn matched with Austin

Austin matched with Timothy

Timothy matched with Samantha

Samantha matched with Jesse

Jesse matched with Allison

--loop 2--

Kirk matched with Kathryn

Kathryn matched with Shawn

Shawn matched with Sara

Sara matched with Peggy

Peggy matched with Kirk

 

I didnt know about array_search and array_rand though! Thanks for the ideas. Any way to eliminate pairing a new target with one that has already been paired, until the last pairing of course?

 

Thanks so much for your help.

Link to comment
Share on other sites

Sorry I didnt explain this well. The game doesnt have rounds. Players are constantly trying to eliminate each other. It is not like a tournament-type pairing system where survivors move on to the next round.

 

In the previous example, ideally Jesse would not be matched with Allison but Kirk and the last pairing would not be a match between Peggy and Kirk but would complete the loop - Peggy matched with Allison.

 

--loop1--

Allison matched with Kara

Kara matched with Jon

Jon matched with Chelsea

Chelsea matched with Quinn

Quinn matched with Austin

Austin matched with Timothy

Timothy matched with Samantha

Samantha matched with Jesse

Jesse matched with Allison

--loop 2--

Kirk matched with Kathryn

Kathryn matched with Shawn

Shawn matched with Sara

Sara matched with Peggy

Peggy matched with Kirk

 

Ideally:

--loop1--

Allison matched with Kara

Kara matched with Jon

Jon matched with Chelsea

Chelsea matched with Quinn

Quinn matched with Austin

Austin matched with Timothy

Timothy matched with Samantha

Samantha matched with Jesse

Jesse matched with Kirk

Kirk matched with Kathryn

Kathryn matched with Shawn

Shawn matched with Sara

Sara matched with Peggy

Peggy matched with Allison

Link to comment
Share on other sites

Found a simple solution. I copied the array, shuffled it, copied the shuffled array, and shifted the copied array indexes by one. The last unmatched value is matched with the first creating a simple loop.

 


$targets = array("Allison","Kirk","Jesse","Quinn","Shawn","Jon","Austin","Kathryn","Samantha","Kara","Chelsea","Timothy","Sara","Peggy");

$targets_shuffled = $targets;	//copy array (unnecessary, but I didnt want to mess with the original)
shuffle($targets_shuffled); //shuffle array
$targets_shuffled_copy = array(); //copy shuffled array
$i = 0; //create counter

while($i < count($targets_shuffled)){ //loop through each index
	if($i+1 == count($targets_shuffled)){ //if we reach the last index match it with the first
		$targets_shuffled_copy[$i] = $targets_shuffled[0]; //assign value to index
	}else{ //if we're not at the end, assign value from next index
		$targets_shuffled_copy[$i] = $targets_shuffled[$i+1]; //assign value to index
	}
	/*
	//echo results
	echo "<br />-------------------------<br />";
	echo "i: " . $i . "<br />";
	echo $targets_shuffled[$i] . " matched with " . $targets_shuffled_copy[$i];
	echo "<br />-------------------------<br /><br />";
	*/
	$i++;
}

 

This works well enough for me. Thanks for your help and ideas.

-Blake

Link to comment
Share on other sites

You could also use array functions to do the manipulation of the randomised array. E.g.

 

// Shuffle the player names
$shuffled = $targets;
shuffle($shuffled);

// Create partners by rotating the randomly ordered names
$partners   = $shuffled;
$partners[] = array_shift($partners);

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.