• 0

PHP Loops and falls


Question

I am trying to create a coin flip game not using anything but one single script (no external scripts, no Databases or anything...or this would be easy...)

 

basically my game will sometimes get stuck in a loop (alot of the time) and others it will work fine..and the game will have a winner...if the game gets stuck in a loop (what I assume is a loop) it will just die... here is my code....any suggestions? 

 

I actually fixed my own code! (yay me) ...but I also broke it (boo me) ...loops no longer go on for ever...but I player names sometimes dont show and I do not know why...

 

new code:

<?php
$input = 51;
$round = 0;
$colours = array('red','yellow','green','blue','orange','pink','black','white');
$playersPerTeam = (int)($input / count($teams));
$teams = array();
$coin = array('heads' ,'tails');
$oddOuts = array('0');
foreach($colours as $colour)
{
$teams[] = array();
}

$playersPerTeam = (int)($input / count($teams));
$remainingPlayers = $input % count($teams);
$inputNoMod = $playersPerTeam * count($teams);
$players = array();
for($i=1;$i<$input+1;$i++) //populate array with number of players
{
	$players[] = "player".$i;
}
shuffle($players); //randomly order the players
$currentArray = -1;
for($o=0;$o<$inputNoMod;$o++) //organise teams
{
	
	if(($o % $playersPerTeam) == 0)
		$currentArray++;
		
	$teams[$currentArray][] = $players[$o];
	
}
for($o=0;$o<$remainingPlayers;$o++) //organise teams / left overs from not nice numbers
{
	$num = mt_rand(0, count($teams)-1);
	
	if (in_array($num, $oddOuts))
	{
		$o--;
	}
	else
	{
		$oddOuts[] = $num;
	}
}
$leftOvers = array_slice($players, -$remainingPlayers, $remainingPlayers, true);
$odds = 1;

foreach($leftOvers as $one)
{
	$teams[$oddOuts[$odds]][] = $one;
	$odds++;
}



/////////////
/////////////
/////////////
/////////////
$teams = play($teams, $coin, $colours, $input);
/////////////
function play($teams, $coin, $colours, $input)
{
	$forLoopNum = (int)($input / 2);
	$left = $input % 2;
	$input = $left + $forLoopNum;
	$battles = array();
	$currentCounter = 0;
	echo "<table border='1'>";
	echo "<tr><td>Match ID</td> <td>TEAM ONE</td> <td>Player</td><td>heads or tails?</td><td>--</td><td>TEAM TWO</td><td>Player</td><td>heads or tails?
	</td><td>Winner</td></tr>";
	
	
	for ($i=0;$i<$forLoopNum;$i++)
	{ 
			$choose = array();

			foreach($teams as $key => $val)
			{
				$choose[] = $key;
			}
			$t1 = array_rand($choose);
			unset($choose[$t1]);
			$t2 = array_rand($choose);
			unset($choose[$t2]);
			
		
			$p1 = array_rand($teams[$t1]);
			$p2 = array_rand($teams[$t2]);
			$p1 = $teams[$t1][$p1];
			$p2 = $teams[$t2][$p2];
			$key1 = array_search($p1, $teams[$t1]);
			$key2 = array_search($p2, $teams[$t2]);
			unset($teams[$t1][$key1]);
			unset($teams[$t2][$key2]);
			$arrayT1Length = count($teams[$t1]);
			$arrayT2Length = count($teams[$t2]);
			if ($arrayT1Length == '0')
				unset($teams[$t1]);
			if ($arrayT2Length == '0')
				unset($teams[$t2]);
				
			$winner = 0;
			$coinP1 = mt_rand(0, 1);
			$coinP2 = 1;
			if ($coinP1 == 1)
				$coinP2 = 0;
				
			$flip = mt_rand(0, 1);
			
			if($flip == $coinP1)
			{
				$winner = $p1;
				$battles[$t1][] = $p1;
			}	
			else
			{
				$winner = $p2;
				$battles[$t2][] = $p2;
			}	
			echo "<tr><td>".$i."</td><td>".$colours[$t1]."</td><td>".$p1."</td><td>".$coin[$coinP1]."</td><td><b>VS</b></td><td>".$colours[$t2]."</td><td>".$p2."</td><td>".$coin[$coinP2]."</td><td>".$winner."</td></tr>";
	}
	echo "</table><br><br><br>";
	if (count($teams) > 0)
	{
		foreach ($teams as $key=>$val)
		{
			foreach($val as $keys=>$vals)
			{
				$battles[$key][] = $teams[$key][$keys];
			}
		}
	}
	//echo $input;
	if ($input > 5)
		$battles = play($battles, $coin, $colours, $input);
		
	return $battles;
}
?> 

old code:

<?php
$input = 51;
$round = 0;
$colours = array('red','yellow','green','blue','orange','pink','black','white');
$playersPerTeam = (int)($input / count($teams));
$teams = array();
$coin = array('heads' ,'tails');
$oddOuts = array('0');
foreach($colours as $colour)
{
$teams[] = array();
}

$playersPerTeam = (int)($input / count($teams));
$remainingPlayers = $input % count($teams);
$inputNoMod = $playersPerTeam * count($teams);
$players = array();
for($i=1;$i<$input+1;$i++) //populate array with number of players
{
	$players[] = "player".$i;
}
shuffle($players); //randomly order the players
$currentArray = -1;
for($o=0;$o<$inputNoMod;$o++) //organise teams
{
	
	if(($o % $playersPerTeam) == 0)
		$currentArray++;
		
	$teams[$currentArray][] = $players[$o];
	
}
for($o=0;$o<$remainingPlayers;$o++) //organise teams
{
	$num = mt_rand(0, count($teams)-1);
	
	if (in_array($num, $oddOuts))
	{
		$o--;
	}
	else
	{
		$oddOuts[] = $num;
	}
}
$leftOvers = array_slice($players, -$remainingPlayers, $remainingPlayers, true);
$odds = 1;

foreach($leftOvers as $one)
{
	$teams[$oddOuts[$odds]][] = $one;
	$odds++;
}



/////////////
/////////////
/////////////
/////////////
$teams = play($teams, $coin, $colours, $input);
/////////////
function play($teams, $coin, $colours, $input) //THIS IS THE FUNCTION WHICH GETS STUCK
{
	$forLoopNum = (int)($input / 2);
	$left = $input % 2;
	$input = $left + $forLoopNum;
	$battles = array();
	$currentCounter = 0;
	echo "<table border='1'>";
	echo "<tr><td>Match ID</td> <td>TEAM ONE</td> <td>Player</td><td>heads or tails?</td><td>--</td><td>TEAM TWO</td><td>Player</td><td>heads or tails?
	</td><td>Winner</td></tr>";
	for ($i=0;$i<$forLoopNum;$i++) //LOOP OF DEATH <<---
	{ 
			$currentCount = 0;
			$t1 = array_rand($teams);

					foreach($teams as $val)
					{
						$currentCount = $currentCount + count($val);
						$currentCounter = $currentCount + count($val);
					}
					//echo "current count ".$currentCount."<br><br>";
					foreach($teams as $key => $val)
					{
						if(count($key) >= (int)($currentCount / 2))
						{
							$t1 = $key;
						}
						
					}	
			$t2 = array_rand($teams);
			while (count($teams[$t1]) == '0')
			{
				$t1 = array_rand($teams);
			}
			while (count($teams[$t2]) == '0'|| $t2 == $t1)
			{
				$t2 = array_rand($teams);
			}
			$p1 = array_rand($teams[$t1]);
			$p2 = array_rand($teams[$t2]);
			$p1 = $teams[$t1][$p1];
			$p2 = $teams[$t2][$p2];
			$key1 = array_search($p1, $teams[$t1]);
			$key2 = array_search($p2, $teams[$t2]);
			unset($teams[$t1][$key1]);
			unset($teams[$t2][$key2]);
			$arrayT1Length = count($teams[$t1]);
			$arrayT2Length = count($teams[$t2]);
			if ($arrayT1Length == '0')
				unset($teams[$t1]);
			if ($arrayT2Length == '0')
				unset($teams[$t2]);
				
			$winner = 0;
			$coinP1 = mt_rand(0, 1);
			$coinP2 = 1;
			if ($coinP1 == 1)
				$coinP2 = 0;
				
			$flip = mt_rand(0, 1);
			
			if($flip == $coinP1)
			{
				$winner = $p1;
				$battles[$t1][] = $p1;
			}	
			else
			{
				$winner = $p2;
				$battles[$t2][] = $p2;
			}	
			echo "<tr><td>".$i."</td><td>".$colours[$t1]."</td><td>".$p1."</td><td>".$coin[$coinP1]."</td><td><b>VS</b></td><td>".$colours[$t2]."</td><td>".$p2."</td><td>".$coin[$coinP2]."</td><td>".$winner."</td></tr>";
	}
	echo "</table><br><br><br>";
	if (count($teams) > 0)
	{
		foreach ($teams as $key=>$val)
		{
			foreach($val as $keys=>$vals)
			{
				$battles[$key][] = $teams[$key][$keys];
			}
		}
	}
	//echo $input;
	if ($input > 5)
		$battles = play($battles, $coin, $colours, $input);
		
		echo $input."!!!!!!!!<br>";
	return $battles;
}
?>

This isnt all of my code there is a function which does the semi final... but its not important here as i built it when this bug existed...helps!? (sorry for lack of comments)

Link to comment
Share on other sites

4 answers to this question

Recommended Posts

  • 0

First, if you're not already, I would recommend turning on the display of errors and warnings - when I run that PHP file there are several that get thrown. That can help narrow down why the script is performing unexpectedly.

 

As for your issue, I believe it lies at the beginning of the for loop in your play() function. Here's what I think is happening:

  1. You create the $choose array and then add each team number to the array one at a time, which means that at the start of the tournament $choose = [0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7]
  2. You assign $t1 and $t2 to random keys from $choose using array_rand(), which works fine at first because the keys for $choose match the keys for $teams.
  3. As you play games, you remove players from their teams. When all players in a team have played, you remove the team from the $teams array
  4. Once an entire team has played, however, at the start of the next round (say Team #4 has been removed) $choose = [0=>0, 1=>1, 2=>2, 3=>3, 4=>5, 5=>6, 6=>7] because you add the team numbers to $choose using $choose[], which auto-assigns the index (key) in the array. This means that array_rand($choose) could return 4 in this instance because there are more than 4 teams, even though team 4 has no more players that can play.
  5. Trying to force a team to play when that team's players have all already played is a clear violation of the International Federation of Coin Flipping, thus your errors.

My suggestion would be to get rid of the whole $choose set of code, and instead take advantage of the fact that array_rand() can return more than one random key, and pull the team numbers directly from $teams instead of building an intermediate $choose:

list($t1, $t2) = array_rand($teams, 2);
Link to comment
Share on other sites

  • 0

 

First, if you're not already, I would recommend turning on the display of errors and warnings - when I run that PHP file there are several that get thrown. That can help narrow down why the script is performing unexpectedly.

 

As for your issue, I believe it lies at the beginning of the for loop in your play() function. Here's what I think is happening:

  1. You create the $choose array and then add each team number to the array one at a time, which means that at the start of the tournament $choose = [0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7]
  2. You assign $t1 and $t2 to random keys from $choose using array_rand(), which works fine at first because the keys for $choose match the keys for $teams.
  3. As you play games, you remove players from their teams. When all players in a team have played, you remove the team from the $teams array
  4. Once an entire team has played, however, at the start of the next round (say Team #4 has been removed) $choose = [0=>0, 1=>1, 2=>2, 3=>3, 4=>5, 5=>6, 6=>7] because you add the team numbers to $choose using $choose[], which auto-assigns the index (key) in the array. This means that array_rand($choose) could return 4 in this instance because there are more than 4 teams, even though team 4 has no more players that can play.
  5. Trying to force a team to play when that team's players have all already played is a clear violation of the International Federation of Coin Flipping, thus your errors.

My suggestion would be to get rid of the whole $choose set of code, and instead take advantage of the fact that array_rand() can return more than one random key, and pull the team numbers directly from $teams instead of building an intermediate $choose:

list($t1, $t2) = array_rand($teams, 2);

 

well balls. which I knew this earlier.... lol in your opinion though what do you think of my logic .... good? bad? this was a logic test i had to do for a job....they have given me a second interview because they liked it though they are slightly concerned with some of my logic. ( though i only had like 1-2 hours solid work on it but in the eyes of the employer i had a week...)...

 

list($t1, $t2) = array_rand($teams, 2); and this here... can you explain it abit more... does it choose two unique randoms? also correct me if i am wrong, but setting the keys manually like i did in the foreach should mean they keep the keys rather than step down ? I thought? 

Link to comment
Share on other sites

  • 0

well balls. which I knew this earlier.... lol in your opinion though what do you think of my logic .... good? bad? this was a logic test i had to do for a job....they have given me a second interview because they liked it though they are slightly concerned with some of my logic. ( though i only had like 1-2 hours solid work on it but in the eyes of the employer i had a week...)...

 

list($t1, $t2) = array_rand($teams, 2); and this here... can you explain it abit more... does it choose two unique randoms? also correct me if i am wrong, but setting the keys manually like i did in the foreach should mean they keep the keys rather than step down ? I thought? 

oh and btw... I did edit $choose[] = $key ... to $choose[$key] = $key

Link to comment
Share on other sites

  • 0

list() is a quick way to create a variable for each value in an array (see http://php.net/list), so...

list($t1, $t2) = array_rand($teams, 2)

 could also be expressed as:

$temp = array_rand($teams, 2);
$t1 = $temp[0];
$t2 = $temp[1];

array_rand($teams, 2) will return 2 (different) random keys from $teams, so you get the same end result that your revised $choose code would (if you build $choose with $choose[$key] instead of $choose[]), with less code (and thus less chance for logic errors like you have). 

 

Without knowing the input/output parameters for the task, your code appears correct, if somewhat inefficient and/or convoluted in places (i.e. writing code to accomplish something that could be done by a built-in PHP function, or doing unnecessary extra work like $key1 = array_search($p1, $teams[$t1]); when you already had the correct value two lines above it with $p1 = array_rand($teams[$t1])). It's hard to evaluate the quality of your code without knowing what the requirements are - I don't know how much of what you're doing is because of a requirement or because that's how you chose to do it.

Link to comment
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.