|
smartX(x, y, step)
// responsible for the blocks' horizontal movement function smartX(x, y, step) { // if moving one step to the left if (step < 0) // if the destination square needs to be turned on explicitly if (ar[x + step][y] == 0) // if there is a block to the right of the current block if (x != 9 && ar[x – step][y] == 1) // set square to the left on without clearing current block setSquare(x + step, y, 1) else // clear current block and turn square to the left on warp(x, y, x + step, y) else // if there is no block to the right of the current block if (x == 9 || ar[x – step][y] == 0) // clear current block setSquare(x, y, 0) // if moving one step to the right if (step > 0) // if the destination square needs to be turned on explicitly if (ar[x + step][y] == 0) // if there is a block to the left of the current block if (x != 0 && ar[x – step][y] == 1) // set square to the right on without clearing current block setSquare(x + step, y, 1) else // clear current block and turn square to the right on warp(x, y, x + step, y) else // if there is no block to the left of the current block if (x == 0 || ar[x – step][y] == 0) // clear current block setSquare(x, y, 0) }
The smartX() function is responsible for the horizontal movement of the affected blocks. Notice that when you move a horizontal bar (four blocks) shape to the right, for example, you only need to move the far-right block to the right of the shape, and clear the premovement far-left block. Figure 25-5 illustrates this concept with an “L” shape. Moving a shape consisting of four blocks one step to the right requires the setting of two blocks and the clearing of two other blocks. moveY()
// move all active squares step squares on the x axis function moveY() { // if specified move is not legal (shape is laid down on block or bottom panel) if (!checkMoveY()) { // active squares are not active anymore (should not be moved later) clearActive() // terminate function (active blocks are not moved) return } // scan screen from bottom to top for (var y = 18; y >= 0; --y) { for (var x = 0; x < 10; ++x) { // if current square is active if (ar[x][y] == 1) // call function to handle movement smartY(x, y) } } }
The moveY() function is identical to the moveX() function, except that, in the case the move is not possible, the clearActive() function is called, inactivating the whole board. Also, since the movement is always downward, no argument is needed. smartY(x, y)
// responsible for the blocks' vertical (downward) movement function smartY(x, y) { // if the destination square needs to be turned on explicitly if (ar[x][y + 1] == 0) // if there is a block above current block if (y != 0 && ar[x][y – 1] == 1) // set square below on without clearing current block setSquare(x, y + 1, 1) else // clear current block and turn square below on warp(x, y, x, y + 1) else // if there is no block above the current block if (y == 0 || ar[x][y – 1] == 0) // clear current block setSquare(x, y, 0) }
This function is the Y-axis equivalent of the smartX() function presented earlier. See the listings for that function. shapeMap()
// construct object containing shape function shapeMap() { // set minimum and maximum coordinates to opposite (minimum and maximum found thus far) var minX = 9 var minY = 18 var maxX = 0 var maxY = 0 // scan screen to find actual minimum and maximum coordinates of active squares for (var y = 0; y < 19; ++y) { for (var x = 0; x < 10; ++x) { // if current coordinates reflect active square if (ar[x][y] == 1) { if (x < minX) minX = x if (x > maxX) maxX = x if (y < minY) minY = y if (y > maxY) maxY = y } } } // create a length property representing the x coordinate span this.length = maxX – minX + 1 // create properties to hold minimum coordinates of both axes this.offsetX = minX this.offsetY = minY // construct minimum array containing all active squares respectively for (x = 0; x <= maxX – minX; ++x) { this[x] = new Array() for (y = 0; y <= maxY – minY; ++y) { this[x][y] = ar[x + minX][y + minY] } } }
Before the script rotates a shape, it must know which shape is currently active and its exact position. The shapeMap() constructor builds the minimum 2D array which encloses the current shape, as illustrated in Figure 25-6: In addition to the array elements, an instance of shapeMap features the board’s x and y coordinates (offsetX and offsetY) of the shape-enclosing rectangle’s top left square (shapeMapInstance[0][0]). The 2D array and these two properties are enough to determine the current active shape and its location. For a complete discussion of each statement in the function refer to the comments. getRandom()
// random function to return an integer between 0 and 6 function getRandom() { // use random number method to find integer between 0 and 8 var randomNum = Math.round(Math.random() * 8) // call function again if random number is 0 or 8. if (randomNum == 0 || randomNum == 8) return getRandom() // 1 to 7 => 0 to 6 randomNum-- // update selected shape's statistics statistics[randomNum]++ // update statistics display form (update *all* fields so user cannot enter any value in fields) for (var shape = 0; shape < 7; ++shape) { document.stats[shape].value = statistics[shape] } // return the random number return randomNum }
The getRandom() function returns a random integer between 0 and 6. First, it uses the Math object’s random() method to generate a random number. Peculiarly enough, we found out that the random generator prefers the inner integers (1, 2, 3, 4, and 5) over the boundary ones (0 and 6). To remedy the situation, we decided to generate random integers between 0 and 8, and then do some juggling to fit the result into the 0-to-6 range. If the integer is 0 or 8, the function invokes itself recursively, until an integer between 1 and 7 is randomly generated. The number then decrements by 1 to fit the 0-to-6 range, and is returned by the function. After updating the statistics array, the text fields, representing the number of appearances of each shape, are updated as well. |
||||||||||||||||||||
With any suggestions or questions please feel free to contact us |