I'm trying to create a bingo game that generates 120 tickets. Each Ticket is a [3x9 matrix] and contains numbers between 1-90. Rules for generating tickets are:
RULE #1 - Each row cannot have more than 5 numbers.
RULE #2 - Each column is assigned a range of numbers: (ex. 1-9 can appear only in column 1, 10-19 can appear only in column 2 and so on. And in column 9 numbers between 80-90 can appear)
RULE #3 - In a specific column, numbers must be arranged in ascending order from top to bottom.
RULE #4 - Each column must have at least one number in it.
RULE #5 - All the numbers 1 to 90 are used only once in each set of 6 tickets.
I'm able to fulfill all rules except RULE #5. Here's my code that I've written so far.
$batch_numbers = array(); //to keep track of numbers used in the set of 6 ticekts
$reset = false; // to check if the set is complete
$ticket_set = 1; // set count
for ($t=1; $t <= 120; $t++) {
$ticket_array = array(array(0,0,0,0,0,0,0,0,0), array(0,0,0,0,0,0,0,0,0), array(0,0,0,0,0,0,0,0,0));
$numbers = range(1, 90);
$indices = array();
$random_indices = array();
$used_numbers = array(); // to check unique numbers in a ticket
$full_ticket = array();
for($i=0;$i<3;$i++){
for($j=0;$j<9;$j++){
$indice = array($i, $j);
array_push($indices, $indice);
}
}
#if reset is true (means a set of 6 is complete) so set the batch_numbers array to empty and increment the ticket_set value
if($reset){
$batch_numbers = array();
$reset = false;
$ticket_set++;
}
#if ticket number is divisible by 6 set the reset variable to true to indicate the end of a set of 6 tickets
if(($t%6)==0){
$reset = true;
}
#selecting 5 random positions to fill the first row
$first_row_numbers = range(0,8);
shuffle($first_row_numbers);
$keys_one = array_rand($first_row_numbers, 5);
$first_row = array();
foreach ($keys_one as $row_one_key) {
array_push($first_row, $indices[$row_one_key]);
}
#selecting 5 random positions to fill the second row
$second_row_numbers = range(9,17);
shuffle($second_row_numbers);
$keys_two = array_rand($second_row_numbers, 5);
$second_row = array();
foreach ($keys_two as $row_two_key) {
array_push($second_row, $indices[$second_row_numbers[$row_two_key]]);
}
#selecting 5 random positions to fill the third row
$third_row_numbers = range(18,26);
shuffle($third_row_numbers);
$keys_three = array_rand($third_row_numbers, 5);
$third_row = array();
foreach ($keys_three as $row_three_key) {
array_push($third_row, $indices[$third_row_numbers[$row_three_key]]);
}
#push the selected 5 positions of first row to random_indices array that satisfies RULE #1
foreach($first_row as $row_one){
array_push($random_indices, $row_one);
}
#push the selected 5 positions of second row to random_indices array that satisfies RULE #1
foreach($second_row as $row_two){
array_push($random_indices, $row_two);
}
#push the selected 5 positions of third row to random_indices array that satisfies RULE #1
foreach($third_row as $row_three){
array_push($random_indices, $row_three);
}
#assign the numbers between 1-90 according to its column position to satisfy RULE #2
foreach($random_indices as $indice){
list($row, $column) = $indice;
#generate a unique number for the current set of 6 tickets
$rand = $this->generateRandomColumnNumber($column, $batch_numbers);
#assign the number to the array
$ticket_array[$row][$column] = $rand;
#push the unique number to batch_numbers array so that we can keep track of the numbers used in set of 6 tickets that satisfies RULE #5
array_push($batch_numbers, $rand);
#Push the unique number to used_numbers array so that we can keep track of the numbers already used in the individual ticket
array_push($used_numbers, $rand);
}
#Sort the ticket_array column wise to satisfy the RULE #3
for($k=0; $k<9; $k++){
# if all the rows are filled with random number
if($ticket_array[0][$k] != 0 && $ticket_array[1][$k] != 0 && $ticket_array[2][$k] != 0){
$temp_1 = NULL;
$temp_2 = NULL;
if($ticket_array[0][$k] > $ticket_array[1][$k]){
$temp_1 = $ticket_array[0][$k];
$ticket_array[0][$k] = $ticket_array[1][$k];
$ticket_array[1][$k] = $temp_1;
}
if($ticket_array[1][$k] > $ticket_array[2][$k]){
$temp_2 = $ticket_array[1][$k];
$ticket_array[1][$k] = $ticket_array[2][$k];
$ticket_array[2][$k] = $temp_2;
}
}
# if 1st and 2nd row are filled by random number
elseif($ticket_array[0][$k] != 0 && $ticket_array[1][$k] != 0 && $ticket_array[2][$k] == 0){
if($ticket_array[0][$k] > $ticket_array[1][$k]){
$temp = $ticket_array[0][$k];
$ticket_array[0][$k] = $ticket_array[1][$k];
$ticket_array[1][$k] = $temp;
}
}
# if 1st and 3rd row are filled by random number
elseif($ticket_array[0][$k] != 0 && $ticket_array[1][$k] == 0 && $ticket_array[2][$k] != 0){
if($ticket_array[0][$k] > $ticket_array[2][$k]){
$temp = $ticket_array[0][$k];
$ticket_array[0][$k] = $ticket_array[2][$k];
$ticket_array[2][$k] = $temp;
}
}
# if 2nd and 3rd rows are filled with random numbers
elseif($ticket_array[0][$k] == 0 && $ticket_array[1][$k] != 0 && $ticket_array[2][$k] != 0){
if($ticket_array[1][$k] > $ticket_array[2][$k]){
$temp = $ticket_array[1][$k];
$ticket_array[1][$k] = $ticket_array[2][$k];
$ticket_array[2][$k] = $temp;
}
}
# if 1st, 2nd and 3rd rows are empty we need to assign a value to the column so that it satisfies RULE #4
elseif($ticket_array[0][$k] == 0 && $ticket_array[1][$k] == 0 && $ticket_array[2][$k] == 0){
$modified_array = $this->fillEmptyColumn($k, $ticket_array, $batch_numbers, $batch, $game_id);
$ticket_array = $modified_array;
}
}
/* Code to store the ticket data in database */
}
protected function fillEmptyColumn($column, $ticket_array, $batch_numbers){
for ($i=0; $i < 9; $i++) {
if($i == $column){
continue;
}else{
//Check if all three rows have digits
if($ticket_array[0][$i] != 0 && $ticket_array[1][$i] != 0 && $ticket_array[2][$i] != 0){
$new_number = $this->generateRandomColumnNumber($column, $batch_numbers);
$ticket_array[2][$i] = 0;
$ticket_array[2][$column] = $new_number;
break;
}
//Check if 1st and 2nd rows have digits
elseif($ticket_array[0][$i] != 0 && $ticket_array[1][$i] != 0 && $ticket_array[2][$i] == 0){
$new_number = $this->generateRandomColumnNumber($column, $batch_numbers);
$ticket_array[1][$i] = 0;
$ticket_array[1][$column] = $new_number;
break;
}
//Check if 1st and 3rd rows have digits
elseif($ticket_array[0][$i] != 0 && $ticket_array[1][$i] == 0 && $ticket_array[2][$i] != 0){
$new_number = $this->generateRandomColumnNumber($column, $batch_numbers);
$ticket_array[2][$i] = 0;
$ticket_array[2][$column] = $new_number;
break;
}
//Check if 2nd and 3rd rows have digits
elseif($ticket_array[0][$i] == 0 && $ticket_array[1][$i] != 0 && $ticket_array[2][$i] != 0){
$new_number = $this->generateRandomColumnNumber($column, $batch_numbers);
$ticket_array[2][$i] = 0;
$ticket_array[2][$column] = $new_number;
break;
}
}
}
return $ticket_array;
}
protected function generateRandomColumnNumber($column, $batch_numbers)
{
#assign the numbers according to the column
if($column == 0){
$rand = rand(1, 9);
}elseif($column == 8){
$rand = rand(80,90);
}
else{
$rand = rand(($column *10), ((($column+1)*10)-1));
}
# check if numbers already exists in the current set of 6 tickets
if(in_array($rand, $batch_numbers)){
return $this->generateRandomColumnNumber($column, $batch_numbers);
}
return $rand;
}
Every time I try to call the generateRandomColumnNumber to generate a unique number and pass the batch_numbers array (to check unique number in the set of 6 tickets) instead of used_numbers array ( to check unique number in a individual ticket ) I get 500 error instantly but doesn't show why it is caused. Could anyone please help me out to point out what's wrong in my code and help me solve this. Been stuck at this for a couple of days now. It'd be of great help. Thanks