import java.net.*; import java.awt.image.*; import java.applet.Applet; import java.awt.*; import java.lang.*; /* The 15 Puzzle - Sameer Singh (12/06/1996) */ class loadThread extends Thread { MediaTracker tracker; piece owner; Image pic; int index; String image_name; public loadThread(String str,String image_name, piece obj,int index) { super(str); owner = obj; this.image_name = image_name; this.index = index; } public void run() { //System.out.println("Entering run of thread "+index); pic = owner.obj.getImage(owner.obj.getDocumentBase(),image_name); //owner.obj.tracker.addImage(pic,index); tracker = new MediaTracker(owner.obj); tracker.addImage(pic,index); try { tracker.waitForID(index); } catch (InterruptedException e) { } owner.setImage(pic); //owner.draw(); //System.out.println("finished "+getName()); } } class piece { Integer value; // the value of the piece Integer x_pos,y_pos; // the on screen position of the piece int width=50,height=50; Graphics gc; int right,left,up,down; Image pic; int flags; puzzle obj; loadThread img_thread; piece(int index,int val, Graphics agc, int x, int y,Image pict,puzzle obj) { int temp; /*if (pict != null) { pic = pict; obj=obj; } else { pic = null; obj=null; } if (pict != null) { pict = pic; } */ if (obj != null) { this.obj = obj; pic = null; //pic = obj.getImage(obj.getDocumentBase(),"skippy_"+val+".gif"); img_thread = new loadThread("thread"+index, obj.image_name+val+".gif", this, index); img_thread.start(); // obj.tracker.addImage(pic,index); } value = new Integer(val); gc = agc; x_pos = new Integer(x); y_pos = new Integer(y); // RIGHT temp = index+1; if ((temp == 4) || ( temp == 8) || (temp ==12) || (temp==16)) { right = -1; }else{ right = temp; } // LEFT temp = index-1; if ((temp == 3) || (temp == 7) || (temp == 11) ) { left = -1; }else{ left = temp; } // UP temp = index-4; if ((temp<0)) { up = -1; } else { up = temp; } // DOWN temp = index+4; if ((temp >= 16)) { down = -1; } else { down = temp; } // !!! draw(); } public void setImage(Image pic) { if (pic != null) { this.pic = pic; } } // checks if a point is inside the piece public boolean point_inside (int x, int y) { if ((x >= x_pos.intValue()) && (y >= y_pos.intValue()) && (x <= x_pos.intValue()+width) && (y <= y_pos.intValue()+height)) { return true; } else { return false; } } // RETURNS TRUE IF A POINT IS IN THE SAME COL AS y public boolean same_col(int x) { return ((x > x_pos.intValue()) && (x < x_pos.intValue()+height)); } // RETURNS TRUE IF A POINT IS IN THE SAME ROW AS x public boolean same_row(int y) { return ((y > y_pos.intValue()) && (y < y_pos.intValue()+width)); } public boolean toLeft(piece p) { return (x_pos.intValue() < p.x_pos.intValue()); } public boolean toRight(piece p) { return (x_pos.intValue() > p.x_pos.intValue()); } public boolean above(piece p) { return (y_pos.intValue() < p.y_pos.intValue()); } public boolean below(piece p) { return (y_pos.intValue() > p.y_pos.intValue()); } public void xchg(piece blank) { Integer temp; Image temp_pic; temp = value; value = blank.value; blank.value = temp; if (pic != null ) { temp_pic = pic; pic = blank.pic; blank.pic = temp_pic; } draw(); blank.draw(); } public void draw() { //System.out.println("In draw\n"); if (piece.value.intValue() == 16) { gc.setColor(Color.black); gc.fillRect(x_pos.intValue(),y_pos.intValue(),width,height); gc.drawRect(x_pos.intValue(),y_pos.intValue(),width,height); } else if (obj.level_indicator.level()==0) { gc.setColor(Color.yellow); gc.fillRect(x_pos.intValue(),y_pos.intValue(),width,height); gc.setColor(Color.black); gc.drawRect(x_pos.intValue(),y_pos.intValue(),width,height); //System.out.println(value.toString()); //gc.drawString(value.toString(),(int)width/2,(int)height/2); // gc.drawString(value.toString(),x_pos.intValue()+width/2,y_pos.intValue()+height/2); gc.setFont(new Font("Times", Font.BOLD, 16)); gc.drawString(value.toString(),x_pos.intValue()+(width-gc.getFontMetrics().stringWidth(value.toString()))/2,y_pos.intValue()+height/2); } else { gc.setColor(Color.black); gc.drawRect(x_pos.intValue(),y_pos.intValue(),width,height); gc.drawImage(pic,x_pos.intValue(),y_pos.intValue(),null); if (obj.level_indicator.level() == 2) { gc.setColor(Color.yellow); gc.setFont(new Font("Times", Font.BOLD, 16)); gc.drawString(value.toString(),x_pos.intValue()+(width-gc.getFontMetrics().stringWidth(value.toString()))/2,y_pos.intValue()+height/2); } } } } /* THIS PUZZLE IS 1-15 IN ORDER */ abstract class puzzle_layout { protected int win[] = new int[16]; protected int win_index, start_index; protected int i; puzzle puz; puzzle_layout() { } // RETURN THE STARTING POSITION OF THE BLANK PIECE public int startPos() { return start_index; } // RETURN THE WINNING POSITION OF THE BLANK PIECE public int winPos() { return win_index; } // CHECKS IF THE PUZZLE IS COMPLETE public abstract boolean puzzle_complete(); } class simple_puzzle extends puzzle_layout { simple_puzzle(int start_pos,puzzle puzl) { int i; for (i = 0; i <= (16-1); i++) { win[i] = i+1; } win_index = 15; start_index = start_pos; puz = puzl; } public boolean puzzle_complete() { int i; if (puz.getBlankLocValue() != win_index) { return false; } for (i=0; i<= (16-1); i++) { if (puz.getLocValue(i) != win[i]) { return false; } } return true; } } /*******************************************************************/ // THIS CLASS IS USED TO PROVIDE A UNIQUE RANDOM VALUE FROM // A RANGE OF VALUES class random_value { int value[]; int total; random_value(int first, int last){ int i; total = last - first +1; value = new int[total]; for (i=0; i 2) { level = 0; } } public boolean inside (int x, int y) { return (((x >= x_pos.intValue()) && (y >= y_pos.intValue()) && (x <= x_pos.intValue()+width) && (y <= y_pos.intValue()+height))); } public void paint() { String Level; Graphics gc = puz.myG; //System.out.println("In level painter\n"); gc.setColor(Color.black); gc.fillRect(x_pos.intValue(),y_pos.intValue(),width,height); gc.setColor(Color.yellow); gc.setFont(new Font("Times", Font.BOLD, 16)); Level = "View 1"; if (level == 1) { Level = "View 2"; } else if (level == 2) { Level = "View 3"; } gc.drawString(Level,x_pos.intValue()+(width-gc.getFontMetrics().stringWidth(Level))/2,y_pos.intValue()+height/2); } } /* THIS CLASS CHECKS WHETHER ALL IMAGES HAVE BEEN OBTAINED IF NOT IT RETURNS A STRING ASKING THE USER TO WAIT. IT EVENTUALY DISPLAYS A MESSAGE INDICATING COMPLETION OF THE DOWNLOAD */ class media_checker extends Thread { Graphics myG; puzzle puz; public media_checker(Graphics gc,puzzle puz) { super("mediachecker"); myG = gc; this.puz = puz; } public void run() { int j; String str; boolean done = false; //System.out.println("In media_checker thread\n"); while (!done) { for (j=0; j<=15; j++) { if (puz.pieces[j].img_thread.isAlive()) { //System.out.println("waiting on "+j); /* user_waiting = true; str = "All Images not loaded, try again soon..."; myG.setFont(new Font("Times", Font.BOLD, 8)); myG.setColor(Color.black); myG.drawString(str,10,275); */ break; } } if (j > 15) { puz.images_loaded = true; if (puz.user_waiting) { str = "Image loading complete!!"; myG.setColor(Color.pink); myG.fillRect(0,251,300,300); myG.setFont(new Font("Times", Font.BOLD, 8)); myG.setColor(Color.black); myG.drawString(str,10,275); } done = true; } else { //System.out.print("slleping cause j was "); //System.out.println(j); try { sleep(1000); } catch (InterruptedException e) { } //System.out.println("awake now"); } } } } /*******************************************************************/ public class puzzle extends Applet { public piece pieces[] = new piece[16]; int i,x,y,cur_val; int start_x=50; int start_y=50; // start pos of puzzle int row_size = 4; int piece_width = 50; int piece_height = 50; private int blank_piece_pos; Graphics myG; simple_puzzle simple; random_value value_supplier = new random_value(1,16); MediaTracker tracker; selector level_indicator; Thread loadThread; // thread used to load images String image_name; media_checker checker; boolean images_loaded = false; boolean user_waiting = false; public void init() { myG = getGraphics(); checker = null; tracker = new MediaTracker(this); level_indicator = new selector(0,this,100, 5); image_name = getParameter("PREFIX"); /* INITIALIZE THE BLANK PIECES */ x = start_x; y = start_y; for (i=0; i <= 15; i++) { cur_val = value_supplier.getRandomValue(); //cur_val = i+1; /* SET THE INITIAL POSTION OF THE BLANK PIECE */ if (cur_val == 16) { blank_piece_pos = i; } //pict = getImage(getDocumentBase(),image_name+cur_val+".gif"); pieces[i] = new piece(i,cur_val,myG,x,y,null,this); x += 50; if (x > 200) { x = 50; y += 50; } } /* CREATE A NEW SIMPLE PUZZLE */ simple = new simple_puzzle(15,this); resize(pieces[0].width*6,pieces[0].height*6); checker = new media_checker(myG,this); checker.start(); } public void start() { /* if (loadThread == null) { loadThread = new Thread(this,"load"); loadThread.start(); } */ } public void stop() { //System.out.println("stop\n"); if (loadThread != null) { loadThread.stop(); loadThread = null; } } public void run() { } public boolean mouseDown(Event evt, int x, int y) { int i; int rel_x,rel_y; int click_piece; int cur; String str; // FIRST CHECK IF THE POINT IS INSIDE THE PUZZLE if (point_inside(x,y)) { // NOW GET THE CLICK PIECE rel_x = (int)(x - start_x)/piece_width; rel_y = (int)(y - start_y)/piece_height; click_piece = rel_x + row_size * rel_y; // IF THE CLICK POINT IS IN THE SAME ROW AS THE BLANK PIECE if (pieces[blank_piece_pos].same_row(y)) { if (pieces[click_piece].toLeft(pieces[blank_piece_pos])) { cur = pieces[blank_piece_pos].left; while (cur != pieces[click_piece].left) { pieces[cur].xchg(pieces[blank_piece_pos]); blank_piece_pos = cur; cur = pieces[blank_piece_pos].left; if (simple.puzzle_complete()) { myG.drawString("Congratulations!!!",75,275); } } } else if (pieces[click_piece].toRight(pieces[blank_piece_pos])) { cur = pieces[blank_piece_pos].right; while (cur != pieces[click_piece].right) { pieces[cur].xchg(pieces[blank_piece_pos]); blank_piece_pos = cur; cur = pieces[blank_piece_pos].right; if (simple.puzzle_complete()) { myG.drawString("Congratulations!!!",75,275); } } } } else if (pieces[blank_piece_pos].same_col(x)) { if (pieces[click_piece].above(pieces[blank_piece_pos])) { cur = pieces[blank_piece_pos].up; while (cur != pieces[click_piece].up) { pieces[cur].xchg(pieces[blank_piece_pos]); blank_piece_pos = cur; cur = pieces[blank_piece_pos].up; if (simple.puzzle_complete()) { myG.drawString("Congratulations!!!",75,275); } } } else if (pieces[click_piece].below(pieces[blank_piece_pos])) { cur = pieces[blank_piece_pos].down; while (cur != pieces[click_piece].down) { pieces[cur].xchg(pieces[blank_piece_pos]); blank_piece_pos = cur; cur = pieces[blank_piece_pos].down; if (simple.puzzle_complete()) { myG.drawString("Congratulations!!!",75,275); } } } } } else if (level_indicator.inside(x,y)) { if (images_loaded == true) { if (user_waiting == true) { str = "Image loading complete!!"; myG.setColor(Color.pink); myG.fillRect(0,251,300,300); myG.setFont(new Font("Times", Font.BOLD, 8)); myG.setColor(Color.black); myG.drawString(str,10,275); user_waiting = false; } level_indicator.change(); level_indicator.paint(); paint(myG); } else { user_waiting = true; str = "All Images not loaded, try again soon..."; myG.setFont(new Font("Times", Font.BOLD, 8)); myG.setColor(Color.black); myG.drawString(str,10,275); } } return true; } public void paint(Graphics g) { int i; int j; int cur; //System.out.println("In main paint\n"); g.setColor(Color.pink); g.fillRect(0,0,size().width,size().height); // System.out.println("HERE"); cur = 0; for (i=0; i <= (15); i++) { pieces[i].draw(); } level_indicator.paint(); } /* public void update(Graphics g) { for (i=0; i <= (15); i++) { pieces[i].draw(); } } */ // THIS ROUTINE RETURNS THE VALUE OF A LOCATION int getLocValue(int arr_loc) { return pieces[arr_loc].value.intValue(); } // THIS ROUTINE RETURNS THE VALUE OF THE BLANK LOCATION int getBlankLocValue() { return pieces[blank_piece_pos].value.intValue(); } public boolean point_inside (int x, int y) { if ((x >= start_x) && (y >= start_y) && (x <= start_x+row_size*piece_width) && (y <= start_y+row_size*piece_width)) { return true; } else { return false; } } }