الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

مشكلة في فهم الكود

بدأه nourkhan في 15 مايو 2011 · 19 رد · 680 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله.

من فضلكم احتاج الى مساعدتكم في فهم هدا الكود.

هدا الكود مقتبس من لعبة لتجميع قطع صورة لتركيب الصورة الأصلية.

عندما يتم الجمع بين قطعتين متجاورتين في الصورة الاصلية يتم الالتحام بين القطعتين.

احتاج لفهم كيف يتم معرفة ان القطعتين متجاورتين في الصورة الاصلية وكيف يتم هدا الالتحام .

وشكرا جزيلا لكم.

.*;

import utils.OrderedHashtable;


public class JigsawPuzzle extends JPanel implements Serializable
{


	// Class constants ------------------------------------------------------
	// ### Allow background to be changed.
	// ### Allow these to be configured.
	// Keyboard commands
	public static final char ROTATE_LEFT  = 'E';
	public static final char ROTATE_RIGHT = 'R';
	public static final char SHUFFLE      = 'S';
	public static final char PREV_BG      = 'V';
	public static final char NEXT_BG      = 'B';
	public static final char CLEAR        = 'C';

	// Available background colors
	public static final Color[] bgColors = {
		Color.BLACK,
		new Color ( 48,  0,  0),
		new Color (  0, 48,  0),
		new Color (  0,  0, 48),
		new Color ( 48, 48, 48),
		new Color ( 96,  0,  0),
		new Color (  0, 96,  0),
		new Color (  0,  0, 96),
		new Color ( 96, 96, 96),
		new Color (144,  0,  0),
		new Color (  0,144,  0),
		new Color (  0,  0,144),
		new Color (144,144,144),
	};

	public static final Color CLEAR_COLOR_W = new Color (255,255,255,48);
	public static final Color CLEAR_COLOR_B = new Color (  0,  0,  0,48);
	public static final Cursor 
		NORMAL_CURSOR = new Cursor (Cursor.DEFAULT_CURSOR),
	   	CLEAR_CURSOR  = new Cursor (Cursor.CROSSHAIR_CURSOR);

	// Constructor, fields, and supporting methods --------------------------
	/** Creates a new JigsawPuzzle.
	 * Implicitly - this is a single player game.
	 * @param image the final picture
	 * @param cutter the cut to use on the image
	 * 
	 */
	public JigsawPuzzle (Image image, JigsawCutter cutter)
	{
		super (false);
		this.image = image;
		this.cutter = cutter;
		this.zOrder = new OrderedHashtable();
		computePreferredSize();
		setOpaque (true);
		setFocusable(true);
		bgColor = 4;
		setBackground (bgColors[bgColor]);
		setCursor (NORMAL_CURSOR);
		setClearColor();
		addWiring();
	}	

	public JigsawPuzzle() {
		super (false);
		this.image = null;
		this.cutter = null;
		this.zOrder = new OrderedHashtable();
		computePreferredSize();		
		setOpaque (true);
		setFocusable(true);
		bgColor = 4;
		setBackground (bgColors[bgColor]);
		setCursor (NORMAL_CURSOR);
		setClearColor();
		addWiring();
	}


	/**
	 * Checks if puzzle is ready - in means of having the pieces.
	 * @return true = the puzzle is ready (all pieces are cut). false = the puzzle is not ready (has no cut pieces yet). 
	 */
	public boolean isPuzzleReady() {
		return (!zOrder.isEmpty());
	}

	public boolean isImageExist() {
		return (image != null);
	}

	Image image, finishedImage;
	JigsawCutter cutter;

	Dimension prefSize;
	boolean mouseDown = false;
	boolean finished  = false;
	boolean clearMode = false;

	// Last in list = topmost piece
	protected OrderedHashtable zOrder;

	int bgColor;
	int clearX0, clearY0, clearX1, clearY1;
	Color clearColor;
	int width;
	int height;
	// If a keyboard command can affect a piece, it'll be this one.
	// Typically, this piece should be last in zOrder, but you never know.
	Piece focusPiece;

	/**
	 * To null to focus piece - used after a puzzle is replace
	 *
	 */
	public void nullFocusPiece() {
		focusPiece = null;
	}

	// Jigsaw Puzzle's properties:

	/**
	 * Gets the image of the puzzle
	 */
	public Image getImage() {
		return image;
	}

	/**
	 * Gets the cutter of the puzzle.
	 * @return JigsawCutter
	 */
	public JigsawCutter getCutter() {
		return cutter;
	}

	/** @return OrderedHashtable of the puzzle's pieces */
	public OrderedHashtable getPieces() {
		return zOrder; 
	}	


	private void addWiring()
	{
		addMouseListener (new MouseAdapter() {
			public void mousePressed (MouseEvent e) {
				JigsawPuzzle.this.requestFocusInWindow(); 
				mousePressed0 (e); 
			}
			public void mouseReleased(MouseEvent e) { 
				mouseReleased0(e); 
			}
			public void mouseClicked(MouseEvent e) {
				JigsawPuzzle.this.requestFocusInWindow();
			}
		});

		addMouseMotionListener (new MouseMotionAdapter() {
			public void mouseDragged (MouseEvent e) { mouseDragged0 (e); }
		});

		addKeyListener (new KeyAdapter() {
			public void keyTyped (KeyEvent e) {	keyTyped0 (e); }
		});
	}

	// Accessors ------------------------------------------------------------
	/** Tells this puzzle to cut the image into pieces and randomize their
	 * positions.  This is a potentially time-consuming operation, and should
	 * not be done in the AWT thread.
	 */
	public void reset()
	{
		this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
		// Add progress listener:
		JigsawProgressDialog progressDialog = 
			new JigsawProgressDialog((JFrame)this.getTopLevelAncestor(), null);
		CuttingProgress listener = new CuttingProgress(progressDialog);
		cutter.addPieceCreatedListener(listener);

		Thread t = new Thread(new Runnable() {
			public void run() {
				zOrder = null;
				Piece[] pieces = cutter.cut (image);
				shuffle (pieces);
			}
		});
		t.start();

		progressDialog.setString("Création du puzzle...");
		progressDialog.show();

		// Removing the progress listener:
		cutter.removePieceCreatedListener(listener);
		this.setCursor(null);
		this.repaint();
	}

	// Event handlers for the cutting process:
	private class CuttingProgress implements PieceCreatedListener {
		private JigsawProgressDialog progressDialog;

		public CuttingProgress(JigsawProgressDialog progressDialog) {
			this.progressDialog = progressDialog; 
		}

		/**
		 * Updates the maximum value of the progress bar
		 */
		public void totalPiecesComputed(int totalPieces) {
			progressDialog.setMinimum(0);
			progressDialog.setMaximum(totalPieces);
		}

		/**
		 * Advances the progress bar. 
		 * In case we reached the end of progress - closes the dialog.
		 */
		public void pieceCreated(int currentCreated) {
			progressDialog.setValue(currentCreated);

			if (progressDialog.getValue() >= progressDialog.getMaximum()) {
				progressDialog.hide();
			}
		}
	}

	/** Move current pieces around randomly, randomize z-order, but don't
	 * randomize rotation.
	 */
	public void shuffle()
	{
		Piece[] pieces = new Piece[zOrder.size()];
		zOrder.toArray(pieces);
		shuffle (pieces);
		repaint();
	}

	// Component methods ----------------------------------------------------
	public Dimension getMaximumSize() { return getPreferredSize(); }
	public Dimension getMinimumSize() { return getPreferredSize(); }
	public Dimension getPreferredSize() { return prefSize; }

	/** Returns whether the pieces have been prepared for this puzzle. */
	public boolean isCut()
	{
		return zOrder != null;

	}


	protected void paintComponent (Graphics g)
	{
		super.paintComponent(g);
		if (zOrder == null) {
			return; 
		} 
		int x = 0, y = 0;
		Iterator iter = zOrder.iterator();
		while (iter.hasNext()) {
			Piece piece = (Piece) iter.next();
			piece.draw (g);
		}
		if (clearMode && mouseDown) {
			int cx = Math.min (clearX0, clearX1);
			int cy = Math.min (clearY0, clearY1);
			int cw = Math.abs (clearX0-clearX1);
			int ch = Math.abs (clearY0-clearY1);
			g.setColor (clearColor);
			g.fillRect (cx, cy, cw, ch);
		}
		if (finished && (finishedImage != null)) {

			Piece lastPiece = (Piece) zOrder.getFirst();
			x = lastPiece.getPuzzleX();
			y = lastPiece.getPuzzleY();
			g.drawImage (finishedImage, x, y, null);
		}
	}

	public void setClearMode (boolean flag)
	{
		clearMode = flag;
		setCursor (clearMode ? CLEAR_CURSOR : NORMAL_CURSOR);
		// Just in case this is done from outside
		if (!clearMode && mouseDown) clear();
	}

	// Private methods ------------------------------------------------------
	/** Ideally, the preferred area is roughly 1.5 times the area of the
	 * image, and the preferred width is 5/3 of the preferred height.
	 * However, if the result would be smaller than the image in either
	 * dimension, it is enlarged to allow the image to fit.
	 */
	private void computePreferredSize()
	{
		Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
		prefSize = screen;
	}

	// ### Should this be public?
	private void finish()
	{
		if (zOrder.size() != 1) return;
		finished = true;
		Piece lastPiece = (Piece) zOrder.getFirst();

		// Auto-rotate the puzzle to its correct position.
		lastPiece.setRotation (0);

		// Center the last piece in the middle of the panel.
		int prevX = lastPiece.getPuzzleX();
		int prevY = lastPiece.getPuzzleY();
		final int width  = lastPiece.getImageWidth();
		final int height = lastPiece.getImageHeight();
		int curW = getWidth();
		int curH = getHeight();
		final int centerX = (curW - width ) / 2;
		final int centerY = (curH - height) / 2;
		lastPiece.moveTo (centerX, centerY);
		repaint(0,   prevX,   prevY, width, height);
		repaint(0, centerX, centerY, width, height);

		// If we have the original image - fade into it - otherwise - finish here:
		if (image == null) {
			return;
		}

		// Draw the original image on top of the last piece in increasing
		// opaqueness.  This should make the pieces appear to fade into the
		// original image.
		final int[] data = new int [width*height];
		try {
			new PixelGrabber(image, 0,0, width, height, data, 0, width).grabPixels();
		} catch (InterruptedException ex) { 
			System.out.println ("interrupted on finish grab"); 
		}

		for (int i = 0; i < data.length; i++) {
			data = data & 0x00ffffff;
		}

		ActionListener fader = new ActionListener() {
			int trans = 0x00;
			public void actionPerformed (ActionEvent evt) {
				for (int i = 0; i < data.length; i++)
				{
					data = (data & 0x00ffffff) | (trans << 24);
				}
				if (finishedImage != null) finishedImage.flush();
				finishedImage = Toolkit.getDefaultToolkit().createImage (
					new MemoryImageSource (width, height, data, 0, width));
				repaint(0, centerX, centerY, width, height);
				if (trans < 0xff) {
					trans += 0x11; 
					if (trans >= 0xff) trans = 0xff;
					Timer timer = new Timer (200, this);
					timer.setRepeats (false);
					timer.start();
				}
			}
		};

		Timer timer = new Timer (200, fader);
		timer.setRepeats (false);
		timer.start();
	}

	// Mouse event handling -------------------------------------------------
	private void mousePressed0 (MouseEvent e)
	{
		if (finished) return;
		mouseDown = true;
		if (clearMode) startClearRect(e);
		else grabPiece(e);
	}

	private void mouseDragged0 (MouseEvent e)
	{
		if (finished) return;
		if (clearMode) dragClearRect(e);
		else dragPiece(e);
	}

	private void mouseReleased0 (MouseEvent e)
	{
		if (finished) return;
		mouseDown = false;
		if (clearMode) finishClearRect(e);
		else releasePiece (focusPiece, e);		
	}

	private void grabPiece (MouseEvent e)
	{
		int x = e.getX();
		int y = e.getY();
		focusPiece = null;
		ListIterator iter = zOrder.listIterator(zOrder.size());
		while ((focusPiece == null) && (iter.hasPrevious())) {
			Piece piece = (Piece) iter.previous();
			if (piece.contains (x, y)) {
				focusPiece = piece;
				iter.remove();
			}
		}
		if (focusPiece != null) {
			zOrder.put(new Integer(focusPiece.getId()), focusPiece);
			focusPiece.transX = x - focusPiece.getPuzzleX();
			focusPiece.transY = y - focusPiece.getPuzzleY();

			// The focusPiece might have moved up in Z-order.  At worst, we have
			// to repaint its bounding rectangle.
			repaint(0, focusPiece.getPuzzleX(), focusPiece.getPuzzleY(),
					focusPiece.getCurrentWidth(), focusPiece.getCurrentHeight());
		}
	}

	private void dragPiece (MouseEvent e)
	{
		if (focusPiece == null) return;
		int prevX = focusPiece.getPuzzleX();
		int prevY = focusPiece.getPuzzleY();
		int prevW = focusPiece.getCurrentWidth();
		int prevH = focusPiece.getCurrentHeight();
		focusPiece.moveTo (e.getX()-focusPiece.transX, e.getY()-focusPiece.transY);
		// Repaint the focusPiece' previous and current bounding rects.
		repaint(0, prevX, prevY, prevW, prevH);
		repaint(0, focusPiece.getPuzzleX(), focusPiece.getPuzzleY(),
				focusPiece.getCurrentWidth(), focusPiece.getCurrentHeight());
	}

	public void releasePiece (Piece piece, MouseEvent e)
	{
		//System.out.println("In release piece of JigsawPuzzle");
		if (piece == null) return;

		Piece[] result = piece.join();
		if (result != null) {
			Piece newPiece = result[0];
			for (int i = 1; i < result.length; i++)
			{	
				Integer key = new Integer(result.getId());
				zOrder.remove(key); 
			}
			zOrder.put(new Integer(newPiece.getId()), newPiece);
			focusPiece = newPiece;
			// Joined pieces may be of any size and number.  Mouse release isn't
			// a terribly frequent event, so just repaint the whole thing.  If
			// it's really necessary later, the thing to do would be to repaint
			// the bounding rect for every piece in the result array above.
			repaint();
			if (zOrder.size() == 1) finish();
		}	
	}

	private void startClearRect (MouseEvent e)
	{
		clearX0 = e.getX();
		clearY0 = e.getY();
	}

	private void dragClearRect (MouseEvent e)
	{
		int prevX1 = clearX1;
		int prevY1 = clearY1;
		clearX1 = e.getX();
		clearY1 = e.getY();
		int x = Math.min (clearX0, prevX1);
		int y = Math.min (clearY0, prevY1);
		int w = Math.abs (clearX0-prevX1);
		int h = Math.abs (clearY0-prevY1);
		repaint (0, x,y,w,h);
		x = Math.min (clearX0, clearX1);
		y = Math.min (clearY0, clearY1);
		w = Math.abs (clearX0-clearX1);
		h = Math.abs (clearY0-clearY1);
		repaint (0, x,y,w,h);
	}

	private void finishClearRect (MouseEvent e)
	{
		clearX1 = e.getX();
		clearY1 = e.getY();
		int cx0 = Math.max (0, Math.min (clearX0, clearX1));
		int cy0 = Math.max (0, Math.min (clearY0, clearY1));
		int cx1 = Math.min (getWidth(), Math.max (clearX0, clearX1));
		int cy1 = Math.min (getHeight(),Math.max (clearY0, clearY1));
		Iterator iter = zOrder.iterator();
		while (iter.hasNext()) 
		{
			Piece piece = (Piece) iter.next();
			if (intersects (piece, cx0,cy0,cx1,cy1))
			shuffle (piece, cx0,cy0,cx1,cy1);
		}
		repaint();
	}

	/** Return whether the piece intersects with the rectangle defined by the
	 * given points.  ### Not perfect; returns true for some pieces that it
	 * shouldn't.  Ideally, it should grab the part of the Piece in the
	 * rectangle, and search it for non-transparent pixels.  Costly, so be
	 * careful.
	 */
	private boolean intersects (Piece piece, int x0, int y0, int x1, int y1)
	{
		int px = piece.getPuzzleX();
		int py = piece.getPuzzleY();
		int pw = piece.getCurrentWidth();
		int ph = piece.getCurrentHeight();
		int w = x1 - x0;
		int h = y1 - y0;
		Rectangle r  = new Rectangle (x0,y0,w,h);
		Rectangle rp = new Rectangle (px,py,pw,ph);
		return r.intersects(rp);
	}

	static final Rectangle emptyRect = new Rectangle (0,0,0,0);

	/** Shuffle piece randomly, but keeping it out of the rectangle defined
	 * by the given points. */
	private void shuffle (Piece piece, int x0, int y0, int x1, int y1)
	{
		// Make the rectangle denoting where the Piece could be placed in the
		// whole panel.  Top point will be (0,0).
		int w = getWidth()  - piece.getCurrentWidth();
		int h = getHeight() - piece.getCurrentHeight();
		// If w or h is negative, the piece is too big to be shuffled, so quit.
		if (w<0 || h<0) return;

		// Define the endpoints of the rectangle the Piece must avoid.
		int ax = Math.max (0, x0 - piece.getCurrentWidth());
		int ay = Math.max (0, y0 - piece.getCurrentHeight());
		int ah = y1 - ay;

		// Now define four rectangles forming the shape where the NW piece
		// corner could go.  I'll use BorderLayout rectangles as a guide.
		Rectangle north = (ay==0) ? emptyRect : new Rectangle (0,0, w, ay);
		Rectangle south = (y1>=h) ? emptyRect : new Rectangle (0,y1+1, w, h-y1);
		Rectangle west  = (ax==0 || ah==0) ? emptyRect : new Rectangle (0,ay, ax,ah);
		Rectangle east  = (x1>=w || ah==0) ? emptyRect : new Rectangle (x1,ay, w-x1,ah);

		int nArea = north.width * north.height, sArea = south.width * south.height,
			wArea = west .width * west .height,
			eArea = east .width * east .height,
			totalArea = nArea + sArea + wArea + eArea;

		int rand = (int) (Math.random() * totalArea);
		rand -= nArea; if (rand<0) { shuffle (piece,north); return; }
    	rand -= sArea; if (rand<0) { shuffle (piece,south); return; }
    	rand -= wArea; if (rand<0) { shuffle (piece,west ); return; }
    	shuffle (piece,east );
	}

	private void shuffle (Piece piece, Rectangle rect)
	{
		int dx = (int) (Math.random() * rect.width);
		int dy = (int) (Math.random() * rect.height);
		piece.moveTo (rect.x+dx, rect.y+dy);
	}

	// Keyboard event handling ----------------------------------------------
	public void keyTyped0 (KeyEvent e)
	{
		if (finished) return;
		char ch = Character.toUpperCase (e.getKeyChar());
		if (ch==ROTATE_LEFT) {
			rotatePiece (focusPiece, 270);
		}
		else if (ch==ROTATE_RIGHT) {
			rotatePiece (focusPiece, 90);
		}
		else if (ch==PREV_BG)      prevBackground();
		else if (ch==NEXT_BG)      nextBackground();
		// The following features are disabled when playing multi-players game
		else if (ch==CLEAR) toggleClearMode();
		else if (ch==SHUFFLE) shuffle();
		else return;
	}



	public Piece findPiece(int pieceId) {
		Piece remoteFocusPiece=null;
		Iterator iter = zOrder.iterator();
		while(iter.hasNext()) {
			remoteFocusPiece = (Piece)iter.next();
			if (remoteFocusPiece.getId()==pieceId) {
				// Piece Found
				return remoteFocusPiece;
			}
		}
		return null;
	}

	public void rotatePiece (Piece piece, int amount)
	{
		if (piece == null) return;
		int newRotation = piece.getRotation()+amount;
		newRotation %= 360;
		int prevW = piece.getCurrentWidth();
		int prevH = piece.getCurrentHeight();
		int prevX = piece.getPuzzleX();
		int prevY = piece.getPuzzleY();
		piece.setRotation (newRotation);
    	// Make the piece appear to rotate about its center.
    	// ### Feature: When the mouse is down, rotate about the cursor instead
    	//   of the center.
    	int centerX = prevX + prevW/2;
    	int centerY = prevY + prevH/2;
    	int currW = piece.getCurrentWidth();
    	int currH = piece.getCurrentHeight();
    	int currX = centerX - currW/2;
    	int currY = centerY - currH/2;
    	piece.moveTo (currX, currY);
    	repaint(0, prevX, prevY, prevW, prevH);
    	repaint(0, currX, currY, currW, currH);
	}

	private void shuffle(Piece[] pieces)
	{
		zOrder = null;

		// Copy pieces in random order into zOrder, and randomize their
		// positions.
		OrderedHashtable zOrder0 = new OrderedHashtable();
		int lastIdx = pieces.length-1;
		while (lastIdx > 0) {			
			int pIdx = (int) (Math.random() * (lastIdx+1));
			Piece piece = pieces[pIdx];
			piece.setPuzzlePosition ((int) (Math.random() * (width  - piece.getCurrentWidth())) ,
									(int)  (Math.random() * (height - piece.getCurrentHeight())) );
			zOrder0.put(new Integer(piece.getId()), piece);
			if (pIdx != lastIdx) {
				Piece temp = pieces[lastIdx];
				pieces[lastIdx] = pieces[pIdx];
				pieces[pIdx] = temp;
			}
			lastIdx--;
		}
		zOrder0.put(new Integer(pieces[0].getId()), pieces[0]);
		finished = false;
		if (finishedImage != null) {
			finishedImage.flush();
			finishedImage = null;
		}

		zOrder = zOrder0;
	}

	private void prevBackground()
	{
		bgColor--;
		if (bgColor < 0) bgColor = bgColors.length-1;
		setBackground (bgColors[bgColor]);
		setClearColor();
		repaint();
	}

	private void nextBackground()
	{
		bgColor++;
		if (bgColor >= bgColors.length) bgColor = 0;
		setBackground (bgColors[bgColor]);
		setClearColor();
		repaint();
	}

	private void toggleClearMode()
	{
		if (mouseDown) return; // can't toggle clear mode while dragging
		setClearMode (!clearMode);
	}

	private void clear()
	{
		// ### stub
	}

	private void setClearColor()
	{ clearColor = getClearColor(); }

	private Color getClearColor()
	{ return isBright (bgColors[bgColor]) ? CLEAR_COLOR_B : CLEAR_COLOR_W; }

	private boolean isBright (Color c)
	{
		float[] hsb = new float[3];
		Color.RGBtoHSB (c.getRed(),c.getGreen(),c.getBlue(), hsb);
		return hsb[2] > 0.5;
	}

    /**
     * Retrieves a piece of the puzzle
     * @param key The piece's key - of the piece to retrieve
     * @return Returns the appropraite piece reference - or null, if no piece with the specified key was found.
     */
    public Piece getPiece(int key) {
    	Piece p = (Piece)zOrder.get(new Integer(key));
        return p;
    }

	public void setHeight(int height) {
		this.height= height;
	}

	public void setWidth(int width) {
		this.width = width;
	}

}

package puzzle;

import java.awt.*;
import java.awt.image.*;
import java.util.*;
import java.io.*;

// ### Should Pieces be implemented as BufferedImages backed by Rasters,
// rather than images backed by MemoryImageSources?

// ### Classic piece edges are problematic.  First of all, the corners are
// weird.  Secondly, the edges are probably too close together.  This is
// causing the bevels to overlap very slightly, so they don't look quite
// right.

/**
 * A single piece of a jigsaw puzzle.  Each piece knows the portion of the
 * image it contains, how its edges are to be drawn, and what its
 * neighboring pieces are.
 *
 * <p> When two or more Pieces are put together, the result is another
 * Piece object, a MultiPiece.
 *
 * @see MultiPiece
 */
public class Piece implements Serializable
{

		//	#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#		
		// That is the way I found to send the int[] piece's data:
		/*private class PieceData implements Serializable {
			public int[] origData;
			public int[] curData; 
		}*/

	/*private void writeObject(ObjectOutputStream out) throws IOException {
		out.writeInt(this.getId());
		out.writeInt(this.getImageX());
		out.writeInt(this.getImageY());
		out.writeInt(this.getTotalWidth());
		out.writeInt(this.getTotalHeight());
		out.writeInt(this.getRotatedX());
		out.writeInt(this.getRotatedY());
		out.writeInt(this.origWidth);
		out.writeInt(this.origHeight);
		out.writeInt(this.curWidth);
		out.writeInt(this.curHeight);

		// #$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#		
		// That is the way I found to send the int[] piece's data:
		PieceData pd = new PieceData();
		pd.origData = this.origData;
		pd.curData = this.curData;
		out.writeObject(pd);
		// #$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#

		out.writeInt(this.puzzleX);
		out.writeInt(this.puzzleY);
		out.writeInt(this.transX);
		out.writeInt(this.transY);
		out.writeInt(this.rotation);

		out.writeInt(this.hash);

		out.writeObject(this.neighbors);
		return;
	}*/

	/*private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
		this.id = in.readInt();
		this.imageX = in.readInt();
		this.imageY = in.readInt();
		this.totalWidth = in.readInt();
		this.totalHeight = in.readInt();
		this.rotatedX = in.readInt();
		this.rotatedY = in.readInt();
		this.origWidth = in.readInt();
		this.origHeight = in.readInt();
		this.curWidth = in.readInt();
		this.curHeight = in.readInt();


		// #$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#		
		// That is the way I found to send the int[] piece's data:		
		PieceData pd = (PieceData)in.readObject();
		this.origData = pd.origData;
		this.curData = pd.curData;
		// #$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#$%#

		this.puzzleX = in.readInt();
		this.puzzleY = in.readInt();
		this.transX = in.readInt();
		this.transY = in.readInt();
		this.rotation = in.readInt();

		this.hash = in.readInt();

		this.neighbors = (Set)in.readObject();

		this.image = Toolkit.getDefaultToolkit().createImage(
				new MemoryImageSource (curWidth,curHeight, curData, 0, curWidth));
		if(image!=null) image.flush();
	}*/

	// Class constants ------------------------------------------------------
	/** Unique id for the next piece */
	private static int nextId = 0;

	/** A Piece must be within this many pixels of "perfect" to be considered
	 * close. */
	public static final int posClose = 7;

	/** A Piece must be within this many degrees of rotation from another to
	 * be considered aligned to it. */
	public static final int rotClose = 5;

	// Constructor and fields -----------------------------------------------
	/** Creates a new Piece.  No initial rotation is done.  (This is needed
	 * by MultiPiece, which needs to set its subpieces before rotating.)
   	 * @param data        image data
   	 * @param imageX      X position of image relative to entire puzzle
   	 * @param imageY      Y position of image relative to entire puzzle
   	 * @param imageWidth   width of original image
   	 * @param imageHeight height of original image
   	 * @param totalWidth  the width of the entire picture
   	 * @param totalHeight the height of the entire picture
   	 */
	protected Piece(int[] data, int imageX, int imageY, int imageWidth, int imageHeight, int totalWidth, int totalHeight)
	{
		id = nextId++;
		neighbors = new HashSet();
		this.curWidth  = this.origWidth  = imageWidth;
		this.curHeight = this.origHeight = imageHeight;
		origData = data;    	
    	this.imageX = imageX;
    	this.imageY = imageY;
    	this.totalWidth = totalWidth;
    	this.totalHeight = totalHeight;

    	// computing hash code:
    	if (data != null) {
    		int temp = 0;
    		for(int i = 0; i < data.length; i++) {
	    		temp += data;
    		}
    		this.hash = temp;
    	} else {
    		this.hash = 0;
    	}
	}

	/** Creates a new Piece.
	 * @param data        image data
	 * @param imageX      X position of image relative to entire puzzle
	 * @param imageY      Y position of image relative to entire puzzle
	 * @param imageWidth   width of original image
	 * @param imageHeight height of original image
	 * @param totalWidth  the width of the entire picture
	 * @param totalHeight the height of the entire picture
	 * @param rotation    initial rotation
	 */
	public Piece(int[] data, int imageX, int imageY, int imageWidth, int imageHeight, int totalWidth, int totalHeight, int rotation)
	{
		this (data, imageX, imageY, imageWidth, imageHeight, totalWidth, totalHeight);
    	forceSetRotation (rotation);
	}

	/**
	 * A Copy Constructor.
	 * @param p
	 */
	public Piece(Piece p) {
		this(p.getOrigData(), p.getImageX(), p.getImageY(), 
		p.getImageWidth(), p.getImageHeight(), p.getTotalWidth(), p.getTotalHeight(), p.getRotation());
	}

	/** Piece's unique id. */
	protected int id;

	/** Location in the image. */
  	int imageX, imageY;

  	/** Size of the entire image. */
  	int totalWidth, totalHeight;

  	/** Location in the image adjusted by current rotation. */
  	int rotatedX, rotatedY;

  	/** Pieces considered to be neighbors to this one.  They are the only
  	 * ones that can be fitted to it.
  	 */
  	protected Set neighbors;

  	/** Original image size and data. */
  	protected int origWidth, origHeight;
  	int[] origData;

  	/** Current size and data, taking rotation into account. */
  	protected int curWidth, curHeight;
  	int[] curData;

  	/** Location in the puzzle panel. */
  	int puzzleX, puzzleY;

	/** Translation from a piece's upper-left corner to the point last clicked on. */
	int transX, transY;

	/** constant hash code of the piece. */
	protected int hash;

  	/** Image for this Piece.  We're going to now try making this null for
  	 * non-atomic pieces. */
  	Image image;

  	/** This is measured in integer degrees, 0-359.  0 is unrotated.  
  	 * 90 is 90 degrees clockwise, etc. */
  	int rotation;

  	// Accessors ------------------------------------------------------------

  	/** Returns this piece's unique id. */
  	public int getId() {return id;}

  	/** Returns this Piece's current rotation.  The rotation is given in
   	 * integer degrees clockwise, and will always be between 0 and 359
   	 * inclusive.
   	 */
  	public int getRotation() { return rotation; }

  	/** Sets this Piece's current rotation.  The rotation is given in integer
  	 * degrees clockwise, and should always be between 0 and 359 inclusive.
  	 * If the new rotation is different, this Piece's image data will be
  	 * recomputed.
  	 * @throws IllegalArgumentException if rotation is not in [0,359]
  	 */
  	public void setRotation (int rot)
  	{
  		if (rot == rotation) return;
  		forceSetRotation (rot);
  	}

  	/** Sets this Piece's current rotation.  Unlike setRotation(), this
  	 * method forces a recompute of the image.
  	 * @throws IllegalArgumentException if rotation is not in [0,359]
  	 */
  	protected void forceSetRotation (int rot)
  	{
  		if ((rot < 0) || (rot > 359)) throw new IllegalArgumentException("invalid rotation: "+rot);
  		// For now, allow only 0, 90, 180, 270.
  		if (rot % 90 != 0) {
  			int newRot = rot / 90;
  			System.out.println ("unsupported rotation "+rot+"; using "+newRot+" instead");
  			rot = newRot;
  		}
  		rotation = rot;
  		recomputeImageData();
  		if (image != null) image.flush();
  		image = Toolkit.getDefaultToolkit().createImage (
  		new MemoryImageSource (curWidth,curHeight, curData, 0, curWidth));
  	}

  	/** Fulshes the image, unless it is null. */
  	public void flushImage() {
  		if (image!= null) {
  			image.flush();
  		}
		image = Toolkit.getDefaultToolkit().createImage (
				new MemoryImageSource (curWidth,curHeight, curData, 0, curWidth));
  	}

  	/** Sets this Piece's upper-left position relative to the upper-left
  	 *position of the JigsawPuzzle.
  	 */
  	public void setPuzzlePosition (int x, int y)
  	{
  		this.puzzleX = x;
  		this.puzzleY = y;
  	}

  	/** Returns this Piece's current height in pixels.  This is the height of
  	 * the smallest rectangle containing all of this Piece's image data at
  	 * its current rotation.
  	 */
  	public int getCurrentHeight() { return curHeight; }

  	/** Returns this Piece's current width in pixels.  This is the width of
  	 * the smallest rectangle containing all of this Piece's image data at
  	 * its current rotation.
  	 */
  	public int getCurrentWidth() { return curWidth; }

  	/** Returns the width of the entire picture. */
  	public int getTotalWidth() { return totalWidth; }

  	/** Returns the height of the entire picture. */
  	public int getTotalHeight() { return totalHeight; }

  	/** Returns this Piece's image height in pixels.  This is the height of
  	 * the smallest rectangle containing all of this Piece's image data in
  	 * its original orientation.
  	 */
  	public int getImageHeight() { return origHeight; }

  	/** Returns this Piece's image width in pixels.  This is the width of the
  	 * smallest rectangle containing all of this Piece's image data in its
  	 * original orientation.
  	 */
  	public int getImageWidth() { return origWidth; }

  	/** Returns this Piece's X position in the original image. */
  	public int getImageX() { return imageX; }

  	/** Returns this Piece's Y position in the original image. */
  	public int getImageY() { return imageY; }

  	/** Returns this Piece's X position in the original image, modified by
  	 * its current rotation.  The origin is the center of rotation.  */
  	public int getRotatedX() { return rotatedX; }

  	/** Returns this Piece's Y position in the original image, modified by
  	 * its current rotation.  The origin is the center of rotation.  */
  	public int getRotatedY() { return rotatedY; }

  	/** Returns this Piece's X position in the original image, modified by
  	 * the given rotation.  */
  	public int getRotatedX(int rotation) { return rotatedX; }

  	/** Returns this Piece's Y position in the original image, modified by
  	 * the given rotation.  */
  	public int getRotatedY(int rotation) { return rotatedY; }

  	/** Returns this Piece's X position in the puzzle. */
  	public int getPuzzleX() { return puzzleX; }

  	/** Returns this Piece's Y position in the puzzle. */
  	public int getPuzzleY() { return puzzleY; }

  	/** Returns thie Piece's transX - last pressed X position. */
  	public int getTransX() {return transX; }
  	public void setTransX(int x) {transX = x;}

	/** Returns thie Piece's transY - last pressed Y position. */
	public int getTransY() {return transY; }
	public void setTransY(int y) {transY = y;}

  	public HashSet getNeighbors() {
  		return (HashSet)neighbors;
  	}

  	public void setNeighbors(HashSet neighbors) {
  		this.neighbors = neighbors;
  	}
  	/** Returns this Piece's current image.  This will be the Piece's portion
  	 * of the original image, rotated by this Piece's current rotation.
  	 */
  	public Image getImage () { return image; }

  	/** Returns current piece's data */
  	public int[] getCurrData() {return curData;	}
  	public void setCurrData(int[] data) { curData = data; }
	/** Returns original piece's data */
  	public int[] getOrigData() {
  		return this.origData;
  	}
  	public void setOrigData(int[] data) {
  		this.origData = data;
  	}

  	/** Returns a hash value - by the current data */
  	public int hashCode() {
  		return hash+rotation;
  	}


  	/** Adds a Piece to this Piece's set of neighbors.
  	 * @throws NullPointerException if neighbor is null
  	 */
  	public void addNeighbor (Piece neighbor)
  	{
  		if (neighbor == null) throw new NullPointerException ("null neighbor");
  		neighbors.add (neighbor);
  	}

  	/** Removes the given Piece from this Piece's set of neighbors. */
  	public void removeNeighbor (Piece neighbor) 
  	{
  		neighbors.remove (neighbor); 
  	}

  	/** Moves this Piece to the given location, relative to the puzzle
  	 * panel's upper-left corner.
  	 */
  	public void moveTo (int x, int y)
  	{ 
  		setPuzzlePosition (x, y); 
  	}

 	/** Returns a string representation of a piece, which can be written to the console. */
  	/*public String toString()
  	{
  		String msg = "";
  		msg += "Piece {" + "\n";
  		msg += "	ID = " + id + "\n";
		msg += "	(imageX, imageY) = ("+imageX+", "+imageY+")" + "\n";
		msg += "	SIZE = "+origWidth+"x"+origHeight+"\n";
		msg += "	Rotation = " + rotation+ "\n";
		msg += "	(rotatedX, rotatedY) = " + "(" + rotatedX+", "+rotatedY+")\n";
		msg += "	(puzzleX, puzzleY) = ("+puzzleX+", "+puzzleY+")\n";
		msg += "	(transX, transY) = (" + transX + ", " + transY + ")\n";
		msg += "}\n";

		return msg;
  	}*/

  	/** Draws this Piece in the given Graphics object.  The current image
  	 * will be drawn, at this Piece's current puzzle position.  */
  	protected void draw (Graphics g)
  	{
  		Image img = getImage();
  		if (img != null) g.drawImage (img, getPuzzleX(), getPuzzleY(), null);
  	}

  	/** Returns whether this Piece currently contains the given point,
  	 * relative to the puzzle panel's upper-left corner.
  	 */
  	public boolean contains (int x, int y)
  	{
  		int puzX = getPuzzleX();
  		int puzY = getPuzzleY();
  		int w = getCurrentWidth();
  		int h = getCurrentHeight();

  		return (puzX <= x) && (x <= (puzX+w-1)) && (puzY <= y) && (y <= (puzY+h-1)) &&
  			   (getAlpha(x-puzX, y-puzY) != 0);
  	}

  	/** Returns the alpha (transparency) value at the given coordinates in
  	 * the current image data.
  	 */
  	protected int getAlpha (int x, int y)
  	{
  		int pixel = curData[y*curWidth + x];
  		return (pixel >> 24) & 0xff;
  	}

  	/** Returns whether this piece is located and oriented close enough to
  	 * the given Piece to be fitted.
  	 */
  	public boolean isCloseTo (Piece piece)
  	{
  		// Check if pieces are aligned
  		int rot = getRotation();
  		int rotD = Math.abs (piece.getRotation() - getRotation());
  		rotD = Math.min (rotD, 360-rotD);
  		if (rotD > rotClose) return false;
  		// If we're here - pieces are aligned
  		int puzXD = getPuzzleX() - piece.getPuzzleX();
  		int puzYD = getPuzzleY() - piece.getPuzzleY();
  		int rotXD = getRotatedX() - piece.getRotatedX(rot);
  		int rotYD = getRotatedY() - piece.getRotatedY(rot);
  		return (Math.abs(puzXD-rotXD) <= posClose) && (Math.abs(puzYD-rotYD) <= posClose) ;

  	}

  	// Joining pieces -------------------------------------------------------

  	/** Checks whether any of this Piece's neighbors are located and oriented
  	 * close enough to be joined to this one.
  	 * @return an array of Pieces, or null if no neighbors were close enough;
  	 * if the array is non-null, the first Piece will be the new one;
  	 * subsequent Pieces will be the ones it was built from
  	 */
  	public Piece[] join ()
  	{
  		ArrayList close = new ArrayList();
  		Iterator iter = neighbors.iterator();
  		while (iter.hasNext()) {
  			Piece piece = (Piece) iter.next();
  			if (piece.isCloseTo (this)) 
  			{
  				close.add (piece);
  			}
  		}
  		if (close.size() == 0) return null;
  		// We can't just return the new MultiPiece, because the JigsawPuzzle
  		// needs to know what pieces the new one was formed from that are
  		// currently in its list.  These might include other MultiPieces, which
  		// wouldn't be in the new Piece's subpiece list.
  		Piece newPiece = MultiPiece.join (this, close);
  		Piece[] ret = new Piece[close.size()+2];
  		ret[0] = newPiece;
  		ret[1] = this;
  		this.image.flush();
  		for (int i = 0; i < close.size(); i++) {
  			Piece piece = (Piece) close.get(i);
  			ret[i+2] = piece;
  			piece.image.flush();
  		}
  		System.gc();
  		return ret;
  	}

  	// Bevel drawing --------------------------------------------------------
  	/** Draws bevels on data.  Check every opaque pixel's NW and SE
  	 * neighbors.  If NW is transparent and SE is opaque, brighten the
  	 * central pixel.  If it's the other way around, darken it.  If both or
  	 * neither are transparent, leave it alone.
  	 */
  	static void bevel (int[] data, int width, int height)
  	{
  		// Scan diagonal NW-SE lines.  The first and last lines can be skipped.
  		for (int i = 0; i < width+height-3; i++) 
  		{
  			int x = Math.max (0, i-height+2);
  			int y = Math.max (0, height-i-2);
  			boolean nw, c, se; // true iff that pixel is opaque
  			nw = c = se = false;
  			c = (((data[y*width+x] >> 24) & 0xff) > 0);
  			while ((x < width) && (y < height)) {
  				if ((x+1 < width) && (y+1 < height))
  				{
  					se = (((data[(y+1)*width+(x+1)] >> 24) & 0xff) > 0);
  				}
  				else 
  				{	
  					se = false;
  				} 

  				if (c) 
  				{
  					int datum = data[y*width+x];
  					if ( nw && !se) 
  					{
  						data[y*width+x] =   darker (datum);
  					}
  					if (!nw &&  se) 
  					{
  						data[y*width+x] = brighter (datum);
  					}
  				}
  				nw = c;
  				c = se;
  				x++; y++;
  			}
  		}
  	}

  	// This mimics Color.brighter() and Color.darker().  They multiply or
  	// divide R/G/B by 0.7, and trim them to 0 or 255 if needed.  I'm going
  	// to use 7/10 (so it's int arithmetic), and not use Math.  I don't quite
  	// trust inlining yet.  And I certainly don't want to make scads of Color
  	// objects for each pixel.  It's bad enough these are methods, and not
  	// inlined in bevel().
  	static final int fn = 10;
  	static final int fd =  7;
  	static final int maxB =  255 * fd / fn;
  	static final int brighter (int val) {
  		int r = (val >> 16) & 0xff;
  		int g = (val >>  8) & 0xff;
  		int b = (val      ) & 0xff;
  		// Black goes to #030303 gray
  		if ((r==0) && (g==0) && (b==0)) return 0xff030303;
  		r = (r < 3) ? 3 : r;
  		g = (g < 3) ? 3 : g;
  		b = (b < 3) ? 3 : b;
  		r = (r >= maxB) ? 255 : (r * fn / fd);
  		g = (g >= maxB) ? 255 : (g * fn / fd);
  		b = (b >= maxB) ? 255 : (b * fn / fd);
  		return ((((0xff00 | r) << 8) | g) << 8) | b;
  	}

  	static final int darker (int val) {
  		int r = (val >> 16) & 0xff;
  		int g = (val >>  8) & 0xff;
  		int b = (val      ) & 0xff;
  		r = r * fd / fn;
  		g = g * fd / fn;
  		b = b * fd / fn;
  		return ((((0xff00 | r) << 8) | g) << 8) | b;
  	}

  	// 4-way rotation -------------------------------------------------------
  	/** Sets this Piece's rotated position and size, based on its current
  	 * rotation.  The entire puzzle is rotated about the origin, and then
  	 * translated so that its new upper left corner is at the origin.  Each
  	 * piece's rotated position is then defined by its new upper left corner
  	 * in the rotated puzzle.
  	 */
  	protected void setRotatedPosition()
  	{
  		int rot = getRotation();
  		switch (rot) {
  			case   0:	rotatedX =  imageX; rotatedY =  imageY;
  						curWidth = origWidth; curHeight = origHeight; 
  						break;
  			case  90:   rotatedX = totalHeight-imageY-origHeight;
  						rotatedY = imageX;
  						curWidth = origHeight; curHeight = origWidth; 
  						break;
  			case 180:	rotatedX = totalWidth -imageX-origWidth;
  						rotatedY = totalHeight-imageY-origHeight;
  						curWidth = origWidth; curHeight = origHeight; 
  						break;
  			case 270:	rotatedX =  imageY;
  						rotatedY = totalWidth -imageX-origWidth;
  						curWidth = origHeight; curHeight = origWidth; 
  						break;
  			default:    System.out.println ("sRotPos() can't handle rotation: "+rot);
  		}
  	}

  	/** Recomputes this Piece's current image data and size from its original
  	 * image data and rotation.
  	 */
  	public void recomputeImageData()
  	{
  		setRotatedPosition();
  		if (rotation == 0) {
  			curData = (int[]) origData.clone();
  		} else if (rotation == 90) {
  			curData = new int[origData.length];
  			for (int i = 0; i < curWidth; i++) {
  				for (int j = 0; j < curHeight; j++) {
  					try {
  						curData[j*curWidth+i] = origData[(origHeight-i-1)*origWidth + j];
  					} catch (ArrayIndexOutOfBoundsException ex) {
  						//System.out.println ("ArrayIndexOutOfBoundsException");
  						//System.out.println (" olen="+origData.length+" clen="+curData.length);
  						//System.out.println (" i="+i+" j="+j);
  						//System.out.println (" orgW="+origWidth+" orgH="+origHeight);
  						//System.out.println (" curW="+ curWidth+" curH="+ curHeight);
  						//System.out.println (" cIdx="+ (j*curWidth+i)+" oIdx="+ ((origWidth-j-1)*origHeight + i));
  						throw new NullPointerException();
  					}
  				}
  			}
  		} else if (rotation == 180) {
  			curData = new int[origData.length];
  			for (int i = 0; i < curWidth; i++) {
  				for (int j = 0; j < curHeight; j++) {
  					curData[j*curWidth+i] = origData[(origHeight-j-1)*origWidth + (origWidth-i-1)];
  				}
  			}
  		} else if (rotation == 270) {
  			curData = new int[origData.length];
  			for (int i = 0; i < curWidth; i++) {
  				for (int j = 0; j < curHeight; j++) {
  					curData[j*curWidth+i] = origData[i*origWidth + (origWidth-j-1)];
  				}
  			}
  		} 
  		bevel(curData, curWidth, curHeight);
  		image = Toolkit.getDefaultToolkit().createImage (
  			new MemoryImageSource (curWidth,curHeight, curData, 0, curWidth));
  	}
}
#2

لقد القيت نظره على الكود وإن شاء الله سوف ارد عليك غدا مالم يقم احد الاخوه الفاضلين في المنتدى بالرد عليك

تحياتي

No intellectual battle was ever won through retreat
You do not watch Gintama? Dude, you are missing a lot!


صورةmsrgb1485.gif ocajavase7programmerclr.gif

#3
mental-driller كتب:

لقد القيت نظره على الكود وإن شاء الله سوف ارد عليك غدا مالم يقم احد الاخوه الفاضلين في المنتدى بالرد عليك

تحياتي

جزاك الله خيرا أخي، وإن استطعت ان تجيبني اليوم مساء فلا تبخل علي اخي لأنني في امس الحاجة لهذا الكود.

شكرا جزيلا.

#4

لقد بدأت بقرأة الكود لذا ارجو منك ومن الاخرين التفاعل لنصل الى نتيجة ، الكود فعلا طويل وغير مقسم الى ملفات كثير كي تسهل قرأتة

الصورة الاصلية تكون محفوظة في HashTable اسمة zorder

يتم خزن محتويات zorder في مصفوفة pieces[] ثم يتم توزيع محتويات zorder بشكل عشوائي حتى نحصل على الصورة المخلبطة

بالنسبة للتلاحم

يتم هنا في كلاس JigsawPuzzle

public void releasePiece (Piece piece, MouseEvent e)
        {
                //System.out.println("In release piece of JigsawPuzzle");
                if (piece == null) return;

                Piece[] result = piece.join();
                if (result != null) {
                        Piece newPiece = result[0];
                        for (int i = 1; i < result.length; i++)
                        {
                                Integer key = new Integer(result.getId());
                                zOrder.remove(key);
                        }
                        zOrder.put(new Integer(newPiece.getId()), newPiece);
                        focusPiece = newPiece;
                        // Joined pieces may be of any size and number.  Mouse release isn't
                        // a terribly frequent event, so just repaint the whole thing.  If
                        // it's really necessary later, the thing to do would be to repaint
                        // the bounding rect for every piece in the result array above.
                        repaint();
                        if (zOrder.size() == 1) finish();
                }
        }

بعد ان يتم ترك الماوس release

هذا السطر

Piece[] result = piece.join();

يستدعي الدالة

public Piece[] join() {
        ArrayList close = new ArrayList();
        Iterator iter = neighbors.iterator();
        while (iter.hasNext()) {
            Piece piece = (Piece) iter.next();
            if (piece.isCloseTo(this)) {
                close.add(piece);
            }
        }
        if (close.size() == 0) {
            return null;
        }
        // We can't just return the new MultiPiece, because the JigsawPuzzle
        // needs to know what pieces the new one was formed from that are
        // currently in its list.  These might include other MultiPieces, which
        // wouldn't be in the new Piece's subpiece list.
        Piece newPiece = MultiPiece.join(this, close);
        Piece[] ret = new Piece[close.size() + 2];
        ret[0] = newPiece;
        ret[1] = this;
        this.image.flush();
        for (int i = 0; i < close.size(); i++) {
            Piece piece = (Piece) close.get(i);
            ret[i + 2] = piece;
            piece.image.flush();
        }
        System.gc();
        return ret;
    }

من كلاس piece

هنا يتم فحص اذا ماكانت القطعة التي نريد تلحيمها موجودة في zorder بفحص الID

for (int i = 1; i < result.length; i++)
                        {
                                Integer key = new Integer(result.getId());
                                zOrder.remove(key);
                        }

بعد ان يتم ازالة القطع التي نريد تلحيمها نضيف الجزء الجديد للzorder

zOrder.put(new Integer(newPiece.getId()), newPiece);

ثم نعيد الرسم

 repaint();

طبعا اذا لم تتبقى سوى قطعة واحدة فان التجميع قد اكتمل

if (zOrder.size() == 1) finish();

هذا ما توصلته حتى الان وانشاء سوف اعيد قرأة الكود اكثر من مرة حتى تتضح لك الرؤية

تم تعديل هذه المشاركة بواسطة mental-driller في 15 مايو 2011 في 19:39

No intellectual battle was ever won through retreat
You do not watch Gintama? Dude, you are missing a lot!


صورةmsrgb1485.gif ocajavase7programmerclr.gif

#5

جزاك الله الف خير أخي الكريم، من فضلك هل في Hashtable يتم تخزين الصورة مجزئة؟

وهل يتم الانتهاء من اللعبة بمجرد حذف جميع مايوجد في zorder

شكرا

#6

لو نظرت هنا

import utils.OrderedHashtable;

فانا اعتقد اما ان هذه مكتبة خاصة اعطاكم هي الدكتور او هي تبع الجامعة ولا حاجة زي كده وعلشان مش مرفقة مع الكود لا استطيع ان اعرف ما بداخلها

No intellectual battle was ever won through retreat
You do not watch Gintama? Dude, you are missing a lot!


صورةmsrgb1485.gif ocajavase7programmerclr.gif

#7

تعقيب :

بالنسبة للكلاس piece يتم حفظ معلومات القطعة المأخوذة من الصورة في

/** Original image size and data. */
    protected int origWidth, origHeight;
    int[] origData;

و

/** Current size and data, taking rotation into account. */
    protected int curWidth, curHeight;
    int[] curData;

ثم استخدام صورة من داخل الكلاس للرسم

 /** Image for this Piece.  We're going to now try making this null for
     * non-atomic pieces. */
    Image image;

وهنا يتم رسم الصورة

 image = Toolkit.getDefaultToolkit().createImage(
                new MemoryImageSource(curWidth, curHeight, curData, 0, curWidth));

في الدالتين

public void recomputeImageData()

و

protected void forceSetRotation(int rot)

No intellectual battle was ever won through retreat
You do not watch Gintama? Dude, you are missing a lot!


صورةmsrgb1485.gif ocajavase7programmerclr.gif

#8

شكرا أخي

في الملف المرفق ستجد الكود الكامل للعبة.

صحح لي إن اخطات من فضلك:

عند النقر على قطعة ما على الشاشة، يتم تخزين رقم هذه القطعة فيid ثم يتم البحث عنها في Hashtabl وعند ايجادها يقارن مع جميع القطع التي تتواجد بالقرب منها علي الشاشة(لاأجد الكود المسؤول عن هذه المقارنة) وان وجدت يتم النداء علىjoin لكي تتلاحم القطع. ثم يتم حذف القطعة منHashtable.

شكرا جزيلا.

عفوا نسيت تحميل الملف.

IG.rar

تم تعديل هذه المشاركة بواسطة nourkhan في 15 مايو 2011 في 21:21

#9

سانظر وارد عليك إن شاء الله

No intellectual battle was ever won through retreat
You do not watch Gintama? Dude, you are missing a lot!


صورةmsrgb1485.gif ocajavase7programmerclr.gif

#10

هذه هي الدالة isCloseTo التي يتم استدعاءها من الدالة join في الكلاس piece

public boolean isCloseTo(Piece piece) {
        // Check if pieces are aligned
        int rot = getRotation();
        int rotD = Math.abs(piece.getRotation() - getRotation());
        rotD = Math.min(rotD, 360 - rotD);
        if (rotD > rotClose) {
            return false;
        }
        // If we're here - pieces are aligned
        int puzXD = getPuzzleX() - piece.getPuzzleX();
        int puzYD = getPuzzleY() - piece.getPuzzleY();
        int rotXD = getRotatedX() - piece.getRotatedX(rot);
        int rotYD = getRotatedY() - piece.getRotatedY(rot);
        return (Math.abs(puzXD - rotXD) <= posClose) && (Math.abs(puzYD - rotYD) <= posClose);

    }

No intellectual battle was ever won through retreat
You do not watch Gintama? Dude, you are missing a lot!


صورةmsrgb1485.gif ocajavase7programmerclr.gif

#11

مع ذلك لاأستوعب كيف تتم هذه المقارنة.

حسنا مع العلم انني لم انقر بعد إلا على قطعة واحدة وقمت بتقريب نفس القطعة من قطعة أخرى. هل يقوم الكود باستدعاء جميع الإحداثيات التي هي بالقرب من القطعة ام ماذا؟ يعني كيف تعلم القطعة المنقور عليها انها بالقرب من قطعة اخرى؟

شكرا.

#12
اقتباس

هل يقوم الكود باستدعاء جميع الإحداثيات التي هي بالقرب من القطعة ام ماذا؟ يعني كيف تعلم القطعة المنقور عليها انها بالقرب من قطعة اخرى؟

في الدالة join يتم استدعاء isCloseTo داخل اللwhile loop للiterator إذا كان هذا ماتقصده

No intellectual battle was ever won through retreat
You do not watch Gintama? Dude, you are missing a lot!


صورةmsrgb1485.gif ocajavase7programmerclr.gif

#13

هل في neighbors توجد فقط القطع التي هي بالقرب من القطعة المنقور عليها ام جميع قطع الصورة الاصلية؟

لانني لاحظت ان join يقوم بالمقارنة مع القطع المتواجدة بneighbors .

شكرا.

#14

بالتأكيد هناك جيران

في الملاحظات المرفقه مع الكود

/**
 * A single piece of a jigsaw puzzle.  Each piece knows the portion of the
 * image it contains, how its edges are to be drawn, and what its
 * neighboring pieces are.
 *
 * <p> When two or more Pieces are put together, the result is another
 * Piece object, a MultiPiece.
 *
 * @see MultiPiece
 */

كما انه مذكور في الملاحظات الخاصة بالدالة join

// Joining pieces -------------------------------------------------------
    /** Checks whether any of this Piece's neighbors are located and oriented
     * close enough to be joined to this one.
     * @return an array of Pieces, or null if no neighbors were close enough;
     * if the array is non-null, the first Piece will be the new one;
     * subsequent Pieces will be the ones it was built from
     */

ايضا الدوال الخاصة بــ neighbor

public HashSet getNeighbors() {
        return (HashSet) neighbors;
    }

    public void setNeighbors(HashSet neighbors) {
        this.neighbors = neighbors;
    }

public void addNeighbor(Piece neighbor) {
        if (neighbor == null) {
            throw new NullPointerException("null neighbor");
        }
        neighbors.add(neighbor);
    }

    /** Removes the given Piece from this Piece's set of neighbors. */
    public void removeNeighbor(Piece neighbor) {
        neighbors.remove(neighbor);
    }

والاستدعاء لهذه الدوال بيتم في الملف

MultiPiece.java

No intellectual battle was ever won through retreat
You do not watch Gintama? Dude, you are missing a lot!


صورةmsrgb1485.gif ocajavase7programmerclr.gif

#15

لاأريد أن أثقل عليك أخي الكريم، ولكن هل من الممكن ان تشرح لي بتفصيل أكثر كيفية عمل البرنامج انطلاقا من تشتيت جميع القطع على الشاشة؟ لأنني يجب ان اكتب تقريرا مفصلا لبرنامج.

كيف يمكنني تجميع البرنامج لكي يعمل في جميع الحواسيب يعني.executable

أثقلت عليك باسئلتي أخي الكريم معذرة وجزاك الله عني الف خير.

#16

اعتقد ان سؤالك كان فقط

nourkhan كتب:

احتاج لفهم كيف يتم معرفة ان القطعتين متجاورتين في الصورة الاصلية وكيف يتم هدا الالتحام .

!!!!!

تم تعديل هذه المشاركة بواسطة .S.T.A.L.K.E.R في 15 مايو 2011 في 23:32

#17

نعم ولكن لانني حتى اللحظة لم استوعب المراحل المتتبعة لذلك!!!!!!!!

شكرا

#18

اول بالنسبة للــ executable اعمل build وبيتولد لك ملف jar في الdirectory اللي اسمها dist

بس بالنسبة للبرنامج لو تشتي شرح لازم تنتظر ، لاني لسه عامله compile وشغلته وبيكتبي فرنسي.

بس بعد ما شفت الملفات كثيرة وليست قليلة وهناك باكجات كثيرة ، فارجو ان تقدر ان هذا ياخذ وقت

و الا لم يكن ديوميدس سبينلز ليكتب كتاب Code Reading: The Open Source Perspective

فارجو منك الصبر

اعتقد ان مشكلتك هي اسلوب قرأتك للكود فهذا الكود OOP لذا يجب ان تكون في الاول صورة عن علاقة الكائنات

ببعضها البعض ومن ثم عليك ان تبدأ ان تحاول فهم كيف تعمل القطع الصغيرة في البرنامج

تم تعديل هذه المشاركة بواسطة mental-driller في 16 مايو 2011 في 00:29

No intellectual battle was ever won through retreat
You do not watch Gintama? Dude, you are missing a lot!


صورةmsrgb1485.gif ocajavase7programmerclr.gif

#19

شكرا لك على اهتمامك.

للعلم اجد صعوبة في jigsawpuzzle وpiece,multipiece وكيف يتم التناسق فيما بينها.

وجزاك الله من فضله انه هو الجواد الكريم.

#20

تقطيع الصورة يبدأ هنا ولاحظ انه استخدم thread منفصل لهذه العملية

 // Accessors ------------------------------------------------------------
        /** Tells this puzzle to cut the image into pieces and randomize their
         * positions.  This is a potentially time-consuming operation, and should
         * not be done in the AWT thread.
         */
        public void reset()
        {
                this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                // Add progress listener:
                JigsawProgressDialog progressDialog =
                        new JigsawProgressDialog((JFrame)this.getTopLevelAncestor(), null);
                CuttingProgress listener = new CuttingProgress(progressDialog);
                cutter.addPieceCreatedListener(listener);

                Thread t = new Thread(new Runnable() {
                        public void run() {
                                zOrder = null;
                                Piece[] pieces = cutter.cut (image);
                                shuffle (pieces);
                        }
                });
                t.start();

                progressDialog.setString("Création du puzzle...");
                progressDialog.show();

                // Removing the progress listener:
                cutter.removePieceCreatedListener(listener);
                this.setCursor(null);
                this.repaint();
        }

طبعا الدالة shuffle هي التي تقوم بالتوزيع ولكن خلي بالك انه في نسختين من هذه الدالة

تم تعديل هذه المشاركة بواسطة mental-driller في 16 مايو 2011 في 01:28

No intellectual battle was ever won through retreat
You do not watch Gintama? Dude, you are missing a lot!


صورةmsrgb1485.gif ocajavase7programmerclr.gif

مواضيع مشابهة