Jigsaw : Game « Page Components « JavaScript DHTML

JavaScript DHTML
1. Ajax Layer
2. Data Type
3. Date Time
4. Development
5. Document
6. Event
7. Event onMethod
8. Form Control
9. GUI Components
10. HTML
11. Javascript Collections
12. Javascript Objects
13. Language Basics
14. Node Operation
15. Object Oriented
16. Page Components
17. Security
18. Style Layout
19. Table
20. Utilities
21. Window Browser
Microsoft Office Word 2007 Tutorial
Java
Java Tutorial
Java Source Code / Java Documentation
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
JavaScript DHTML » Page Components » Game 
Jigsaw

<!----------------------------------------------------------------\
|                                                                 |
|  Fair License                                                   |
|                                                                 |
|  JS Games :: Jigsaw Puzzle                                      |
|  Copyright (C2002-2004 Arun Narayanan                         |
|                                                                 |
|  For latest release information and downloads visit:            |
|  http://jsgames.sourceforge.net/                                |
|                                                                 |
|  Usage of the works is permitted provided that this             |
|  instrument is retained with the works, so that any entity      |
|  that uses the works is notified of this instrument.            |
|                                                                 |
|  DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.                    |
|                                                                 |
|  [2004, Fair License: rhid.com/fair]                            |
|                                                                 |
\----------------------------------------------------------------->

<html>
<head>
<title>!!! JS Games :: Jigsaw Puzzle !!!</title>
<style>
body,h1,h2,h3,.msg,capt2,td {font-family:  Verdana,Comic Sans MS,Arial;}
body {margin: 0px;}
h1 {font-size:28pt; font-weight:bold; margin-bottom:0px;}
h2,.h2 {font-size:22pt; margin:0px; font-weight:bold; padding:0px;}
h3 {font-size:8pt; margin:0px; font-weight:bold;}
.msg {font-size:8pt; font-weight:bold;}
.capt1,.base,.bar {font-size:10pt; font-weight:bold;}
.capt2 {font-size:9pt; font-weight:bold;}
.capt3 {font-size:8pt; font-weight:bold;}
.tip {font-size:9pt; font-weight:bold; color:#66ffcc;}
.fscapt {font-size:9pt; font-weight:bold;color:#ddffdd;}
.selcapt2 {font-size:9pt; font-weight:normal; margin:4px;background-color:#ddffee;color:#666655;}
.selcapt3 {font-size:9pt; font-weight:normal; margin:4px;background-color:#336666;color:#ffffff;}
.selcapt {font-size:9pt; font-weight:normal; margin:4px;background-color:#ffffff;color:#006600;}

.but {font-size:8pt; font-weight:bold; height:24px; background-color:#606060;color:#ffffff;background-image:url(images/butbase.gif);border:0px solid #cccccc; border-left:none; border-right:none;}

.base {background-color:#aaff66;border:1px solid #009900;color:#006600;}
.bar {background-image:url(jigsaw/bar.gif);background-color:#336633;color:#00330;text-align:center;}
.url,.urlp,.urla {font-size:8pt; font-weight:bold;color:#ffffaa}
.urlp {color:#aaffaa}
.urla {color:#66eeff}
.info {border:2px;border-style:solid;border-color:white;}
.bnote {font-size:8pt; font-weight:normal;color:white;}
a.notelnk,a.notelnk:visited,a.notelnk:active {font-size:8pt; font-weight:normal; color:#66ffcc;}
.bnotehead {font-size:10pt; font-weight:bold;color:#66ffcc;}
.email {font-size:8pt; font-weight:bold; color:white;}
.menubar {padding:0px; margin:0px; brder-top:1px solid white; brder-bottom:1px solid white; background-color:#606060;
          background-image:url(images/menu.gif);}
.fra {border:2px solid #999999; background-color:#606060;}
.clsThisGame, .clsBar {font-size:8pt; font-weight:bold; color:#cccccc;}
.clsBar {margin:0px; font-size:8pt; font-weight:bold; color:#ffffff;}
.clsOtherGame {margin:0px; font-size:8pt; font-weight:bold; color:#ffffff; text-decoration:none;}
.help {font-size:8pt; margin:0px; font-weight:bold;}
</style>

<script language="javascript">
<!--
//global configuration (change these to alter the position of the playing board)
var gtop = 200//168;          //constant denotes top of board
var gleft = 10;          //constant denotes left of board

//internal use variables
var gintervalid = -1;    //keeps track of the game timer
var gtime = 0;           //stores time in seconds
var gmoves = 0;          //stores the total moves per game
var gpicid = -1;         //keeps track of the picture loading timer
var gpictick = 0;        //counter for the picture loading timer
var gpicture = "";       //current picture path
var gloaded = false;     //becomes true when a proper picture has been loaded
var gdragging = false;   //true while a block is being dragged
var gcurrobjid = "";     //id of the block being dragged
var gdx = 0;             //width of a block of the picture
var gdy = 0;             //height of a block of the picture
var gsrcx = 0;           //x coordinate of the block before the drag started
var gsrcy = 0;           //y coordinate of the block before the drag started
var gpicurl = "";        //last valid picture url used
var gprogress = 0;       //stores the % of correctly positioned pieces
var gactive = false;     //keeps track of whether the game timer is active

function toggleHelp()
{
  if (butHelp.value == "Hide Help")
  {
    help.style.display = "none";
    divTip.style.display = "block";
    butHelp.value = "Show Help";
  }
  else
  {
    help.style.display = "block";
    divTip.style.display = "none";
    butHelp.value = "Hide Help";
  }  
}

function loadPicture(picture)
{
  var i;
  
  gloaded = false;
  selPic.disabled = true;
  butLoad.value = "Cancel Loading";  
  board.style.display = "none";
  board.style.pixelLeft = gleft;
  board.style.pixelTop = gtop;
  divPic.style.pixelLeft = gleft;
  divPic.style.pixelTop = gtop;
  divPic.style.display = "block";
  showStatus("Picture Loading... Please Wait!");
  pic.src = picture;
  gpictick = 0;
  gpicture = picture;
  stopPicTimer();
  gpicid = setInterval("checkPictureLoadStatus()",300);
}

function checkPictureLoadStatus()
{
  gpictick++;
  
  if (pic.readyState != "complete")
  {
    if (gpictick >= 100//after each 30 secs
    {
      gpictick = 0//reset the timer
      

      //ask user if he wants to continue loading the picture
      //vbRetryCancel=5 vbRetry=4 vbCancel=2
      if (== VBMsgBox("The url you provided may be invalid or too slow!\n\n" 
                        "Do you wish to continue loading the picture?",5,"Loading Picture"))
      {
        //do a final check to see if by this time the picture has already loaded!
        if (pic.readyState == "complete")
        {
          checkPictureLoadStatus();
          return;
        }
        gloaded = false;
        divPic.style.display = "block";
        showStatus('Unable to load Picture: ' + gpicture);
        stopPicTimer();
        return;
      }
    }
  }
  else //picture loaded!
  {
    stopPicTimer();
    showStatus('Picture \"' + gpicture + '" Loaded!<p>
               "Press 'Start Game' to start the game.");
    gloaded = true;
    butLoad.disabled = true;
    selPic.disabled = false;
    butLoad.value="Load Picture";
    butStart.disabled = false;
    butStart.focus();
    gpicurl = gpicture;
  }
}

function drawBoard() 
{
  var i,j,s="",dx,dy,t=0,l=0,n=0,picWidth,picHeight;

  if (!gloaded)
  {
    alert("No Picture selected!. Please use the picture drop down.");
    selPic.focus();
    return;
  }
  
  divisionsX = parseInt(selCols.value);
  divisionsY = parseInt(selRows.value);
  
  picWidth = pic.clientWidth;
  picHeight = pic.clientHeight;
  
  if (picWidth == 0picWidth = 400;
  if (picHeight == 0picHeight = 400;

  divPic.style.display = "none";
  
  board.style.display = "block";
  
  dx = parseInt(picWidth/divisionsX);
  dy = parseInt(picHeight/divisionsY);
  board.style.pixelWidth = divisionsX * dx + 1;
  board.style.pixelHeight = divisionsY * dy + 1;      

  for (i=0;i<divisionsY;i++)
    for (j=0;j<divisionsX;j++)
    {
      t = i*dy;
      l = j*dx;
      s += '<div id=a_' + j + '_' + i + ' style="position:absolute;clip:rect(' 
            + (t+1) + ',' + (l+dx) + ',' + (t+dy) + ',' + (l+1) + ');"'
            ' ondragstart="startDrag(this)" ondrag="move();" ondragend="reposition()">'
            '<img id=p_' + j + '_' + i + ' src="' + gpicture + '" width=' + picWidth 
            ' height=' + picHeight + "></div>\n";
    }

  s += '<table width="100%" style="position:absolute;top:-60;" cellpadding=cellspacing=0><tr>'
        '<td width="33%"><input style="width:120px" type=button class=but onclick="quitGame();" value="Quit Game">&nbsp;</td>'
        '<td width="33%" align=center><input style="width:120px" type=button class=but onclick="restartGame();" value="Restart Game">&nbsp;</td>'
        '<td width="33%" align=right><input style="width:120px" type=button name=butPause class=but onclick="pauseGame();" value="Pause Game"></td>'        
        '</tr><tr><td height=colspan=4></td></tr>'
        '<tr><td valign=center id=fldTime class=capt1 nowrap></td>'
        '<td align=center valign=center id=fldMoves class=capt1 nowrap></td>'
        '<td valign=center id=fldProgress class=base nowrap>'
        '<span class=bar id=divProgressBar></span></td></tr></table>'

  board.innerHTML = s                    
  gdx = dx;
  gdy = dy;
}

function startDrag(obj)
{
  if (!gactive)
  {
    if (butPause.value == "Continue Game")
      alert("Press the 'Continue Game' button above to resume the game");
    else
      alert("Press the 'Restart Game' button to start a new game");

    return;
  }
  
  gsrcx = obj.style.pixelLeft;
  gsrcy = obj.style.pixelTop;
  gcurrobjid=obj.id;    
  obj.style.zIndex = 1//make topmost layer
  gdragging=true;
}

function move()
{
  var obj,a;
  
  if (!gactivereturn;
  if (!gdraggingreturn;

  obj = eval(gcurrobjid);
  a = getRowCol(obj)
  obj.style.pixelLeft = event.clientX - (parseInt(a[0])+1)*gdx + gdx/+ document.body.scrollLeft - gleft;
  obj.style.pixelTop = event.clientY - (parseInt(a[1])+1)*gdy + gdy/+ document.body.scrollTop - gtop;
}

function reposition()
{
  var osrc,odest,x1,y1,x2,y2,cx1,cy1,cx2,cy2,s;

  if (!gactivereturn;
  if (!gdraggingreturn;
  gdragging = false;
  
  osrc = eval(gcurrobjid);
  osrc.style.zIndex = 0;

  osrc.style.display = "none";
  odest = document.elementFromPoint(event.clientX,event.clientY)
  osrc.style.display = "block";  
  
  if (!osrcreturn;
  osrc.style.pixelLeft = gsrcx;
  osrc.style.pixelTop = gsrcy;

  a = odest.id.replace('p','a');
  if (a.substr(0,2!= "a_"return;
  odest = eval(a);
  if (!odestreturn;
  
  swapPieces(osrc,odest);
  
  gmoves++;
  
  showProgress();
  
  if (isWin())
  {  
    gactive = false;
    butPause.disabled = true;
    stopTimer();
    showProgress()//needed because isWin() may update the status
    getPiece(0,0).style.clip = "rect(auto)"//show the full image
    
    //vbYesNo=4 vbYes=6 vbNo=7
    if (== VBMsgBox('!!  C  O  N  G  R  A  T  S  !!\n\n' +
      'You did it in ' + gmoves + ' moves and ' + gtime + ' secs!\n\n'
                'Do you wish to play it again?',4,"Game Over!") )
      restartGame();
  }
}

function getPiece(row,col)
{
  return eval("a_" + col + "_" + row);
}

function getRow(obj)
{
  var a = obj.id.split('_');
  return parseInt(a[1])
}

function getCol(obj)
{
  var a = obj.id.split('_');
  return parseInt(a[2]);
}

function getRowCol(obj)
{
  var a = obj.id.split('_');
  return new Array(a[1],a[2]);
}

function getClipRow(col)
{
  return (col*gdx)
}

function getClipCol(row)
{
  return (row*gdy)
}

function getX(obj)
{
  return getClipRow(getRow(obj));
}

function getY(obj)
{
  return getClipCol(getCol(obj));
}

function showStatus(msg)
{
  fldStatus.innerHTML = msg;
}

//random number between 0 and hi
function r0(hi)
{
  return Math.floor((hi)*Math.random())
}

function shuffle()
{
  var i, j, divisionsX, divisionsY;
  
  divisionsX = selCols.value;
  divisionsY = selRows.value;
  
  showStatus('Loading Game... Please Wait!');
  for (i=0;i<divisionsY;i++)
    for (j=0;j<divisionsX;j++)
    {
      swapPieces(getPiece(i,j),getPiece(r0(divisionsY),r0(divisionsX)));
    }
  
  if (isWin()) shuffle()//ensure that it is not already a won puzzle!
  showStatus('');
  showProgress();
}

function swapPieces(osrc,odest)
{
  var x1,y1,x2,y2,cx1,cy1,cx2,cy2;

  if (osrc == odestreturn//nothing to swap!
  
  x1 = osrc.style.pixelLeft;
  y1 = osrc.style.pixelTop;
  cx1 = getX(osrc);
  cy1 = getY(osrc);
  
  x2 = odest.style.pixelLeft;
  y2 = odest.style.pixelTop;
  cx2 = getX(odest);
  cy2 = getY(odest);

  //Calculate new co-ordinates 
  osrc.style.pixelLeft = x2 + (cx2 - cx1);
  osrc.style.pixelTop = y2 + (cy2 - cy1);
  odest.style.pixelLeft = x1 - (cx2 - cx1);
  odest.style.pixelTop = y1 - (cy2 - cy1);
}

function changePicture(lasturl)
{
  var picurl, locfile, re, defurl="http://",retval;

  stopPicTimer();
      
  if (selPic.value == ""return;
  if (selPic.value == "myurl")
  {
    if (lasturl != nulldefurl = lasturl;
    picurl = prompt("Please enter a valid Picture URL (JPG,GIF,PNG,BMP)",defurl);
    if (picurl == null || picurl == "")
    {
      selPic.value = "";
      return;
    }
    re = /^http\:\/\/[\w/.-~?&\\%=]*\.(JPG|JPEG|GIF|PNG|BMP)$/i;
    if (re.test(picurl))
    {
      loadPicture(picurl);
    }
    else
    {
      //yes=6 no=7 cancel=2
      retval = VBMsgBox("HMMM. Looks like an invalid url !!\n\n" + picurl + "\n\nDo you really want to proceed with it?",3,"Invalid URL?");

      if (retval == 6//yes button
        loadPicture(picurl);
      else if (retval == 2//cancel button   
        changePicture(picurl)//prompt again
      else //no button
        selPic.value = "";
      return;
    }
  }
  else if (selPic.value == "localfile")
  {
    //locfile
    loadPicture(selPic.value);
  }
  else
  {
    loadPicture(selPic.value);
  }
}

//stops the game timer if it is running
function stopTimer()
{
  if (gintervalid != -1
  {
    clearInterval(gintervalid);
    gintervalid = -1;
  }
}

function stopPicTimer()
{
  if (gpicid != -1
  {
    clearInterval(gpicid);
    gpicid = -1;
  }
}

function quitGame()
{
//  stopGame();
  stopTimer();
  gtime = 0;
  gmoves = 0;
  gactive = false;
  
  board.style.display = "none";
  board.innerHTML = "";
  divMain.style.display = "block";
  divInfo.style.display = "block";            
  divPic.style.display = "block";
//  butStart.disabled = true;
  selPic.focus();
  showStatus('');
}

function showProgress()
{
  fldTime.innerHTML = "Time:&nbsp;" + gtime + "&nbsp;secs";
  fldMoves.innerHTML = "Moves:&nbsp;" + gmoves + "&nbsp;";
  fldProgress.title = "Percentage Solved: " + gprogress + "%";
  if (gprogress < 40)
  {
    divProgressBar.innerHTML = "";
    fldProgress.innerHTML = divProgressBar.outerHTML + "&nbsp;" + gprogress + "%";
  }
  else
  {
    fldProgress.innerHTML = divProgressBar.outerHTML;
    divProgressBar.innerHTML = gprogress + "%";
  }
  divProgressBar.style.width = gprogress + "%";
}

function startGame()
{
  if (parseInt(selRows.value* parseInt(selCols.value4)
  {
    alert("Sorry. At least 4 pieces are needed for a proper jigsaw game!\n\n" +
          '     No. of Jigsaw Pieces = Rows X Cols\n\n' +
          "Please try increasing the 'Rows' and/or 'Cols'.");
    return;
  }
      
  stopTimer();
  stopPicTimer();
  gtime = 0;
  gmoves = 0;
  gactive = true;
    
  drawBoard() ;
  divMain.style.display = "none";    
  divInfo.style.display = "none"
  shuffle();
  tickTime();
  gintervalid = setInterval("tickTime()",1000);
}  

function tickTime()
{
  showProgress();
  gtime++;
}

function isWin()
{
  var i, j, divisionsX, divisionsY, obj,s="", prog=0;
  
  divisionsX = parseInt(selCols.value);
  divisionsY = parseInt(selRows.value);
  
  for (i=0;i<divisionsY;i++)
    for (j=0;j<divisionsX;j++)
    {
      obj = getPiece(i,j);
      if (obj.style.pixelLeft != || obj.style.pixelTop != 0prog++;
    }

  gprogress = 100 - Math.round((prog * 100.0(divisionsX * divisionsY));
  
  if (prog == 0
    return true;
  else
    return false;
}

function restartGame()
{
  stopTimer();
  gtime = 0;
  gmoves = 0;
  
  getPiece(0,0).style.clip = "rect(1," + gdx + "," + gdy + ",1)" ;
  shuffle();
  tickTime();
  gintervalid = setInterval("tickTime()",1000);
  butPause.value = "Pause Game";
  butPause.disabled = false;
  gactive = true;
}  

function pauseGame()
{
  if (butPause.value == "Pause Game" && gactive)
  {
    butPause.value = "Continue Game";
    gactive = false;
    stopTimer();
  }
  else
  {
    butPause.value = "Pause Game";
    gintervalid = setInterval("tickTime()",1000)//start the count again
    gactive = true;
  }
}

function checkSelection()
{
  var obj;
  
  switch (selPic.value)
  {
    case "":
      divURL.style.display = "none";
      divFile.style.display = "none";
      divPic.style.display = "none";
      butStart.disabled = true;
      butLoad.disabled = true;
      gloaded = false;
    showStatus("<marquee width=300 loop=4>" +
               "Select a Picture for the Jigsaw Puzzle from the drop down above." +
               "</marquee>");
      break;
      
    case "myurl":
      divURL.style.display = "block";
      divFile.style.display = "none";
      divPic.style.display = "none";
      butStart.disabled = true;
      obj = document.getElementById("fldURL");
      butLoad.disabled = (obj.value == ""true false;
      gloaded = false;
      obj.select();
      obj.focus();
      showStatus("Type in the URL of the Picture you wish to<br>" 
                  "play the Jigsaw Game with.<p>" +
                  "Press 'Load Picture' button when done.");
      break;
      
    case "localfile":
      divURL.style.display = "none";
      divFile.style.display = "block";
      divPic.style.display = "none";
      butStart.disabled = true;
      obj = document.getElementById("fldFile");
      butLoad.disabled = (obj.value == ""true false;
      gloaded = false;
      obj.select();
      obj.focus();
      showStatus("Type in the Path to a Picture file (JPG,GIF,BMP,PNG)<br>" +
                 "OR use the 'Browse' button to locate a file in your<br>" +
                 "machine or on a shared network drive.<p>" 
                 "Press the 'Load Picture' button when done.");
      break;
      
    default:
      divURL.style.display = "none";
      divFile.style.display = "none";
      divPic.style.display = "none";
      butStart.disabled = true;
      butLoad.disabled = false;
      butLoad.focus();
      gloaded = false;
      selPic.disabled = true;
      checkPicture();
  }
}

function checkPicture()
{
  var picsrc, picurl, retval, re, re2;
  
  stopPicTimer();
  butStart.disabled = true;

  if (butLoad.value == "Cancel Loading")
  {
    selPic.disabled = false;
    butLoad.value = "Load Picture";  
    divPic.style.display = "none";
    showStatus("<marquee width=300 loop=4>" +
               "Select a Picture for the Jigsaw Puzzle from the drop down above." +
               "</marquee>");
    return;
  }
  
  switch (