DHTML Jigsaw Puzzle: IE4; Auto Solve | WebReference

DHTML Jigsaw Puzzle: IE4; Auto Solve


The DHTML Lab Jigsaw Puzzle, Part II: IE4 cont'd
solving the puzzle automatically

The Solve Button

At any time during puzzle play, we can choose to have the remainder of the puzzle solved automatically by clicking the Solve button. As you will recall, the button HTML is:

    <INPUT ID="solvBut" TYPE=BUTTON STYLE="cursor:hand" VALUE="Solve" onClick="solve(true)">

The onClick handler calls the solve() function, passing an argument of true. This single argument tells solve() whether we want to solve the full puzzle or not.

    function solve(isFullSolve) { if (!isBroken) { return }; if (pieceToSolve > puzzPieces) { pieceToSolve = 1; return } tempEl = eval("PIECE" + pieceToSolve); if (tempEl.draggable){ if (tempEl != activeEl ) { tempEl.style.zIndex = activeEl.style.zIndex + 1; activeEl = tempEl; } flashTimer = setInterval("visToggle(" + isFullSolve + ")",100); } else { pieceToSolve++; solve(isFullSolve) }; }

When solve() is called, it first determines if the puzzle is broken. That is, if a solve is called for. The user may have clicked when the puzzle was unbroken. It proceeds only if a solve is possible.

Next, it checks if the next piece in line to be solved (pieceToSolve) is within the piece range (puzzPieces). If it isn't, it means the puzzle has been solved already, so pieceToSolve is re-initialized to 1, to ready it for the next puzzle, and the function returns.

If the puzzle is not yet solved, the next piece in line to be solved is assigned to tempEl. Now, although this is the next piece to be solved, the user may have solved this piece by dragging it to the correct position before an automatic solved was called for. If that is the case, then it is no longer draggable. Therefore, to determine if it is in the correct position already, we check its draggable property. If it is false, the piece is already solved, so we move on. pieceToSolve is incremented and we call solve() again, passing it the value of isFullSolve. This looping is continued until a solvable piece is found.

When we find the next piece in line whose draggable property is true, it is placed on top of the other pieces in z-order, just like when it is readied for a drag. This is necessary because we want to make it visible to the user if it was under another piece. We then call visToggle() repeatedly, as we did when the user successfully positioned a piece.

Flashing the Piece

The visToggle() function is called when:

  • a piece is dragged by the user to the correct position, or
  • the puzzle is fully solved, or
  • a piece is about to be solved in automatic mode.

In the first case, above, an argument of false is passed, as we saw on the previous page. The same applies to the second case, as we shall see later. In the last case, it could be either true or false. This argument tells visToggle() if a full automatic solve has been called for. Therefore, for clarity, we give it the same name to use internally as the corresponding argument in the solve() function: isFullSolve

    function visToggle(isFullSolve){ if (flashCount != flashTotal) { tempEl.style.visibility = (tempEl.style.visibility=="visible") ? "hidden" : "visible"; flashCount++; } else { clearInterval(flashTimer); flashCount = 0; tempEl.style.visibility = "visible"; if (tempEl != elImOrig) { origPos(tempEl) }; if (isFullSolve) { pieceToSolve++; solve(true) } } }

Recall that we have set two variables earlier: flashCount, a counter, initialized to 0 and flashTotal, storing the total number of times our piece should flash. When visToggle() is called, it compares the two to determine if our total has been reached. If it hasn't, the visibility of the piece is toggled. If it is visible, it is made hidden, and vice-versa. This gives the illusion of a "flashing" piece. flashCount is incremented for the next time visToggle() is called.

Remember that visToggle() is being repeatedly called by the setInterval() method. Eventually, flashcount will be equal to flashTotal. In that case, the repeated callings are cancelled with the clearInterval() method. flashCount is reinitialized to 0, ready for the next time a flashing piece is required and the piece's visibility is set to visible. This may be redundant, as the piece may already be visible. Since the final visibility depends on the value of flashTotal, which can be changed, this extra safeguard is provided to assure that when the flash ends, we can see the piece.

If it is a piece we are dealing with, and not the already-correctly-positioned puzzle image (elImOrig), then the piece is passed as an argument to origPos(), a function that will position it.

Finally, visToggle() determines if a full solve is in progress. If it is, pieceToSolve is incremented, and solve() is called again, repeating the cycle discussed on this page for the next piece.

Code-wise, it's all downhill from now on. First let's look at origPos(), that automatically positions a piece.

Produced by Peter Belesis and

All Rights Reserved. Legal Notices.
Created: Nov. 13, 1997
Revised: Jan. 18, 1998

URL: http://www.webreference.com/dhtml/column9/puzzSolve.html