A DOM-based Sliding Puzzle: Puzzle-Player Interaction | WebReference

A DOM-based Sliding Puzzle: Puzzle-Player Interaction


A DOM-based Sliding Puzzle (8)

The Puzzle-Player Interaction

The Puzzle-Player interaction is based on the player's mouse clicking. The player clicks the square that he or she wants to slide to the blank position. The script catches every mouse click within the document, as specified in the BODY statement:

<BODY BGCOLOR="#ffffff" onclick=handleClick() ID="bodyNode">

The handleClick() function finds out which square has been clicked, checks for its validity, and then swaps the positions of the old blank square with the new blank square:

function handleClick() {
  for (i=0; i < size; i++) {
    if (window.event.srcElement == divNode.childNodes[i]) {
      newBlank = i;
      break;
    }
  }
if (!validClick(oldBlank, newBlank)) return;
divNode.childNodes[oldBlank].swapNode(divNode.childNodes[newBlank]);
oldBlank = newBlank;
goodClicks++;
window.status = "You made " + goodClicks + " moves";
if (done()) alert("Congratulations! You made it in " + goodClicks + " moves");
}

The first loop iterates over all squares and finds out which object has been clicked. The trick here is to compare the object provided by the event object, window.event.srcElement, and the DOM node:

if (window.event.srcElement == divNode.childNodes[i])

Once the clicked object has been found, its index is assigned to the newBlank variable. Then we verify that the click is valid. The position of the blank square determines which neighboring squares can be clicked and slides into the blank position. The middle square (numbered 5) may accommodate clicks on all four neighbors. The player can only slide squares 1 and 4 into position 0, for example. Here is the full function for doing this validation check:


function validClick(oldSquare, newSquare){
  if (oldSquare == 0 && (newSquare == 1 || newSquare == 4)) return (true);
  if (oldSquare == 1 && (newSquare == 0 || newSquare == 2 || newSquare == 5))
    return (true);
  // (The above two lines should be joined as one line.
  // They have been split for formatting purposes.)
  if (oldSquare == 2 && (newSquare == 1 || newSquare == 6)) return (true);
  if (oldSquare == 4 && (newSquare == 0 || newSquare == 5 || newSquare == 8))
    return (true);
  // (The above two lines should be joined as one line.
  // They have been split for formatting purposes.)
  if (oldSquare == 5 && (newSquare == 1 || newSquare == 4 || newSquare == 6 ||
    newSquare == 9)) return (true);
  // (The above two lines should be joined as one line.
  // They have been split for formatting purposes.)
  if (oldSquare == 6 && (newSquare == 2 || newSquare == 5 || newSquare == 10))
    return (true);
  // (The above two lines should be joined as one line.
  // They have been split for formatting purposes.)
  if (oldSquare == 8 && (newSquare == 4 || newSquare == 9)) return (true);
  if (oldSquare == 9 && (newSquare == 5 || newSquare == 8 || newSquare == 10))
    return (true);
  // (The above two lines should be joined as one line.
  // They have been split for formatting purposes.)
  if (oldSquare == 10 && (newSquare == 6 || newSquare == 9)) return (true);
}

Once the mouse click has been validated, swapping of oldBlank with newBlank positions is as explained before in this column:

divNode.childNodes[oldBlank].swapNode(divNode.childNodes[newBlank]);

After swapping the nodes, we update the number of good moves and reflect them to the player. The last thing left is to check for completion of the puzzle. The strategy we took is to compare the picture name in every square with that originally set with the picture array. A winner is declared when all squares match their original assignments. The only complication in this function is due to the fact that file names are kept in the DOM tree with their full path name, while the picture array holds the short file names. Take a look at the done() function:

function done() {
  for(i = 0; i < size; i++) {
    lastSlashPos = divNode.childNodes[i].src.lastIndexOf("/");
    lastChar = divNode.childNodes[i].src.length - 1;
    if (divNode.childNodes[i].src.substring(lastSlashPos + 1, lastChar + 1)
      != picture[i]) return (false);
  // (The above two lines should be joined as one line.
  // They have been split for formatting purposes.)
  }
  return (true);
}

http://www.internet.com

Produced by Yehuda Shiran and Tomer Shiran

Created: August 2, 1999
Revised: August 2, 1999

URL: http://www.webreference.com/js/column45/interact.html