Jump to content

Recommended Posts

Windows XP  Apache/2.0.59 (Win32) PHP/4.4.7

------------------------------------------------------------------

Without listing the code, which is lengthy, here is the issue:

 

In a section of code, I create an array (let's call it $array1) and populate it very carefully.

 

Later in the code, I create a second array ($array2) and populate it as well.

The problem comes after all of this:

If I add a shuffle($array2) command after the second array, the first array ($array1) becomes populated differently---incorrectly---than it would have been if I had never shuffled $array2.  This is a repeatable issue.

 

My questions:

1. Why does shuffling the second array affect how a different array is populated?

2. How can shuffling an array change how code EARLIER in the script  behaves?

 

(The arrays are never equated or matched or associated with each other at all.  Each array uses different code to populate it.  They do not coexist in any loops or functions.).

 

Thanks

 

Link to comment
https://forums.phpfreaks.com/topic/188383-unpredictable-effects-of-shuffle/
Share on other sites

My questions:

1. Why does shuffling the second array affect how a different array is populated?

2. How can shuffling an array change how code EARLIER in the script  behaves?

 

1) That's impossible to answer unless, like mike mentioned, you provide code.

2) Because not everything is procedural.

Here is the code, below.

The shuffle($squareSet) command (later in the script) disrupts the desired population of the array $grid earlier in the script.  I have no idea why.

 

NOTE: The undesired result is almost never seen the first time, but rather only afer refreshing.  Another head-scratcher...

 

(The desired result is a grid of all numbers.  An undesired result means the presence of the 'X' character.)

 

(FYI, my workaround failed.  Instead of shuffling the array, I created a string and shuffled that before exploding it into an array.  However, the page fails to load with a 30-second timeout error when I try this. All for a string just over 256 characters exploding into an 81-element aray.  Go figure.) 

Here's the original code:

-------------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------------------------

<?PHP
$colsInBlock = 3;
$rowsInBlock = 3;
$blocksAcrossGrid = 3;
$blocksDownGrid = 3;

$difficulty = 1;   // 0 is Easiest (All Nums Shown)




$blockTotalSquares = $rowsInBlock * $colsInBlock;
$gridSquaresAcross = $blocksAcrossGrid * $colsInBlock;
$gridSquaresDown = $blocksDownGrid * $rowsInBlock;
$gridTotalSquares = $gridSquaresAcross * $gridSquaresDown;
$gridTotalBlocks = $blocksDownGrid * $blocksAcrossGrid;

$numberDigits = $rowsInBlock * $colsInBlock;

switch ($numberDigits){
   case 9:
      $digitsList = array("X", "1", "2", "3", "4", "5", "6", "7", "8", "9");
   default:
      $digitsList = array("X", "1", "2", "3", "4", "5", "6", "7", "8", "9");
} //End Switch

$blockInterval = $gridSquaresAcross * $rowsInBlock;





switch ($difficulty){
   case 0:
      $squaresVisible = $gridTotalSquares; //All squares visible
      break;
   case 1:
      $squaresVisible = ((int)($gridTotalSquares * 36 / 81));
      break;
   case 2:
      $squaresVisible = ((int)($gridTotalSquares * 32 / 81));
      break;
   case 3:
      $squaresVisible = ((int)($gridTotalSquares * 30 / 81)); 
      break;
   case 4:
      $squaresVisible = ((int)($gridTotalSquares * 28 / 81));  
      break;
   case 5:
      $squaresVisible = ((int)($gridTotalSquares * 25 / 81));  
      break;
   case 99:
      $squaresVisible = 0; // No squares visible
      break;
   default:
      $squaresVisible = -1;
      break;
} //End Switch









// POPULATE GRID =========================================================================
$maxTriesPerPuzzle = 400;
$maxTriesPerDigit = 14;

$gridTry = 0;
$puzzleSuccess = 0;
while ($puzzleSuccess == 0 && $gridTry < $maxTriesPerPuzzle){
$gridTry = $gridTry + 1;




//Create Sudoku Number Matrix --- All squares with default value of Zero
$grid = array();
$gridSize = $gridSquaresAcross * $gridSquaresDown;
for ($gridSquares = 0; $gridSquares < $gridSize; $gridSquares++){
   $grid[$gridSquares] = array();
   $grid[$gridSquares][0] = "X";   // Number/Character in square
   $grid[$gridSquares][1] = 0;   // Lock Status      0 = Unlocked    1 = Locked
   $grid[$gridSquares][2] = 0;   // Visibility         0 = Hidden      1 = Visible
} //Next $gridSquares








$puzzleSuccess = 1;
//Digit by digit into blocks
for ($digits = 1; $digits < ($numberDigits + 1); $digits++){
$digitString = (string) $digits;
$successfulDigit = 0;
$digitTry = 0;
   
    while ($successfulDigit == 0 && $digitTry < $maxTriesPerDigit){
   $successfulDigit = 1;
   $digitTry = $digitTry + 1;


   //Undo previous attempts on this digit - if applicable
   if ($digitTry > 1){
      for ($undoSquares = 0; $undoSquares < $gridTotalSquares; $undoSquares++){
         
         if ($grid[$undoSquares][0] == $digitString){
            $grid[$undoSquares][0] = "X";
            $grid[$undoSquares][1] = 0;
         }
      } //Next $undoSquares
   } // EndIf beyond first failed try




   for ($block = 0; $block < ($blocksAcrossGrid * $blocksDownGrid); $block++){
      $freeBlockSquares = array();
      for ($rowInBlock = 0; $rowInBlock< $rowsInBlock; $rowInBlock++){
         for ($colInBlock = 0; $colInBlock< $colsInBlock; $colInBlock++){
            $squareID = (Int) ($block / $blocksDownGrid) * $blockInterval + $rowInBlock * $gridSquaresAcross + (Int) ($block % $blocksAcrossGrid) * $colsInBlock + $colInBlock;
            if ($grid[$squareID][0] == "X" && $grid[$squareID][1] == 0){
               array_push($freeBlockSquares, $squareID);    
            } // EndIf available square
         }  // Next $colInBlock
      } // Next $rowInBlock

      $freeCount = sizeof($freeBlockSquares);
      $rSquare = array_rand($freeBlockSquares);
      $squareChosen = $freeBlockSquares[$rSquare];
      $grid[$squareChosen][0] = $digitsList[$digits];   // Number or Character in square
      $grid[$squareChosen][1] = 1;   // Lock Status      0 = Unlocked    1 = Locked
      $grid[$squareChosen][2] = 0;   // Visibility         0 = Hidden      1 = Visible

      //Digit Validation
      if ($grid[$squareChosen][0] == "X" || strlen($grid[$squareChosen][0]) < 1){
         $successfulDigit = 0;
      }  //EndIf


      for ($sweepDown = $squareChosen; $sweepDown > -1; $sweepDown = $sweepDown - $gridSquaresAcross){
         if ($sweepDown != $squareChosen){
            $grid[$sweepDown][1] = 1;   // Lock Status      0 = Unlocked    1 = Locked
         } //EndIf
      } //Next $sweepDown
      for ($sweepUp = $squareChosen; $sweepUp < $gridTotalSquares; $sweepUp = $sweepUp + $gridSquaresAcross){
         if ($sweepUp != $squareChosen){
            $grid[$sweepUp][1] = 1;   // Lock Status      0 = Unlocked    1 = Locked
         } //EndIf         
      } //Next $sweepUp

      $startRow = $squareChosen;
      while ($startRow % $gridSquaresAcross > 0){
         $startRow = $startRow - 1;
      }
      for ($sweepRight = $startRow; $sweepRight < ($startRow + $gridSquaresAcross); $sweepRight++){
         if ($sweepRight != $squareChosen){
            $grid[$sweepRight][1] = 1;   // Lock Status      0 = Unlocked    1 = Locked
         } //EndIf         
      } //Next $sweepRight
      //if ($successfulDigit == 0){
      //   break;
      //}


   } // Next $block
   //Release all locks on 'empty' squares
   for ($clearLocks = 0; $clearLocks < $gridTotalSquares; $clearLocks++){
      if ($grid[$clearLocks][0] == "X"){
         $grid[$clearLocks][1] = 0;
         if ($digits == $numberDigits){
            $successfulDigit = 0;
            $puzzleSuccess = 0;
            break;
         } //EndIf
      }
   } //Next $clearLocks




    } // Wend try on digit
    if ($successfulDigit == 0){
   $puzzleSuccess = 0;
        break;
    }


} // Next $digits




// END POPULATE GRID =====================================================================
} //Wend try on whole grid















// CHOOSE VISIBLE SQUARES ------------------------
$maxVisblperBlock = (int)($blockTotalSquares * 5 / 9);

$availForVisPerBlock = array();  // Keeps track of visible square limits per block 
for ($blkVis = 0; $blkVis < $gridTotalBlocks; $blkVis++){
   $availForVisPerBlock[$blkVis] = $maxVisblperBlock;
} // Next

$squaresSet = range(0, ($gridSize - 1));
shuffle($squaresSet);  // ********************************** <<<<<<< THIS COMMAND MESSES UP HOW ARRAY $grid IS POPULATED ********************************

$stillToBeVisible = $squaresVisible;





$scrArrIdx = 0;
while ($stillToBeVisible > 0){
   $sqrToConsider = $squaresSet[$scrArrIdx];
   $thisBlock = (int)($sqrToConsider / $blockInterval) * $rowsInBlock + (int)(($sqrToConsider % $gridSquaresAcross) / $colsInBlock);
   if ($availForVisPerBlock[$thisBlock] > 0){
      $grid[$sqrToConsider][2] = 1;
      $stillToBeVisible = $stillToBeVisible - 1;
      $availForVisPerBlock[$thisBlock] = $availForVisPerBlock[$thisBlock] - 1;
   } // EndIf
   $scrArrIdx = $scrArrIdx + 1;
} //Wend


















//if ($puzzleSuccess == 1){

// DRAW GRID WITH NUMBERS
$cellID = 0;

$blCl = "<td width='" . ((int) (100/$blocksAcrossGrid)) . "%'>"; //container for block
$blClTbl = "<table border=0 width='100%' height='100%' cellspacing=1>";  //block table

//Assemble grid by rows of blocks
$allRows = "";
for ($grRs = 0; $grRs < $blocksDownGrid; $grRs++){   // $grRs is block-row number (e.g. 0-2)

    //Assemble row of blocks
    $blockRow = "<tr>";
    for ($grR = 0; $grR < $blocksAcrossGrid; $grR++){   // $grR is Block# within the block-row
        
        //Assemble block by row
        $block = $blCl . $blClTbl;
        for ($blRs = 0; $blRs < $rowsInBlock; $blRs++){  // $blRs is 'mini-Row' within Block

            //Assemble row within block
            $blR = "<tr>";
            for ($blRn = 0; $blRn < $colsInBlock; $blRn++){  // $blR  is 'mini-Column' within Block
                // $cellID = $grRs * $blockInterval + $blR * $gridSquaresAcross + $grR * $blocksAcrossGrid ;
            $cellID = $grRs * $blockInterval + $blRs * $gridSquaresAcross + $grR * $blocksAcrossGrid  + $blRn;
                $blR = $blR . "<td width='" . ((int) (100/$colsInBlock)) . "%' bgColor='FFFFFF'><span class='cell' ID='cell$cellID'>" . $grid[$cellID][0] . "</span></td>"; //Individual Cell
            } //Next $blRn
            $blR = $blR . "</tr>";
            $block = $block . $blR;

        } //Next $blRs
        $block = $block . "</table></td>";
        $blockRow = $blockRow . $block;

    } //Next $grR
    $blockRow = $blockRow . "</tr>";
    $allRows = $allRows . $blockRow;

} //Next $grRs



echo $allRows;



//}  //End if $puzzleSuccess












?>

Your code does not contain any method of causing the result produced on one page request to be available on another page request so you will get a different result on every page refresh.

 

Can you list the procedure or post the code showing how you are determining this problem is occurring?

 

Your code also has some logic error concerning incorrect indexing in the following line, because it throws hundreds of error messages when the code executes (might be relevant to your problem because $squareChosen is used as an index for $grid to set the values) -

      $squareChosen = $freeBlockSquares[$rSquare];

The $grid array is firstly prepopulated with default values.  Later on, each index is to have its value updated with something else.  The characters displayed on screen are straight from the array. So if I see any "X" characters in the final display, this indicates that some default values were never given their proper value assignment.  These "X" occurences only happen when I shuffle the other array later in the code.

 

[Different results per load is by design.  This is for the sake of randomness].

 

The undefined index notice is a mystery to me.  PHP itself is supplying an existing index via the array_rand function.  So I don't know why this is considered "undefined".  A legitimate array element is being provided to the buggy line. 

I have reviewed these index values using my own customized console-type log file.  They all appear to be in the correct numeric range.

 

 

Thanks

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.