Shane_N Posted April 22, 2020 Share Posted April 22, 2020 Hi All, im a beginner so please bear with me - as part of teh COVID-19 response we have been running a little free bingo night for our local village the numbers are called on facebook live on a saturday night and the village join in for a bit of fun, its taken off well and were finding that issuing the tickets is taking all day so were trying to simplify it - Ive got half way there with a peice of code i found online - but i cant quite get 'the whole way'! Wouldbe greatful if someone could helpo with a few issues! <?php DEFINE('BR', "<br />\n"); $number_of_cards = 6; // the amount of unique cards to generate. don't make too many! $columns = array( range(1,15), range(16,30), range(31,45), range(46,60), range(61,90) ); $bingo_cards = array(); $card_hashes = array(); $i = 0; /* GENERATE THE CARDS */ while($i < $number_of_cards) { $bingo_card = array(); for($j=0; $j<5; $j++) { $random_keys = array_rand($columns[$j], 5); $random_values = array_intersect_key($columns[$j], array_flip($random_keys)); // http://stackoverflow.com/a/18047331/3625228 $bingo_card = array_merge($bingo_card, $random_values); } // generate a unique hash for this card and compare it to the ones we already have $card_hash = md5(json_encode($bingo_card)); // or whatever hashing algorithm is preferred if(!in_array($card_hash, $card_hashes)) { $bingo_cards[] = $bingo_card; $card_hashes[] = $card_hash; $i += 1; } if($i > 10000) break; // safety exit } /* OUTPUT, if needed (output with monospace font). could be made into an html table. */ foreach($bingo_cards as $card) { for($k=0; $k<(sizeof($card)/5); $k++) { echo(str_pad($card[$k], 2, ' ', STR_PAD_LEFT).' | '); echo($card[$k+5].' | '); echo($card[$k+10].' | '); echo($card[$k+15].' | '); echo($card[$k+20].BR); if($k < 4) echo(str_repeat('-', 22).BR); } echo(BR.BR); } ?> This code does what i need - sort of but creates a grid / table /array (?) thats 5 rows / 5 columns - what i would like to do is replciate (as close as possible) the tickets we have been sending out for the last few weeks these are 3 rows per ticket and 9 columns with the numbers 1-9 in C1, 10-19 in C2, 20-29 in c3 etc tec this makes it easy for older users to find the numbers while they are been called - see example below So far ive achieved this: http://culmstocklights.com/bingo.php each user visiting the page is presented with 3 Games (Green Pink and Brown) and 6 sets of numbers in each game (thats how we do it at the moment) Im 75% of the way there just need to get this to 3 rows and 9 columns per game and if possible randomly add the blanks. Any help would be massivly appreciated! Thanks in advance Quote Link to comment https://forums.phpfreaks.com/topic/310632-php-community-bingo/ Share on other sites More sharing options...
gw1500se Posted April 22, 2020 Share Posted April 22, 2020 Exactly what are you asking us to do? This is not a free programming forum. You are expected to do the work and if you have problems then we can help. You need to understand what the code you posted is doing then make the appropriate modifications. For example, there are 5 columns in your array. Change that to 9 and set the appropriate ranges for each. Quote Link to comment https://forums.phpfreaks.com/topic/310632-php-community-bingo/#findComment-1577109 Share on other sites More sharing options...
Shane_N Posted April 22, 2020 Author Share Posted April 22, 2020 (edited) gw1500se, thank you for your repsonse - i was hoping that given the non commecial - comunity nature of this request that your answer may have been a little more charitable, im a complete beginner to PHP so really dont understand the code. That said i have tried what you suggested already I spotted the: $columns = array( range(1,15), range(16,30), range(31,45), range(46,60), range(61,90) ); part and expanded this to 9 'ranges' with the number outputs i was looking for i then changed $random_keys = array_rand($columns[$j], 5); to $random_keys = array_rand($columns[$j], 9); hoping that would solve my problem however the output didnt match my expecations i suspect thats becuase the output is driven from here: foreach($bingo_cards as $card) { for($k=0; $k<(sizeof($card)/5); $k++) { echo(str_pad($card[$k], 2, ' ', STR_PAD_LEFT).' | '); echo($card[$k+5].' | '); echo($card[$k+10].' | '); echo($card[$k+15].' | '); echo($card[$k+20].BR); if($k < 4) echo(str_repeat('-', 22).BR); } echo(BR.BR); however thats so far away from my basic HTML knowledge that i cant even begin to see what i might change here to fix it! Edited April 22, 2020 by Shane_N Quote Link to comment https://forums.phpfreaks.com/topic/310632-php-community-bingo/#findComment-1577111 Share on other sites More sharing options...
Shane_N Posted April 22, 2020 Author Share Posted April 22, 2020 (edited) PS the output from my changes i tried above can be viewed here: http://culmstocklights.com/bingo-dev.php as you can see it simply creates extra rows with sequesnced numbers this is generated byu the following code: <?php /* Random bingo Generator - by Shane Nelson */ DEFINE('BR', "<br />\n"); $number_of_cards = 6; // the amount of unique cards to generate. don't make too many! $columns = array( range(1,9), range(10,19), range(20,29), range(30,39), range(40,49), range(50,59), range(60,69), range(70,79), range(80,89), range(90,99) ); $bingo_cards = array(); $card_hashes = array(); $i = 0; /* GENERATE THE CARDS */ while($i < $number_of_cards) { $bingo_card = array(); for($j=0; $j<5; $j++) { $random_keys = array_rand($columns[$j], 9); $random_values = array_intersect_key($columns[$j], array_flip($random_keys)); // http://stackoverflow.com/a/18047331/3625228 $bingo_card = array_merge($bingo_card, $random_values); } // generate a unique hash for this card and compare it to the ones we already have $card_hash = md5(json_encode($bingo_card)); // or whatever hashing algorithm is preferred if(!in_array($card_hash, $card_hashes)) { $bingo_cards[] = $bingo_card; $card_hashes[] = $card_hash; $i += 1; } if($i > 10000) break; // safety exit } /* OUTPUT, if needed (output with monospace font). could be made into an html table. */ foreach($bingo_cards as $card) { for($k=0; $k<(sizeof($card)/5); $k++) { echo(str_pad($card[$k], 2, ' ', STR_PAD_LEFT).' | '); echo($card[$k+5].' | '); echo($card[$k+10].' | '); echo($card[$k+15].' | '); echo($card[$k+20].BR); if($k < 4) echo(str_repeat('-', 22).BR); } echo(BR.BR); } ?> Edited April 22, 2020 by Shane_N Quote Link to comment https://forums.phpfreaks.com/topic/310632-php-community-bingo/#findComment-1577112 Share on other sites More sharing options...
kicken Posted April 25, 2020 Share Posted April 25, 2020 Your example has missing cells, I assume they are supposed to be populated. Maybe something like this is what you're looking for: <?php $columns = [ range(1, 9), range(10, 19), range(20, 29), range(30, 39), range(40, 49), range(50, 59), range(60, 69), range(70, 79), range(80, 89), range(90, 99) ]; $number_of_cards = $_GET['cards'] ?? 6; $bingo_cards = []; while (count($bingo_cards) < $number_of_cards){ $card = []; foreach ($columns as $columnRange){ shuffle($columnRange); $card[] = array_slice($columnRange, 0, 3); } $hash = sha1(json_encode($card)); if (!isset($bingo_cards[$hash])){ $bingo_cards[$hash] = $card; } } foreach ($bingo_cards as $card){ echo '<table>'; for ($row = 0; $row < 3; $row++){ echo '<tr>'; for ($column = 0; $column < count($columns); $column++){ echo '<td>'.$card[$column][$row].'</td>'; } echo '</tr>'; } echo '</table>'; } For each card that is generated it goes through your $columns array and uses shuffle to randomize the order of the numbers. It then uses array_slice to pick off the first three numbers, one for each row. Finally it hashes the card and checks if that hash exists already to prevent duplicates. Keep in mind this only prevents duplicates for that one generation cycle. If you reload the page to generate more cards then there could be duplicates of the first batch in the second batch. If you want to prevent duplicates across all generation cycles you'll need to track the cards in a file or database. Finally it prints out a simple HTML table for each card. Quote Link to comment https://forums.phpfreaks.com/topic/310632-php-community-bingo/#findComment-1577194 Share on other sites More sharing options...
Shane_N Posted April 28, 2020 Author Share Posted April 28, 2020 Kicken - thank you for taking the time to help - ill have a play with you you have provided and see where it takes me - thankyou! Quote Link to comment https://forums.phpfreaks.com/topic/310632-php-community-bingo/#findComment-1577289 Share on other sites More sharing options...
Barand Posted April 28, 2020 Share Posted April 28, 2020 A friend of mine is also organising bingo sessions so I wrote a script for her, and I am happy to share it here. There are additions I plan to make, such as outputting each players cards in pdf for emailing out before the game storing the cards and numbers called in a DB to facilitate checking when "Bingo!" is called but here is current version which produces this... Code <?php $name = $_GET['name'] ?? ''; $date = $_GET['date'] ?? date('Y-m-d', strtotime("+1 day")); $players = $_GET['players'] ?? '4'; $games = $_GET['games'] ?? '5'; $output = ''; $cards = []; if ($name) { $ranges = [ 0 => range( 1, 9), 1 => range(10, 19), 2 => range(20, 29), 3 => range(30, 39), 4 => range(40, 49), 5 => range(50, 59), 6 => range(60, 69), 7 => range(70, 79), 8 => range(80, 90) ]; if ($nCards = $players * $games) { do { $card = makeCard($ranges); if (!in_array($card, $cards)) { $cards[] = $card; } } while ( count($cards) < $nCards); #echo '<pre>', print_r($cards, 1), '</pre>'; } $output = '<div class="w3-container w3-purple w3-padding w3-margin"><h1>'.$name.'</h1></div>'; $output .= cardOutput($cards, $players, $games); } /** * build html output for the generated cards * * @param array $cards * @param int $players * @param int $games */ function cardOutput($cards, $players, $games) { $cardColors = ['blue', 'green', 'yellow', 'orange', 'red']; $output = ''; $pcards = array_chunk($cards, $games); foreach ($pcards as $pid =>$gcards) { $pno = $pid +1; $output .= "<div class=\"w3-container w3-indigo w3-margin w3-padding\"><h3>Player $pno</h3></div>"; foreach ($gcards as $gid => $gnums) { $clr = $cardColors[$gid % 5]; $gno = $gid + 1; $output .= "<div class='w3-content w3-$clr w3-margin-top'> <table border='1'> <tr><th colspan='9'>Game $gno</th></tr>"; $rows = explode('|', $gnums); foreach ($rows as $rnums) { $nums = explode(',', $rnums); $output .= "<tr>"; foreach ($nums as $n) { $output .= $n!=' ' ? "<td>$n</td>" : "<td class='empty'></td>"; } $output .= "</tr>"; } $output .= "</table> </div> "; } } return $output; } /** * generate random bingo card - 3 rows x 9 columns - 5 numbers per row * * @param array $ranges */ function makeCard($ranges) { $cols = array_keys($ranges); shuffle($cols); $colnums = []; foreach (array_slice($cols,0,6) as $c) { shuffle($ranges[$c]); $colnums[$c] = array_slice($ranges[$c],0,2); sort($colnums[$c]); } foreach (array_slice($cols,-3) as $c) { $colnums[$c][] = $ranges[$c][array_rand($ranges[$c])]; } $krows = [0,0,0]; $rownums = []; $first=1; foreach ($colnums as $c => $nums) { sort($nums); switch (count($nums)) { case 1: if ($first) { $r = rand(0,2); } else { $r = shortestRow($krows); } $first = 0; $krows[$r]++; $rownums[$r][$c] = $nums[0]; break; default: $check = []; foreach ($nums as $n) { $r = shortestRow($krows); $krows[$r]++; $rownums[$r][$c] = $n; $check[] = [$r,$n]; } // are col numbers in asc sequence? if ( ($check[0][0] < $check[1][0] && $check[0][1] > $check[1][1]) || ($check[0][0] > $check[1][0] && $check[0][1] < $check[1][1]) ) { // swap numbers $rownums[$check[0][0]][$c] = $check[1][1]; $rownums[$check[1][0]][$c] = $check[0][1]; } break; } } $rows = []; foreach ($rownums as $r => $carr) { $rstr = []; foreach (array_keys($ranges) as $i) { $rstr[] = isset($carr[$i]) ? $carr[$i] : ' '; } $rows[] = join(',',$rstr); } return join("|", $rows); } /** * find row with fewest numbers * * @param array $krows row counts */ function shortestRow($krows) { $n = min($krows); foreach ($krows as $r => $k) { if ($k==$n) return $r; } } ?> <!DOCTYPE html> <html> <head> <meta http-equiv="content-language" content="en"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Bingo Setup</title> <meta name="author" content="Barand"> <meta name="creation-date" content="04/26/2020"> <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css"> <style type="text/css"> table { width: 100%; border-collapse: collapse; border-color: #FFF; } td { background-color: #FFF; color: #000; margin: 5px; text-align: center; font-size: 12pt; font-weight: 600; width: 11%; } td.empty { background-color: #F8F8F8; } </style> </head> <body> <header class="w3-container w3-green"> <h1>Bingo Game Setup</h1> </header> <div class="w3-content w3-round-large w3-border w3-margin-top w3-padding w3-sand"> <form> <div class="w3-row"> <label class="w3-third">Your name/group</label> <input type="text" class="w3-input w3-twothird" name="name" value="<?=$name?>"> </div> <div class="w3-row"> <label class="w3-third">Game date</label> <input type="date" class="w3-input w3-twothird" name="date" value='<?=$date?>'> </div> <div class="w3-row"> <label class="w3-third">Number of players</label> <input type="number" class="w3-input w3-twothird" name="players" value='<?=$players?>'> </div> <div class="w3-row"> <label class="w3-third">Number of games</label> <input type="number" class="w3-input w3-twothird" name="games" value='<?=$games?>'> </div> <button class="w3-button w3-blue">Generate game cards</button> </form> </div> <?=$output?> </body> </html> Quote Link to comment https://forums.phpfreaks.com/topic/310632-php-community-bingo/#findComment-1577290 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.