hj_
hj_

Reputation: 55

Implementing slide puzzle using Javascript

First off, thank you for reading this question. With this javascript code, I'm trying to implement a 4x4 slide number puzzle, which looks like this when completed. :

1 2 3 4

5 6 7 8

9 10 11 12

13 14 15 [blank]

Each number are represented by .gif number files which are on the same folder where this HTML file is. When a user clicks "START" button below the puzzle, it shuffles pieces by repetitively swapping randomly chosen two pieces. (shuffle function)

When a user clicks a piece adjacent to the blank piece then it swaps the two. (movePiece function)

But the problem is when I click the START button and the piece adjacent to the blank piece, nothing happens.. even though except for this code's logic and algorithm is not different from the answer that my instructor's given and I can't find where is causing this problem.

Can anyone help me find out where is wrong with this code?

Any advice would be much appreciated.

<html>
<head>
    <title>15 Puzzle Game</title>
    <meta name="generator" content="Microsoft FrontPage 4.0" charset="UTF-8">
    <script language="JavaScript">

var completed=true; 

function tokenize(sep,str){
  tokens = new Array(); 

  i=0;
  while(1)
  {
     idx=str.indexOf(sep);
     if(idx == -1)
     {
          if(str.length>0)
          {
              tokens[i]=str;
          } 
          break;
     }
     tokens[i++]=str.substring(0,idx); 
     str=str.substr(idx+1);
  }
  return tokens;
}


function getX(idx)
{
  var rest=idx-Math.floor(idx/4)*4; 
  return (rest==0)?4:rest;
}


function getY(idx)
 {
    return Math.floor((idx-1)/4)+1;
 }


function getIndex(x,y)
 {
   return x+(y-1)*4;
 }


function newDirection(pos)
{
  var dir;

  if ((pos==2)||(pos==3)) dir=(Math.floor(Math.random()+0.5)==0)?-1:1;
  else dir=(pos==1)?1:-1;
  return (pos+dir);
}


function newIndex(idx)
{
  var x,y;

  x=getX(idx);
  y=getY(idx);
  if (Math.floor(Math.random()+0.5)==0) x=newDirection(x);
  else y=newDirection(y);
  return getIndex(x,y);
}


function isComplete()
{

  if(completed) return 0;

    for(var i = 1; i <= document.images.length; i++){
    if(document.images[i-1].src != i+".gif") return 0;
  }
  return 1;
}

function getNum(idx){
  var index = idx - 1;
  var token[] = tokenize("/",document.images[index].src);
  var numOfTokens = tokenize("/",document.images[index].src).length;
  var num = tokenize(".", token[numOfTokens-1])[0];
  return Number(num);
}

function shuffle()
 {
  var puzzles=new Array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);

  iter=Math.floor(Math.random()*200+0.5)+100;

  for (i=0;i<iter;i++)
  {
    var ranNum = Math.floor(Math.random()*16)+1;
    var newNum = newIndex(ranNum);
    var temp = puzzles[ranNum-1];
    puzzles[ranNum-1] = puzzles[newNum-1];
    puzzles[newNum-1] = temp;
    }
  }
  for(i=1;i<document.images.length+1;i++){
      document.images[i-1].src = ""+puzzles[i-1]+".gif";
  }
  completed = false;
}
function movePiece(idx)
{
  x = getX(idx);
  y = getY(idx);
  var flag = 0;
  var tempIdx;

  for(i=-1; i<=1 ; i=i+2){
    if ((x==2)||(x==3)) dir=i;
    else dir=(x==1)?1:-1;
    var tmpx= (x+dir);
    tempIdx = getIndex(tmpx,y);
    if(getNum(tempIdx) == 16){ flag = 1; midx=tempIdx; }
  }
   for(i=-1; i<=1 ; i=i+2){
    if ((y==2)||(y==3)) dir=i;
    else dir=(y==1)?1:-1;
    var tmpy= (y+dir);
    tempIdx = getIndex(x,y);
    if(getNum(tempIdx) == 16){ flag = 1; midx=tempIdx; }
  }

  if (flag == 1){ 
    document.images[midx-1].src = document.images[idx-1].src;
    document.images[idx-1].src = "16.gif";
  }  

  if(isComplete()) alert('Congratulation!');
  completed = true;
}
    </script>

</head>

<body bgcolor="silver" text="black" link="#0000EE" vlink="#551A8B" alink="red">
    <h2 align="center">
        15 Puzzle</h2>
    <div align="center">
        <table border>
            <tr>
                <td width="50%" align="center">

                <script language="JavaScript">
with(window.document)
  {
    open();
    writeln('<table border=1 cellpadding=0 cellspacing=1>');
    for(var i=1;i<17;i++)
       {
         if(i==1 || i==5 || i==9 || i==13 )
           {
             writeln('<tr>');
           }
         writeln('  <td width=49 height=49>');
         writeln('      <a href=JavaScript:movePiece('+i+');>');
         writeln('       <img src=',i,'.gif border=0 width=49 height=49 name=i',i,'></a>');
         writeln('  </td>');
         if(i==4 || i==8 || i==12 || i==16 )
           {
              writeln('</tr>');
           }
        }
      writeln('</table>');
      close();
    }
                    </script>

                </td>
            </tr>
        </table>
    </div>
    <p align="center">
        <br>
    </p>
    <form method="get">
    <p align="center">
        <input type="button" value="START" onClick="shuffle()"></p> 
    </form>
</body>
</html>
javascript

and this is working code

<html>
<head>
    <title>15 Puzzle Game</title>
    <meta charset="UTF-8">

    <script language="JavaScript">

var completed=true;

function tokenize(sep,str)
{
  tokens = new Array();

  i=0;
  while(1)
  {
     idx=str.indexOf(sep);
     if(idx == -1)
     {
          if(str.length>0)
          {
              tokens[i]=str;
          } 
          break;
     }
     tokens[i++]=str.substring(0,idx); 
     str=str.substr(idx+1);
  }
  return tokens;
}

function getX(idx)
{
  var rest=idx-Math.floor(idx/4)*4; 
  return (rest==0)?4:rest;
}

function getY(idx)
 {
    return Math.floor((idx-1)/4)+1;
 }

function getIndex(x,y)
 {
   return x+(y-1)*4;
 }

function newDirection(pos)
{
  var dir;

  if ((pos==2)||(pos==3)) dir=(Math.floor(Math.random()+0.5)==0)?-1:1;
  else dir=(pos==1)?1:-1;
  return (pos+dir);
}

function newIndex(idx)
{
  var x,y;

  x=getX(idx);
  y=getY(idx);
  if (Math.floor(Math.random()+0.5)==0) x=newDirection(x);
  else y=newDirection(y);
  return getIndex(x,y);
}

function isComplete() {

    if(completed)
        return false;

    var prev = getPiece(1);
    for(var i = 2; i < 17; i++) {
        var current = getPiece(i);
        if(current != prev+1)
            return false;
        prev = current;
    }
    return true;
}

function shuffle()
 {
  var puzzles=new Array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);

  iter=Math.floor(Math.random()*200+0.5)+100;
  var blank = 15; 
  for (i=0; i<iter; i++)
  {
      var move = newIndex(blank+1)-1;
      var t = puzzles[blank];
      puzzles[blank] = puzzles[move];
      puzzles[move] = t;
      blank = move;
  }

  for(i = 0; i < 16; i++)
      document.images[i].src = ""+puzzles[i]+".gif";

  completed = false;
}

function movePiece(idx)
{
    var current = getPiece(idx);
    if(current == 16)
        return;

    var x = getX(idx);
    var y = getY(idx);

      var flag=false, midx=idx;

    var dx = [0, 0, -1, 1], dy = [-1, 1, 0, 0]; 
    for(var i = 0; i < 4; i++) {
        if(1 <= x+dx[i] && x+dx[i] <= 4 && 1 <= y+dy[i] && y+dy[i] <= 4) {
            if(getPiece(getIndex(x+dx[i], y+dy[i])) == 16) { 
                flag = true;
                midx = getIndex(x+dx[i], y+dy[i]);
                break;
            }
        }
    }

    if(flag) {
        var t = document.images[idx-1].src;
        document.images[idx-1].src = document.images[midx-1].src;
        document.images[midx-1].src = t;
    }

  if(isComplete()) {
       alert("Congratulation!");
       completed = true;
  }
}

function getPiece(idx) {
    idx--;
    var len = tokenize("/", document.images[idx].src).length;
    return Number(tokenize(".", tokenize("/", document.images[idx].src)[len-1])[0]);
}

    </script>

</head>

<body bgcolor="silver" text="black" link="#0000EE" vlink="#551A8B" alink="red">
    <h2 align="center">
        15 Puzzle</h2>
    <div align="center">
        <table border>
            <tr>
                <td width="50%" align="center">

                    <script language="JavaScript">

                        with(window.document)
  {
    open();
    writeln('<table border=1 cellpadding=0 cellspacing=1>');
    for(var i=1;i<17;i++)
       {
         if(i==1 || i==5 || i==9 || i==13 )
           {
             writeln('<tr>');
           }
         writeln('  <td width=49 height=49>');
         writeln('      <a href=JavaScript:movePiece('+i+');>');
         writeln('       <img src=',i,'.gif border=0 width=49 height=49 name=i',i,'></a>');
         writeln('  </td>');
         if(i==4 || i==8 || i==12 || i==16 )
           {
              writeln('</tr>');
           }
        }
      writeln('</table>');
      close();
    }
                </script>

                </td>
            </tr>
        </table>
    </div>
    <p align="center">
        <br>
    </p>
    <form method="get">
    <p align="center">
        <input type="button" value="START" onClick="shuffle()"></p> 
    </form>

</body>
</html>

Upvotes: 0

Views: 755

Answers (1)

marzelin
marzelin

Reputation: 11600

The code you provided isn't a good read, so I've created my own version in React. I hope it'll help you to figure things out or at least inspire you to learn React.

https://codesandbox.io/s/wq8n9k5jr7

Upvotes: 0

Related Questions