import java.awt.*;
import java.applet.*;




public class P5 extends Applet implements Runnable{

Image        offImage;          /* variable Declerations */  
Thread       anim;
AudioClip    MoveClip;
SoundList    soundlist;
int[]        P;
int          B,H,x,y,i,j,direc,delay,m,n,alt,moves;
int	     font_s_width,font_height,font_mv_width;
boolean      moving,bingo;
Image[]      Tiles;
Image        Q,bing;
Graphics     g2;






private void mixIt()
{
 i=1;                             /* mix up tiles */
 j=0;
 while(j<998)
  {  
    y=(int)(Math.random()*99)%15; 
    x=P[i];
    P[i]=P[y];
    P[y]=x;
    if (y!=i) {j++;}
    i=y;
  } 
 bingo = false;
 moves = 0;
}





public void init()		/* initiates the Puzzle */	
{
 showStatus("Please wait a second...");
 soundlist = new SoundList(this, getCodeBase());
 soundlist.startLoading("explosion.au");
 String s=getParameter("file");
 MediaTracker r=new MediaTracker(this);  
 Q=getImage(getCodeBase(),s);
 bing=getImage(getCodeBase(),"Bingo.GIF");
 r.addImage(Q,0);
 r.addImage(bing,1);
 moving=false;              
 delay = 1000 /25;
 setBackground(java.awt.Color.red);
 setFont(new Font("Arial",Font.BOLD,16));
 P=new int [16];                  /* Array for tiles   */
 j=0;                             /* number tiles      */
 while(j<16){P[j]=j++;}
 try {r.waitForAll();}            /* Now get the image */
 catch(InterruptedException e){} 
 B=Q.getWidth(this)/4;            /* Width of Image    */
 H=Q.getHeight(this)/4;           /* Height ...        */
 Tiles=new Image [15];         
 for (i=0;i<15;i++)
  {                               /* Split up the image*/
    Tiles[i]=createImage(B,H);
    Graphics g2= Tiles[i].getGraphics();
    g2.drawImage(Q,-(i%4)*B,-(i/4)*H,this);
    g2.dispose();
  }
 mixIt();
}







public void run()		/* Animation of moving Tiles */
{
 i=0; 
 long startTime=System.currentTimeMillis();
 while ((Thread.currentThread()==anim) && (m+n>-4) && (m+n<4))
  {
   switch (direc) 
    {
     case 1: n -= 1;
             break;
     case 2: n += 1;
             break;
     case 3: m += 1;
             break;
     case 4: m -= 1;
             break;
    }
   repaint();
   try
    {
      startTime += delay;
      Thread.sleep(Math.max (0,startTime-System.currentTimeMillis() ));
    } 
   catch (InterruptedException e) 
    {
      break;
    }
 }
 if (bingo) 
   {
      repaint();
      try
      {
       Thread.sleep(4000);
      } 
      catch (InterruptedException e) {}
    moves=0;
    repaint();
   }
moving=false;
anim.stop();
}








public boolean mouseDown(java.awt.Event evt,int t,int u)  /* Moving a tile */
{
 if (bingo)  /* Was the Puzzle already finished? */
  {
   mixIt(); 
   repaint();
  } 
 else
  {
    if (!moving) 
    {
     boolean b=false;
     x=t/B;
     y=u/H;
     if(x<4 && y<4)
       {
        x=x+4*y;
        i=-1;
        while (P[++i]!=15){}
        switch (i-x)
         {
           case -1 : if(i%4!=3) {b=true; direc=4;} break; 
           case  1 : if(i%4!=0) {b=true; direc=3;} break;
           case -4 : b=true; direc=2; break;
           case  4 : b=true; direc=1; break;
         }
       if (b)
         {
           P[i]=P[x];P[x]=15;
           alt=P[i];
           m=0; n=0;
           moving = true;
           moves++;

           if (MoveClip == null)
            {
              MoveClip = soundlist.getClip("explosion.au");
            }
           else
            { 
              MoveClip.play();     
            }    

           if (direc<3) offImage=createImage(B,2*H);
             else offImage=createImage(2*B,H); /*creates new Bitmap*/
           g2=offImage.getGraphics();          /*of the size of 2 tiles */
           g2.setColor(java.awt.Color.red); 
           anim = new Thread(this);
           anim.start();
           j=0;
           while((j<16) && (P[j]==j++)) {}
           bingo=(j==16);
         }
    }
  }
  }
 return true;
}






public void paint(Graphics g)         /* Repaint the whole Puzzle */
{ 
if (bingo) 
{
 g.drawImage(Q,0,0,this);
}
else 
{
 int i=-1; while(++i<16) 
 {
  if(P[i]!=15)
  {
   g.drawImage(Tiles[P[i]],i%4*B,i/4*H,this);
  }
  else 
  {
   g.setColor(java.awt.Color.red);
   g.fillRect(i%4*B,i/4*H,B,H);
  }
 }
}
score(g);
showStatus("Thorsten's Puzzle Applet"); 
}







private void score(Graphics g)      /* Output of number of moves */
{
 font_s_width = g.getFontMetrics().stringWidth("5000");
 font_height  = g.getFontMetrics().getHeight();
 font_mv_width= g.getFontMetrics().stringWidth("Moves: ");
 g.clearRect(68, 4*H+4, 68+font_mv_width+font_s_width+4, 4*H+8+font_height);
 g.setColor(java.awt.Color.black);
 g.drawString("Moves: "+moves,14,4*H+24);
 g.setColor(java.awt.Color.yellow);
 g.drawString("Moves: "+moves,10,4*H+20);
}




public void update(Graphics g)          /* Change Graphic */
{
 if (moves==0)
  {
    paint (g);
  }
else
  {
  g2.setColor(java.awt.Color.red);
  g2.fillRect(0,0,2*B,2*H);

  switch (direc) 
   {         
    case 1: g2.drawImage(Tiles[alt],0,-n*H/4,this);
            g.drawImage(offImage,x%4*B,x/4*H,this);
            break;
    case 2: g2.drawImage(Tiles[alt],0,-n*H/4+H,this);
            g.drawImage(offImage,x%4*B,x/4*H-H,this);
            break;
    case 3: g2.drawImage(Tiles[alt],m*B/4,0,this);
            g.drawImage(offImage,x%4*B,x/4*H,this);
            break;
    case 4: g2.drawImage(Tiles[alt],m*B/4+B,0,this);
            g.drawImage(offImage,x%4*B-B,x/4*H,this); 
            break;
   }
   if ((m==4) || (m==-4) || (n==4) || (n==-4))
   {
    score(g);
      if (bingo) g.drawImage (bing,0,0,4*B,4*H,this);
   }
  }
}


public String getAppletInfo()    /* Just in case someone wants to know... */
{
 return "Thorstens Puzzle Applet. No Copyright, Garanty or stuff like that";
}


public String[][] getParameterInfo()   /* Just for the case someone wants to use it! */
{
 String[][] info = {{"file"," URL","a GIF or JPEG Image"}};
 return info;
}    
}

