import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;

public class r_cube extends Applet implements Runnable{

    Thread th = null;
    int mtd[][] = new int[3][3];
    int ccd[][] = {{1,1,1,1},{1,1,0,0},{1,0,0,1},{0,0,1,1},{0,1,1,0},{0,0,0,0}};
    int tc[][] = {{2,1,4,3},{1,5,1,0},{5,2,0,2},{3,0,3,5},{0,4,5,4},{4,3,2,1}};
    Color cc[] = new Color[2];
    double r2 = 1.414214 , pi = 3.141592;
    double ang;
    int sx = 2,sy = 1;
    int dx = 1,dy = 1;
    int cx,cy,p1x,p1y,p2x,p2y,p3x,p3y,l1,l2;
    int swx = 1 , swy = 0 , fg = 1;
    int sn = 0 , dn = 4;
    Button rep;
    Image os;
    Graphics og;

    public void init(){

        setBackground(Color.white);
        os = createImage(220,240);
        og = os.getGraphics();
        ang = pi / 2;
        for(int ix = 0;ix < 3;ix ++){
            for(int iy = 0;iy < 3;iy ++){
                mtd[iy][ix] = 0;
            }
        }
        mtd[1][1] = -1 ; mtd[1][2] = -1 ;

        cc[0] = new Color(200,20,20);
        cc[1] = new Color(250,250,250);
        setLayout(new BorderLayout());
        Panel pan = new Panel();
        pan.setLayout(new FlowLayout());
        pan.add(rep = new Button("  replay  "));
        add("South",pan);

        addMouseListener(
            new MouseAdapter(){
                public void mousePressed(MouseEvent e){
                    if(fg == 0){
                        dx = (e.getX() - 20) / 60;
                        dy = (e.getY() - 20) / 60;
                        if((sx == dx) && (sy == dy + 1)){
                            swx = 0 ; swy = 1 ;
                            dn = mtd[dy][dx] ; sn = tc[mtd[dy][dx]][3];
                            mtd[dy][dx] = -1;mtd[sy][sx] = -1;
                            ang = 0;fg = 1;
                            th.resume(); 
                        }
                        if((sx == dx) && (sy == dy - 1)){
                            swx = 0 ; swy = -1 ;
                            dn = mtd[dy][dx] ; sn = tc[mtd[dy][dx]][1];
                            mtd[dy][dx] = -1;mtd[sy][sx] = -1;
                            ang = 0;fg = 1;
                            th.resume(); 
                        }
                        if((sx == dx + 1) && (sy == dy)){
                            swx = 1 ; swy = 0 ; 
                            dn = mtd[dy][dx] ; sn = tc[mtd[dy][dx]][0];
                            mtd[dy][dx] = -1;mtd[sy][sx] = -1;
                            ang = 0;fg = 1;
                            th.resume(); 
                        }
                        if((sx == dx - 1) && (sy == dy)){
                            swx = -1 ; swy = 0 ;
                            dn = mtd[dy][dx] ; sn = tc[mtd[dy][dx]][2];
                            mtd[dy][dx] = -1;mtd[sy][sx] = -1;
                            ang = 0;fg = 1;
                            th.resume(); 
                        }
                    }
                }
            }
        );

        rep.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                for(int ix = 0;ix < 3;ix ++){
                    for(int iy = 0;iy < 3;iy ++){
                        mtd[iy][ix] = 0;
                    }
                }
                mtd[1][1] = -1 ; mtd[1][2] = -1 ;
                sx = 2 ; sy = 1;
                dx = 1 ; dy = 1;
                swx = 1 ; swy = 0 ; fg = 1;
                sn = 0 ; dn = 4;
                ang = pi / 2;
                th.resume(); 
            }
        });

    }

    public void paint(Graphics g){
        og.setColor(Color.darkGray);
        og.fill3DRect(10,10,200,200,true);
        og.setColor(Color.lightGray);
        og.fillRect(20,20,180,180);
        for(int px = 0;px < 3;px ++){
            for(int py = 0;py < 3;py ++){
                if(mtd[py][px] > -1){
                    og.setColor(cc[ccd[mtd[py][px]][1]]);
                    og.fillRect(px * 60 + 20,py * 60 + 20,30,30);
                    og.setColor(cc[ccd[mtd[py][px]][2]]);
                    og.fillRect(px * 60 + 20,py * 60 + 50,30,30);
                    og.setColor(cc[ccd[mtd[py][px]][0]]);
                    og.fillRect(px * 60 + 50,py * 60 + 20,30,30);
                    og.setColor(cc[ccd[mtd[py][px]][3]]);
                    og.fillRect(px * 60 + 50,py * 60 + 50,30,30);
                    og.setColor(Color.black);
                    og.drawRect(px * 60 + 20,py * 60 + 20,60,60);
                }
            }
        }

        if(swx == -1){
            cx = dx * 60 + 20 ; cy = dy * 60 + 20;
            p1x = cx + (int)(Math.round((60 * Math.cos(ang + (pi / 2))))) ; p1y = cy;
            p2x = cx + (int)(Math.round((r2 * 60 * Math.cos(ang + (pi / 4))))) ; p2y = cy;
            p3x = cx + (int)(Math.round((60 * Math.cos(ang)))) ; p3y = cy;
            l1 = p2x - p1x ; l2 = p3x - p2x;
        }else if(swx == 1){
            cx = sx * 60 + 20 ; cy = sy * 60 + 20;
            p1x = cx - (int)(Math.round((r2 * 60 * Math.cos(ang + (pi / 4))))) ; p1y = cy;
            p2x = cx - (int)(Math.round((60 * Math.cos(ang)))) ; p2y = cy;
            p3x = cx - (int)(Math.round((60 * Math.cos(ang + (pi / 2))))) ; p3y = cy;
            l1 = p3x - p1x ; l2 = p1x - p2x;
        }else if(swy == -1){
            cx = dx * 60 + 20 ; cy = dy * 60 + 20;
            p1x = cx ; p1y = cy + (int)(Math.round((60 * Math.cos(ang + (pi / 2)))));
            p2x = cx ; p2y = cy + (int)(Math.round((r2 * 60 * Math.cos(ang + (pi / 4)))));
            p3x = cx ; p3y = cy + (int)(Math.round((60 * Math.cos(ang))));
            l1 = p2y - p1y ; l2 = p3y - p2y;
        }else if(swy == 1){
            cx = sx * 60 + 20 ; cy = sy * 60 + 20;
            p1x = cx ; p1y = cy - (int)(Math.round((r2 * 60 * Math.cos(ang + (pi / 4)))));
            p2x = cx ; p2y = cy - (int)(Math.round((60 * Math.cos(ang))));
            p3x = cx ; p3y = cy - (int)(Math.round((60 * Math.cos(ang + (pi / 2)))));
            l1 = p3y - p1y ; l2 = p1y - p2y;
        }
        if((swx == 0) && (fg == 1)){
            og.setColor(cc[ccd[dn][1]]); og.fillRect(p1x,p1y,30,l1 / 2);
            og.setColor(cc[ccd[dn][2]]); og.fillRect(p1x,p1y + l1 / 2,30,l1 / 2);
            og.setColor(cc[ccd[dn][0]]); og.fillRect(p1x + 30,p1y,30,l1 / 2);
            og.setColor(cc[ccd[dn][3]]); og.fillRect(p1x + 30,p1y + l1 / 2,30,l1 / 2);
            og.setColor(cc[ccd[sn][1]]); og.fillRect(p2x,p2y,30,l2 / 2);
            og.setColor(cc[ccd[sn][2]]); og.fillRect(p2x,p2y + l2 / 2,30,l2 / 2);
            og.setColor(cc[ccd[sn][0]]); og.fillRect(p2x + 30,p2y,30,l2 / 2);
            og.setColor(cc[ccd[sn][3]]); og.fillRect(p2x + 30,p2y + l2 / 2,30,l2 / 2);
            og.setColor(Color.black);
            og.drawRect(p1x,p1y,60,l1);
            og.drawRect(p2x,p2y,60,l2);
        }else if((swy == 0) && (fg == 1)){
            og.setColor(cc[ccd[dn][1]]); og.fillRect(p1x,p1y,l1 / 2,30);
            og.setColor(cc[ccd[dn][2]]); og.fillRect(p1x,p1y + 30,l1 / 2,30);
            og.setColor(cc[ccd[dn][0]]); og.fillRect(p1x + l1 / 2,p1y,l1 / 2,30);
            og.setColor(cc[ccd[dn][3]]); og.fillRect(p1x + l1 / 2,p1y + 30,l1 / 2,30);
            og.setColor(cc[ccd[sn][1]]); og.fillRect(p2x,p2y,l2 / 2,30);
            og.setColor(cc[ccd[sn][2]]); og.fillRect(p2x,p2y + 30,l2 / 2,30);
            og.setColor(cc[ccd[sn][0]]); og.fillRect(p2x + l2 / 2,p2y,l2 / 2,30);
            og.setColor(cc[ccd[sn][3]]); og.fillRect(p2x + l2 / 2,p1y + 30,l2 / 2,30);
            og.setColor(Color.black);
            og.drawRect(p1x,p1y,l1,60);
            og.drawRect(p2x,p2y,l2,60);
        }
        g.drawImage(os,0,0,this );
    }

    public void start(){    
        if(th == null){
            th = new Thread(this);
            th.start();
        }
    }

    public void stop(){
        th = null;
    }

    public void run(){
        while (th != null){
            try {
                ang = ang + pi / 50;
                if(ang > pi / 2){
                    mtd[sy][sx] = sn;
                    sx = dx ; sy = dy;
                    fg = 0;
                    th.suspend();
                }
                Thread.sleep(50);
            }
            catch (InterruptedException e){ }
            repaint();
        }
    }
    public void update( Graphics g )
    {
        paint( g ) ;
    }
}