PHP Bingo Cards
My wife is the room parent for my daughter's first grade class, and an hour ago she was trying to print off bingo cards for the kid's Valentine's Day party this week. The problem was the site she was using to print the template had a link to a site that no longer existed. Using the Wayback Machine I was able to find a cached version of the cards, but it was a static image, which means every card would be the same - what fun would that be? So, after taking a quick look at the card I told her to wait ten minutes and I'd work out a solution; here is what I created (use the refresh button to randomize the cards).
It was a simple enough bit of code, but I thought I'd share it in case others are looking for a way to create BINGO cards from home. You can view the source at the link above to see how I styled the page, but lets peek under the hood at the PHP code I created to generate these cards.
# create array of numbers for the cards, 1-75 $numbers = range(1,75); # setup templates $table = '<table cellspacing="0" cellpadding="0"><tr><th>H</th><th>E</th><th>A</th><th>R</th><th>T</th></tr>%rows%</table>'; $row = '<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>'; $center = '<tr><td>%s</td><td>%s</td><td>FREE</td><td>%s</td><td>%s</td></tr>'; # vars to hold formatted templates after loops $cards = ''; $rows = ''; # shuffle array to randomize numbers shuffle($numbers); # set a counting var for moving through the numbers array $n = 0; # four cards to a sheet, create a four step loop for ( $c=0; $c<4; $c++ ) { # for each card loop through five times to build each row of numbers # start iteration at 1 to make it easier to read for ( $i=1; $i<6; $i++ ) { # if this is the center row (3) use a different template with free space $template = ( $i==3 ) ? $center : $row; # create array to hold numbers for this row $num = array(); # loop through the numbers array five at a time to build row numbers for ( $d=0; $d<5; $d++ ) { # if the number counter is already at the end of the numbers array reset and rehuffle # important so the fourth card properly displays and isn't a duplicate of the first card if ( $n == 75 ) { shuffle($numbers); $n = 0; } # add number to array for the row and increment pointer for numbers array by 1 $num[] = $numbers[$n]; $n++; } # add row to rows var $rows .= sprintf($template,$num[0],$num[1],$num[2],$num[3],$num[4]); } # add card to cards var and reset rows var for next card pass $cards .= str_replace('%rows%',$rows,$table); $rows = ''; }
Let's take this one step at a time, first I create an array holding 75 numbers:
# create array of numbers for the cards, 1-75 $numbers = range(1,75);
This will be used to populate the rows of our cards. Next I setup the templates for output using the PHP sprintf format:
# setup templates $table = '<table cellspacing="0" cellpadding="0"><tr><th>H</th><th>E</th><th>A</th><th>R</th><th>T</th></tr>%rows%</table>'; $row = '<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>'; $center = '<tr><td>%s</td><td>%s</td><td>FREE</td><td>%s</td><td>%s</td></tr>';
You can replace the text in the $table var's table header cells to something more appropriate, but as I stated this was for the kid's Valentine's Day party so my wife wanted it to say HEART instead of BINGO. Next I setup a few vars that will hold our formatted output, randomize the array using the PHP shuffle function, and set a counting var that will enable the script to iterate through the $numbers array as we loop through each row and card:
# vars to hold formatted templates after loops $cards = ''; $rows = ''; # shuffle array to randomize numbers shuffle($numbers); # set a counting var for moving through the numbers array $n = 0;
Now we begin our loops, first we want four cards to a page to cut down on printing, so we build a simple for loop and begin with the first card:
# four cards to a sheet, create a four step loop for ( $c=0; $c<4; $c++ )
Next we loop through each row on the card:
# for each card loop through five times to build each row of numbers # start iteration at 1 to make it easier to read for ( $i=1; $i<6; $i++ )
I decided to start the counting at 1 to make it easier to read, because on the third row we want to use the center row template setup above which has the free spot:
# if this is the center row (3) use a different template with free space $template = ( $i==3 ) ? $center : $row;
Now lets build a new array that will hold the 5 numbers we're going to grab from the shuffled numbers array to use in this row, then setup a for loop to go through the first 5 numbers in the numbers array:
# create array to hold numbers for this row $num = array(); # loop through the numbers array five at a time to build row numbers for ( $d=0; $d<5; $d++ )
Now, since I'm only using 75 numbers I want to check if the array pointer is at the end of the array, if so I'll reset the pointer and reshuffle the array so as to not end up with the first and fourth cards as identical twins. Then we add the number from the numbers array to the temporary array we setup and increase the counter by 1:
# if the number counter is already at the end of the numbers array reset and rehuffle # important so the fourth card properly displays and isn't a duplicate of the first card if ( $n == 75 ) { shuffle($numbers); $n = 0; } # add number to array for the row and increment pointer for numbers array by 1 $num[] = $numbers[$n]; $n++;
To finish the row we format it using sprintf and add it to the $rows var:
# add row to rows var $rows .= sprintf($template,$num[0],$num[1],$num[2],$num[3],$num[4]);
Finally we end the card loop by replacing the %rows% string in our table template and adding the card to the $cards var, then reset the $rows var for the next card:
# add card to cards var and reset rows var for next card pass $cards .= str_replace('%rows%',$rows,$table); $rows = '';
The only thing required to display the cards is to copy the CSS from the finished page and echo/print the cards to your HTML BODY tag:
I know there are more elegant ways to pull this off, but I wasn't going to spend time generating a function or get into OOP for a simple task. In the end my wife is very happy, and that's all that matters ;)