import java.awt.*;
import java.applet.*;




public class P6 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)%24; 
    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 [25];                  /* Array for tiles   */
 j=0;                             /* number tiles      */
 while(j<25){P[j]=j++;}
 try {r.waitForAll();}            /* Now get the image */
 catch(InterruptedException e){} 
 B=Q.getWidth(this)/5;            /* Width of Image    */
 H=Q.getHeight(this)/5;           /* Height ...        */
 Tiles=new Image [24];         
 for (i=0;i<24;i++)
  {                               /* Split up the image*/
    Tiles[i]=createImage(B,H);
    Graphics g2= Tiles[i].getGraphics();
    g2.drawImage(Q,-(i%5)*B,-(i/5)*H,this);
    g2.dispose();
  }
 mixIt();
}







public void run()		/* Animation of moving Tiles */
{
 i=0; 
 long startTime=System.currentTimeMillis();
 while ((Thread.currentThread()==anim) && (m+n>-5) && (m+n<5))
  {
   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<5 && y<5)
       {
        x=x+5*y;
        i=-1;
        while (P[++i]!=24){}
        switch (i-x)
         {
           case -1 : if(i%5!=4) {b=true; direc=4;} break; 
           case  1 : if(i%5!=0) {b=true; direc=3;} break;
           case -5 : b=true; direc=2; break;
           case  5 : b=true; direc=1; break;
         }
       if (b)
         {
           P[i]=P[x];P[x]=24;
           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<25) && (P[j]==j++)) {}
           bingo=(j==25);
         }
    }
  }
  }
 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<25) 
 {
  if(P[i]!=24)
  {
   g.drawImage(Tiles[P[i]],i%5*B,i/5*H,this);
  }
  else 
  {
   g.setColor(java.awt.Color.red);
   g.fillRect(i%5*B,i/5*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, 5*H+4, 68+font_mv_width+font_s_width+4, 5*H+8+font_height);
 g.setColor(java.awt.Color.black);
 g.drawString("Moves: "+moves,14,5*H+24);
 g.setColor(java.awt.Color.yellow);
 g.drawString("Moves: "+moves,10,5*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/5,this);
            g.drawImage(offImage,x%5*B,x/5*H,this);
            break;
    case 2: g2.drawImage(Tiles[alt],0,-n*H/5+H,this);
            g.drawImage(offImage,x%5*B,x/5*H-H,this);
            break;
    case 3: g2.drawImage(Tiles[alt],m*B/5,0,this);
            g.drawImage(offImage,x%5*B,x/5*H,this);
            break;
    case 4: g2.drawImage(Tiles[alt],m*B/5+B,0,this);
            g.drawImage(offImage,x%5*B-B,x/5*H,this); 
            break;
   }
   if ((m==5) || (m==-5) || (n==5) || (n==-5))
   {
    score(g);
      if (bingo) g.drawImage (bing,0,0,5*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;
}    
}

