puzzle15


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<total; i++) {
				value[i] = first;
				first++;

		}
	}

	int getRandomValue() {
		boolean found = false;
		int i;
		int rand,ret;

		if (total == 0) { return -1; }

		if (total == 1) { total=0; return value[0]; }

		i = (int) (Math.random() * total);
		ret = value[i];

		total--;
		for (i=i;i<total;i++) {
			value[i]=value[i+1];
		}

		return ret;
	}
}

class selector {
int level;
puzzle puz;
int width=100;
int height=30;
Integer x_pos;
Integer y_pos;

selector (int lev, puzzle obj,int x, int y) {
	level = lev;
	puz = obj;
	x_pos = new Integer(x);
	y_pos = new Integer(y);
}

public int level (){
	return level;
}

public void change (){
	level++;
	if (level > 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;
		}

	}

}


Back to the puzzle15 applet page

How to Add Java Applets to Your Site

New on the Java Boutique:

New Review:

Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling API boasts simplicity, ease-of-integration, a well-rounded feature set, and it's free!

New Applet:

Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA sequences into three useful formats.

Elsewhere on internet.com:

WebDeveloper Java
Lots of Java information on webdeveloper.com

WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.

ScriptSearch Java
Hundreds of free Java code files to download.

jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.