Location: PHPKode > scripts > Bingoware > bingoware/functions.php
<? 

include ("settings.php");

/** set_exists()
* This function tests the existence of a card set,
* corresponding to the $setid in the config file
*/
function set_exists() {
	global $setid;
	return (file_exists("set.".$setid.".dat"));
}

/** card_number()
* This function returns the number of cards found in the card set
* user must verify that set exists before calling this function.
* This function will reload the set from the disk.  Use 
* count($set) if you already opened and loaded the set to fasten
* the process 
*/
function card_number() {
	$set=load_set();
	if (is_array($set))
		return count($set);
}

/** generate_cards()
* This function generate the appropriate number of cards
* All cards are randomly generated, and have a Free square
* in the center.  The function saves the newly created set.
* This function will overwrite an existing set with the same
* setid.
*/
function generate_cards($numbercards) {
	global $freesquare;

	for ($cardnumber = 0; $cardnumber <$numbercards; $cardnumber++) {
		
		// The next two variables are only used when freesquare == 2 (random location)
		$randcolumn = rand(0,4); 
		$randrow = rand(0,4);
		
		for ($column = 0; $column<5; $column++) {
			for ($row = 0; $row<5; $row++) {
				if (($column==2) && ($row == 2) && ($freesquare==1)) {  //free
					$set[$cardnumber][$column][$row]["number"] = "Free";  //free
					$set[$cardnumber][$column][$row]["checked"] = true;  //free
				}
				else if (($column==$randcolumn) && ($row==$randrow) && ($freesquare==2)){
					$set[$cardnumber][$column][$row]["number"] = "Free";  //free
					$set[$cardnumber][$column][$row]["checked"] = true;  //free
				}
				else {
					//to ensure we do not have the same number twice in one column
					$numberexists = true; //loop entry
					while ($numberexists) {
						$random = rand(1+$column*15,($column+1)*15);
						
						$numberexists =false; //assume it is not repeated until it is found
						for ($checker=0; $checker<$row; $checker++)
							if ($set[$cardnumber][$column][$checker]["number"] == $random) $numberexists=true;
					}

					$set[$cardnumber][$column][$row]["number"] = $random;
					$set[$cardnumber][$column][$row]["checked"] = false;
				}
			} //row
		} //column
	}	//cardnumbber
	
	save_set($set);
}

/** display_card()
* This function draws an HTML table for one or four cards.
* By setting the $fourperpage parameter to 1, the tables
* are drawn smaller.
*/
function display_card ($cardnumber,$fourperpage=0) {
	global $bingoletters, $setid;
	
	$set = load_set();  //normal cards

	if (is_array($set)) {
		
		echo "<center><table width=".(($fourperpage)?"300":"75%")." border=1 cellpadding=".(($fourperpage)?"4":"20")." bgcolor=\"silver\" BORDERCOLOR=\"#FF0000\"><tr>";
		//header
		for ($column = 0; $column<5; $column++) { 
				echo '<td  width="20%" align="center" bgcolor="#dd00dd"><b><font size=+'.(($fourperpage)?'2>':'7>').$bingoletters[$column].'</font></b></td>';
		}
		echo "</tr>";

		//table
		for ($row = 0; $row<5; $row++) {
			echo "<tr>";
			
			for ($column = 0; $column<5; $column++) { //column has to be inner loop due to HTML table
				echo "\n<td align=center bgcolor=\"".($set[$cardnumber][$column][$row]["checked"]?"#eeee00":"silver")."\">";
				if ($fourperpage) echo '<font size=+'.(($set[$cardnumber][$column][$row]["number"]=="Free")?'1':'3').'>';
				else echo '<font size=+'.(($set[$cardnumber][$column][$row]["number"]=="Free")?'2':'5').'>';
				echo $set[$cardnumber][$column][$row]["number"].'</font></td>';
			}
			echo "</tr>";
		}
		echo "</table><table width=".(($fourperpage)?"65%>":"75%>");
		printf("<tr><td align=right colspan=5><font size=-2> Card Number: %s%'04s </font></td></tr>",$setid,$cardnumber+1);
		echo "</table></center>";
		
	}
	else echo "set could not be opened";
}

/** random_number()
* This function generates a new random number.
* The number is unique: the function checks the draws.xx.dat file
* and loops until a new number randomly generated.
* The file draws.xx.dat is resorted and rewritten before the end of the function
* so it includes the new number.
* The function calls mark_cards() to have the new number set in all
* cards, and call check_bingo() to update the winners' list.
*/
function random_number($numberinplay) {
	global $bingoletters;
	
	$draws = load_draws();

	if ($draws!=null){
		$total=count($draws);
	} else $total=0;
	
	$samenumbertwice= true;
	while ($samenumbertwice) {
		
		$col = rand(0,4);
		$row = rand(1,15);
		$num = 15*$col+$row;
		
		$samenumbertwice=false;
		
		 if ($total >0 ) //no need to check if we have no numbers yet
		 	for ($i=0;$i < $total; $i++)
				if ($num==$draws[$i]) $samenumbertwice=true;
	}
	$draws[$total]=$num;
	save_draws($draws);
	
	mark_cards($col,$num);
	check_bingo($numberinplay);
	return $bingoletters[$col].$num;
}

/** submit_number()
* This function is used in manual mode to enter a number into the draw list.
* The file draws.xx.dat is resorted and rewritten before the end of the function
* so it includes the new number.
* The function calls mark_cards() to have the new number set in all
* cards, and call check_bingo() to update the winners' list.
*/
function submit_number($number,$numberinplay) {
	global $bingoletters;
	$draws = load_draws();
	
	if ($draws!=null){
		$total=count($draws);
	} else $total=0;
		
	$samenumbertwice=false;
	
	//extract the number out of the input string
	$convert = intval(substr($number,1));	
	
	if ($total >0 ) //no need to check if we have no numbers yet
		 	for ($i=0;$i < $total; $i++)
				if ($convert==$draws[$i]) $samenumbertwice=true;

	if (!$samenumbertwice) {
		
		$draws[$total]=$convert;
		save_draws($draws);
		
		mark_cards(array_search(strtoupper(substr($number,0,1)),$bingoletters),$convert);
		check_bingo($numberinplay);
	} else echo '<font color="#ff3300"><b>This number has already been entered, please verify and enter a new number</b><br><hr></font>';
}


/** mark_cards()
* This function will "color" a given number on all cards
* that possess this number.  The card set will be resaved
* before the end of the function.
* This function should be called before check_bingo() which
* determine winning cards.
*/
function mark_cards($col, $num) { //col provided here to speed up search in the right column only
	
	$set = load_set();
	$numcards=count($set);
	
	for ($n=0; $n<$numcards;$n++) {
		for ($r=0; $r<=4; $r++) { //go down the given column
			if ($set[$n][$col][$r]["number"]==$num) 
				$set[$n][$col][$r]["checked"]=true;	
		}
	}
	save_set($set);
}

/** check_bingo()
* This function goes through the complete set and attempts to find
* winning cards.
* Winning cards are cards that match the current winning pattern.
* The winning cards are saved to the file winners.xx.dat and the file
* is re-written each time.
*/
function check_bingo ($numberinplay) {
	global $winningpattern;
	global $setid;
	
	$set=load_set();
	$numcards = count($set);
	
	$currentwinners = load_winners();
	
	//refresh the new winner list
	@unlink("new_winners.".$setid.".dat");//erase the new winners file

	
	//if a numberinplay is given, which is smaller than the the number
	// of cards in the set, the rest of the cards are not verified.
	for ($n=0; $n<min($numberinplay,$numcards);$n++) {

		if (!(@in_array($n+1,$currentwinners))) {  //avoids the warning if there are no winners yet
		
			switch ($winningpattern) {
				
				case 0: //normal bingo
					$bingo=false;
					for ($c=0; $c<5; $c++) {
						$rowbingo=true; //assume there is bingo in rows and prove wrong
						$colbingo=true; //assume there is bingo in columns and prove wrong
						for ($r=0; $r<5;	$r++) {
							if (!$set[$n][$c][$r]["checked"]) $colbingo=false; //as soon as one is not checked
							if (!$set[$n][$r][$c]["checked"]) $rowbingo=false; //as soon as one is not checked
						} //end of that column/row, if we still have either bingo, we have a winner
						if ($rowbingo||$colbingo){
							$bingo=true;
							break; //no need to keep checking
						}
					}
					
					if (!$bingo) { //if it is not a winner already, will check the diagonals
						$bingod1=true; //assume there is bingo in diagonals, prove wrong
						$bingod2=true;
						for ($d=0; $d<5 ; $d++) {
							if (!$set[$n][$d][$d]["checked"]) $bingod1=false; //as soon as one item from diagonal is not checked
							if (!$set[$n][$d][4-$d]["checked"]) $bingod2=false;
						}
						if ($bingod1||$bingod2) {
							$bingo=true;
						}
					}
					break; //from case 0
				
				default: 
					//for any other case, check all the "winning squares" against the current card
					//by loading the appropriate card of the "winningpatterns" set
					//stop at the first unmatching square
					$bingo=true; //assume true until one square not checked
					$winningset = load_winning_patterns();
					
					for ($c=0; $c<5; $c++) {
						for ($r=0; $r<5;	$r++) {
							if ($winningset[$winningpattern-1][$c][$r]["checked"] && !$set[$n][$c][$r]["checked"]) {
								$bingo=false; //as soon as one is not checked
								break 3; //break from loop 1, loop 2 and default case
							}
						} 
					}
					break; //from case else
			} //end switch
			
			if ($bingo){ //for the current card
				$newwinners[count($newwinners)]=($n+1);
			} //if bingo
		}
	} //for each card
	
	if (count($newwinners)>0) {
		save_new_winners($newwinners);
		save_winners(array_merge($currentwinners,$newwinners));
	}
}

/** restart()
* This function allows one to restart the game mode.
* Current list of winners will be erased, as well as all drawn numbers.
* The card set will remain untouched, but all "colours" will be reset, except
* for the free square. Very useful if you are using the same set of bingo cards for
* several games.
*/
function restart() { //erases winners, draws, and clears all cards but keeps numbers
	global $setid;
	
	@unlink ("winners.".$setid.".dat");
	@unlink ("new_winners.".$setid.".dat");
	@unlink("draws.".$setid.".dat");
	
	if (set_exists()) {
		$set = load_set();
		$numcards=count($set);
		
		for ($n=0; $n<$numcards;$n++) {
			for ($c=0; $c<5; $c++) { 
				for ($r=0; $r<5; $r++) { //go down the column
					$set[$n][$c][$r]["checked"]=($set[$n][$c][$r]["number"]=="Free"); //don't forget the free
					
				}
			}
		}
		save_set($set);
	}

}

/** draws_table()
* This function generates an HTML table of all numbers drawn.
* It is used in game mode on the right side. The file containing the
* numbers drawn (draws.xx.dat) is already sorted.
*/
function draws_table() { //table of all numbers drawn
	$draws = load_draws();
	
	echo '<table width="100%" border=1 cols=5><tr>';
	if ($draws!=null) {
		$number = count($draws);
	
		for ($i =0; $i<$number; $i++) {
			echo '<td align=center width="20%">'.find_letter($draws[$i]).$draws[$i].'</td>';
			if (($i+1)%5==0) echo "</tr><tr>";
		}
	} else echo "<td>No numbers drawn yet</td>";
	echo '</tr></table>';
}

/** winners_table()
* This function generates an HTML table of all winning cards.
* It is used in game mode at the bottom. 
* Each winning card number is displayed with its view link.
*/
function winners_table() {
	$winners = load_winners();
	$new_winners = load_new_winners(); //to be indicated in a different color
	
	echo '<table width="100%" border=1><tr>';
	
	if ($winners!=null) {
		$number = count($winners);

		for ($i =0; $i<$number; $i++) {
			
			$color= ((@in_array($winners[$i],$new_winners))? "#ff0000" :"#ffffff"); 
			echo '<td align=center width="20%"><a href="view.php?cardnumber='.$winners[$i].'" target=_blank><FONT color="'.$color.'">'.$winners[$i].'</font></a></td>';
			if (($i+1)%5==0) echo "</tr><tr>";
		}
	}
	else echo "<td>No winners yet!</td>";
	echo '</tr></table>';
}



/** find_letter()
* This function returns the letter associated with the 
* bingo number passed as a parameter (1 to 75): B, I, N, G or O
*/
function find_letter($num) {
	global $bingoletters;
	return $bingoletters[intval(($num-1) /15)];
}


/** load_set()
* This function attemps to load the card set  
* from the file set.xx.dat where xx is the setid.
*/
function load_set() {
	global $setid;
	if (set_exists()) {	
		$filearray = file("set.".$setid.".dat");
		for ($i=0; $i< $filearray[0]; $i++) { //first row is number of rows
			$set[$i] = unserialize($filearray[$i+1]);
		}
		return $set;
	} else {
		echo "set could not be loaded";
		return null;
	}
}

/** save_set()
* This function attemps to save the card set
* to the file set.xx.dat where xx is the setid.
* Error msgs were removed because the demo
* on sourceforge.net cannot save files.
* The file is written by serializing each card onto a different line
* Serializing the whole set table also works, but the file
* is a lot more difficult to observe with a text editor.
*/
function save_set(&$set) {
	global $setid;
	$numcards = count($set);
		
	if (@$fp = fopen("set.".$setid.".dat","w")) {
		
		fwrite($fp,$numcards."\n");
		for ($i =0; $i<$numcards; $i++) {
			fwrite($fp, serialize($set[$i])."\n");  //one card per row
		}
		fclose($fp);
		return true;
	}
}

/** load_draws()
* This function attemps to load the series of numbers drawn
* from the file draws.xx.dat where xx is the setid.
*/
function load_draws() {
	global $setid;
	if (@file_exists("draws.".$setid.".dat")){
		$filearray=file("draws.".$setid.".dat");
		$draws = unserialize($filearray[0]);
		return $draws;
	} else return null;
}

/** save_draws()
* This function attemps to save the series of numbers drawn 
* to the file draws.xx.dat where xx is the setid.
* Error msgs were removed because the demo
* on sourceforge.net cannot save files.
* The file is written by serializing the whole
* draws table, once sorted.
*/
function save_draws(&$draws) {
	global $setid;
	
	sort($draws);
	if (@$fp=fopen("draws.".$setid.".dat","w")) {
		fwrite($fp, serialize($draws));
		fclose($fp);
	} 
}

/** load_winners()
* This function attemps to load the series of winning card numbers 
* from the file winners.xx.dat where xx is the setid.
*/
function load_winners() {
	global $setid;
	if (@file_exists("winners.".$setid.".dat")){
		$filearray=file("winners.".$setid.".dat");
		$winners = unserialize($filearray[0]);
		return $winners;
	} else return null;
}

/** save_winners()
* This function attemps to save the series of winning cards 
* to the file winners.xx.dat where xx is the setid.
* Error msgs were removed because the demo
* on sourceforge.net cannot save files.
* The file is written by serializing the whole
* winners table.
*/
function save_winners(&$winners) {
	global $setid;
	sort($winners);
	
	if (@$fp=fopen("winners.".$setid.".dat","w")) {
		fwrite($fp, serialize($winners));
		fclose($fp);
	} 		
}

/** load_new_winners()
* This function attemps to load the series of new winning card numbers
* from the file new_winners.xx.dat where xx is the setid.
*/
function load_new_winners() {
	global $setid;
	if (@file_exists("new_winners.".$setid.".dat")){
		$filearray=file("new_winners.".$setid.".dat");
		$new_winners = unserialize($filearray[0]);
		return $new_winners;
	} else return null;
}
/** save_new_winners()
* This function attemps to save the series of new winning cards 
* to the file new_winners.xx.dat where xx is the setid.
* Error msgs were removed because the demo
* on sourceforge.net cannot save files.
* The file is written by serializing the table containing the new
* winners table.
*/
function save_new_winners(&$new_winners) {
	global $setid;

	if (@$fp=fopen("new_winners.".$setid.".dat","w")) {
		fwrite($fp, serialize($new_winners));
		fclose($fp);
	} 		
}

/** load_winning_patterns()
* This function attemps to load the winning patterns set (winningpatterns.dat) which contains 
* all winning patterns, with the exception of the normal winning pattern (pattern 0)
* (any row, any column, any diagonal).  The set is loaded when the user wishes to preview
* customize a given winning pattern.
*/
function load_winning_patterns() {

	if (file_exists("winningpatterns.dat")) {	
		$filearray = file("winningpatterns.dat");
		for ($i=0; $i< $filearray[0]; $i++) { //first row is number of rows
			$set[$i] = unserialize($filearray[$i+1]);
		}
		return $set;
	} else {
		echo "set could not be loaded";
		return null;
	}	
}


/** update_winning_patterns()
* This function updates the given $cardnumber within the "winningp atterns" set based
* on the information graphically entered from the web page.  The squares selected on the
* interactive web page are converted to a hidden string.  The string is passed to this
* function as a parameter, along with the pattern number chosen.  The set is updated
* to "check" all squares that were selected by the user.
* The functions saves the previewpatterns set prior to exiting.
*/
function update_winning_patterns($hiddenstring, $cardnumber) {
	global $bingoletters;
	
	@$winningset=load_winning_patterns();

	if (is_array($winningset)) {

		for ($row = 0; $row<5; $row++) {
			for ($column = 0; $column<5; $column++) { 
				
				//eg. if B0 is in the string, then we must ensure that square becomes checked in
				//the first card of the previewpattern set
				if (ereg(($bingoletters[$column].$row),$hiddenstring)) {
					$winningset[$cardnumber][$column][$row]["checked"]=true;
				} else $winningset[$cardnumber][$column][$row]["checked"]=false; 
			}
		}
		save_winning_patterns($winningset);
	}	
}

/** save_winning_patterns()
* This function attemps to save the pattern preview set  
* to the winningpatterns.dat file, a carefully crafted file that stores all winning patterns.
* with the exception of the normal winning pattern (pattern 0) which is not easily represented
* (any row, any column, any diagonal).  This function is called once the user has selected 
* the squares of the winning pattern from the GUI.  The string of winning squares is converted
* from the interactive form with the function call update_winning_patterns() and then saved here
*/
function save_winning_patterns(&$set) {
	if (file_exists("winningpatterns.dat")) {	
		//we must first open the file in reading to determine the number of rows
		
		$filearray = file("winningpatterns.dat");
		$numcards= trim($filearray[0]);
	
		//then we write the appropriate number of cards in the previewpatterns set
		if (@$fp=fopen("winningpatterns.dat","w")) {
			fwrite($fp,$numcards."\n");
			for ($i =0; $i<$numcards; $i++) {
				fwrite($fp, serialize($set[$i])."\n");  //one card per row
			}
			fclose($fp);
		} 	
	}	
}


/** display_interactive_card()
* function similar to display_card() that is called when the user wishes
* to preview or customize one of the "winning patterns".  The technique
* used to customize the winning pattern involves Javascript and CSS components
* that are not supported by Netscape 4 (Opera 6 and IE 6 have been tested and
* are fully compatible.  The card is an HTML table in which the cells react to mouse
* clicks.  When the card is first loaded, the information is retreived from the
* winningpatterns.dat set and is represented visually on the screen.  A string
* is generated from the "checked cell" and stored (hidden) in the form.  When the user 
* clicks a cell from the table, its color is reversed, and the hidden string is truncated 
* or expanded with the name of the chosen cell.  When the form is submitted, the 
* updated winningpatterns.dat file is saved.
* This function returns a string composed of the names of the selected cell of the given
* card in the winningpatterns.dat file: eg. B0;I0;N0;N1;N2;N3;N4;G0;O0 would be returned
* if the T-shaped winning pattern was selected.
*/
function display_interactive_card($cardnumber) {
	global $bingoletters;
	
	@$winningset=load_winning_patterns(); //display a pattern preview

	if (is_array($winningset)) {
		
		echo '<center><table width="75%" border="1" cellpadding="20" bgcolor="silver" bordercolor="red"><tr>';
		//header
		for ($column = 0; $column<5; $column++) { 
				echo '<td  width="20%" align="center" bgcolor="#dd00dd"><b><font size="+7">'.$bingoletters[$column].'</font></b></td>';
		}
		echo "</tr>";

		//table
		for ($row = 0; $row<5; $row++) {
			echo "<tr>\n";
			
			for ($column = 0; $column<5; $column++) { //column has to be inner loop due to HTML table
				echo "\n<td align=\"center\" style=\"background:".($winningset[$cardnumber][$column][$row]["checked"]?"#eeee00;":"silver;")."\" onClick = \"this.style.background=clickcell(this.style.background,'".$bingoletters[$column].$row."')\">";
				echo '<font size="+5">';
				echo $winningset[$cardnumber][$column][$row]["number"].'</font></td>';
				if ($winningset[$cardnumber][$column][$row]["checked"]) $hiddenstring.=($bingoletters[$column].$row.';');
			}
			echo "</tr>";
		}
		echo "</table></center>";
		
	}
	else echo "set could not be opened";
	return $hiddenstring;
}


?>
Return current item: Bingoware