aidez moi svp dans la compréhension de ce code

aidez moi svp dans la compréhension de ce code - Java - Programmation

Marsh Posté le 15-05-2011 à 16:16:46    

Bonjour,
est ce que svp je peux savoir d’après ce code comment il detecte si les pieces sont bien mises et que le puzzle est résolu.
je pense que apres le clique sur la piece il recupere son identifiant, mais je ne comprends pas comment sa voisine est detecté avant de les coller?
 
Merci beaucoup pour votre aide.
 :??:  

Code :
  1. /**
  2. *Each piece knows the portion of the image it contains, how its edges are to *be drawn, and what its
  3. * neighboring pieces are.
  4. *
  5. * <p> When two or more Pieces are put together, the result is another
  6. * Piece object, a MultiPiece.
  7. *
  8. * @see MultiPiece
  9. */
  10. public class Piece implements Serializable
  11. {
  12. // Class constants ------------------------------------------------------
  13. /** Unique id for the next piece */
  14. private static int nextId = 0;
  15. /** A Piece must be within this many pixels of "perfect" to be considered
  16.  * close. */
  17. public static final int posClose = 7;
  18. /** A Piece must be within this many degrees of rotation from another to
  19.  * be considered aligned to it. */
  20. public static final int rotClose = 5;
  21. // Constructor and fields -----------------------------------------------
  22. /** Creates a new Piece.  No initial rotation is done.  (This is needed
  23.  * by MultiPiece, which needs to set its subpieces before rotating.)
  24.      * @param data        image data
  25.      * @param imageX      X position of image relative to entire puzzle
  26.      * @param imageY      Y position of image relative to entire puzzle
  27.      * @param imageWidth   width of original image
  28.      * @param imageHeight height of original image
  29.      * @param totalWidth  the width of the entire picture
  30.      * @param totalHeight the height of the entire picture
  31.      */
  32. protected Piece(int[] data, int imageX, int imageY, int imageWidth, int imageHeight, int totalWidth, int totalHeight)
  33. {
  34.  id = nextId++;
  35.  neighbors = new HashSet();
  36.  this.curWidth  = this.origWidth  = imageWidth;
  37.  this.curHeight = this.origHeight = imageHeight;
  38.  origData = data;   
  39.      this.imageX = imageX;
  40.      this.imageY = imageY;
  41.      this.totalWidth = totalWidth;
  42.      this.totalHeight = totalHeight;
  43.    
  44.      // computing hash code:
  45.      if (data != null) {
  46.       int temp = 0;
  47.       for(int i = 0; i < data.length; i++) {
  48.       temp += data[i];
  49.       }
  50.       this.hash = temp;
  51.      } else {
  52.       this.hash = 0;
  53.      }
  54. }
  55. /** Creates a new Piece.
  56.  * @param data        image data
  57.  * @param imageX      X position of image relative to entire puzzle
  58.  * @param imageY      Y position of image relative to entire puzzle
  59.  * @param imageWidth   width of original image
  60.  * @param imageHeight height of original image
  61.  * @param totalWidth  the width of the entire picture
  62.  * @param totalHeight the height of the entire picture
  63.  * @param rotation    initial rotation
  64.  */
  65. public Piece(int[] data, int imageX, int imageY, int imageWidth, int imageHeight, int totalWidth, int totalHeight, int rotation)
  66. {
  67.  this (data, imageX, imageY, imageWidth, imageHeight, totalWidth, totalHeight);
  68.      forceSetRotation (rotation);
  69. }
  70. /**
  71.  * A Copy Constructor.
  72.  * @param p
  73.  */
  74. public Piece(Piece p) {
  75.  this(p.getOrigData(), p.getImageX(), p.getImageY(),
  76.  p.getImageWidth(), p.getImageHeight(), p.getTotalWidth(), p.getTotalHeight(), p.getRotation());
  77. }
  78. /** Piece's unique id. */
  79. protected int id;
  80. /** Location in the image. */
  81.    int imageX, imageY;
  82.    /** Size of the entire image. */
  83.    int totalWidth, totalHeight;
  84.    /** Location in the image adjusted by current rotation. */
  85.    int rotatedX, rotatedY;
  86.  
  87.    /** Pieces considered to be neighbors to this one.  They are the only
  88.     * ones that can be fitted to it.
  89.     */
  90.    protected Set neighbors;
  91.  
  92.    /** Original image size and data. */
  93.    protected int origWidth, origHeight;
  94.    int[] origData;
  95.  
  96.    /** Current size and data, taking rotation into account. */
  97.    protected int curWidth, curHeight;
  98.    int[] curData;
  99.    /** Location in the puzzle panel. */
  100.    int puzzleX, puzzleY;
  101. /** Translation from a piece's upper-left corner to the point last clicked on. */
  102. int transX, transY;
  103. /** constant hash code of the piece. */
  104. protected int hash;
  105.    /** Image for this Piece.  We're going to now try making this null for
  106.     * non-atomic pieces. */
  107.    Image image;
  108.    /** This is measured in integer degrees, 0-359.  0 is unrotated.   
  109.     * 90 is 90 degrees clockwise, etc. */
  110.    int rotation;
  111.  
  112.    // Accessors ------------------------------------------------------------
  113.  
  114.    /** Returns this piece's unique id. */
  115.    public int getId() {return id;}
  116.  
  117.    /** Returns this Piece's current rotation.  The rotation is given in
  118.      * integer degrees clockwise, and will always be between 0 and 359
  119.      * inclusive.
  120.      */
  121.    public int getRotation() { return rotation; }
  122.  
  123.    /** Sets this Piece's current rotation.  The rotation is given in integer
  124.     * degrees clockwise, and should always be between 0 and 359 inclusive.
  125.     * If the new rotation is different, this Piece's image data will be
  126.     * recomputed.
  127.     * @throws IllegalArgumentException if rotation is not in [0,359]
  128.     */
  129.    public void setRotation (int rot)
  130.    {
  131.     if (rot == rotation) return;
  132.     forceSetRotation (rot);
  133.    }
  134.  
  135.    /** Sets this Piece's current rotation.  Unlike setRotation(), this
  136.     * method forces a recompute of the image.
  137.     * @throws IllegalArgumentException if rotation is not in [0,359]
  138.     */
  139.    protected void forceSetRotation (int rot)
  140.    {
  141.     if ((rot < 0) || (rot > 359)) throw new IllegalArgumentException("invalid rotation: "+rot);
  142.     // For now, allow only 0, 90, 180, 270.
  143.     if (rot % 90 != 0) {
  144.      int newRot = rot / 90;
  145.      System.out.println ("unsupported rotation "+rot+"; using "+newRot+" instead" );
  146.      rot = newRot;
  147.     }
  148.     rotation = rot;
  149.     recomputeImageData();
  150.     if (image != null) image.flush();
  151.     image = Toolkit.getDefaultToolkit().createImage (
  152.     new MemoryImageSource (curWidth,curHeight, curData, 0, curWidth));
  153.    }
  154.  
  155.    /** Fulshes the image, unless it is null. */
  156.    public void flushImage() {
  157.     if (image!= null) {
  158.      image.flush();
  159.     }
  160.  image = Toolkit.getDefaultToolkit().createImage (
  161.    new MemoryImageSource (curWidth,curHeight, curData, 0, curWidth));
  162.    }
  163.  
  164.    /** Sets this Piece's upper-left position relative to the upper-left
  165.     *position of the JigsawPuzzle.
  166.     */
  167.    public void setPuzzlePosition (int x, int y)
  168.    {
  169.     this.puzzleX = x;
  170.     this.puzzleY = y;
  171.    }
  172.  
  173.    /** Returns this Piece's current height in pixels.  This is the height of
  174.     * the smallest rectangle containing all of this Piece's image data at
  175.     * its current rotation.
  176.     */
  177.    public int getCurrentHeight() { return curHeight; }
  178.  
  179.    /** Returns this Piece's current width in pixels.  This is the width of
  180.     * the smallest rectangle containing all of this Piece's image data at
  181.     * its current rotation.
  182.     */
  183.    public int getCurrentWidth() { return curWidth; }
  184.  
  185.    /** Returns the width of the entire picture. */
  186.    public int getTotalWidth() { return totalWidth; }
  187.  
  188.    /** Returns the height of the entire picture. */
  189.    public int getTotalHeight() { return totalHeight; }
  190.  
  191.    /** Returns this Piece's image height in pixels.  This is the height of
  192.     * the smallest rectangle containing all of this Piece's image data in
  193.     * its original orientation.
  194.     */
  195.    public int getImageHeight() { return origHeight; }
  196.  
  197.    /** Returns this Piece's image width in pixels.  This is the width of the
  198.     * smallest rectangle containing all of this Piece's image data in its
  199.     * original orientation.
  200.     */
  201.    public int getImageWidth() { return origWidth; }
  202.  
  203.    /** Returns this Piece's X position in the original image. */
  204.    public int getImageX() { return imageX; }
  205.  
  206.    /** Returns this Piece's Y position in the original image. */
  207.    public int getImageY() { return imageY; }
  208.  
  209.    /** Returns this Piece's X position in the original image, modified by
  210.     * its current rotation.  The origin is the center of rotation.  */
  211.    public int getRotatedX() { return rotatedX; }
  212.  
  213.    /** Returns this Piece's Y position in the original image, modified by
  214.     * its current rotation.  The origin is the center of rotation.  */
  215.    public int getRotatedY() { return rotatedY; }
  216.  
  217.    /** Returns this Piece's X position in the original image, modified by
  218.     * the given rotation.  */
  219.    public int getRotatedX(int rotation) { return rotatedX; }
  220.  
  221.    /** Returns this Piece's Y position in the original image, modified by
  222.     * the given rotation.  */
  223.    public int getRotatedY(int rotation) { return rotatedY; }
  224.  
  225.    /** Returns this Piece's X position in the puzzle. */
  226.    public int getPuzzleX() { return puzzleX; }
  227.  
  228.    /** Returns this Piece's Y position in the puzzle. */
  229.    public int getPuzzleY() { return puzzleY; }
  230.  
  231.    /** Returns thie Piece's transX - last pressed X position. */
  232.    public int getTransX() {return transX; }
  233.    public void setTransX(int x) {transX = x;}
  234.  
  235. /** Returns thie Piece's transY - last pressed Y position. */
  236. public int getTransY() {return transY; }
  237. public void setTransY(int y) {transY = y;}
  238.  
  239.    public HashSet getNeighbors() {
  240.     return (HashSet)neighbors;
  241.    }
  242.  
  243.    public void setNeighbors(HashSet neighbors) {
  244.     this.neighbors = neighbors;
  245.    }
  246.    /** Returns this Piece's current image.  This will be the Piece's portion
  247.     * of the original image, rotated by this Piece's current rotation.
  248.     */
  249.    public Image getImage () { return image; }
  250.  
  251.    /** Returns current piece's data */
  252.    public int[] getCurrData() {return curData; }
  253.    public void setCurrData(int[] data) { curData = data; }
  254. /** Returns original piece's data */
  255.    public int[] getOrigData() {
  256.     return this.origData;
  257.    }
  258.    public void setOrigData(int[] data) {
  259.     this.origData = data;
  260.    }
  261.  
  262.    /** Returns a hash value - by the current data */
  263.    public int hashCode() {
  264.     return hash+rotation;
  265.    }
  266.  
  267.  
  268.    /** Adds a Piece to this Piece's set of neighbors.
  269.     * @throws NullPointerException if neighbor is null
  270.     */
  271.    public void addNeighbor (Piece neighbor)
  272.    {
  273.     if (neighbor == null) throw new NullPointerException ("null neighbor" );
  274.     neighbors.add (neighbor);
  275.    }
  276.  
  277.    /** Removes the given Piece from this Piece's set of neighbors. */
  278.    public void removeNeighbor (Piece neighbor)
  279.    {
  280.     neighbors.remove (neighbor);
  281.    }
  282.  
  283.    /** Moves this Piece to the given location, relative to the puzzle
  284.     * panel's upper-left corner.
  285.     */
  286.    public void moveTo (int x, int y)
  287.    {
  288.     setPuzzlePosition (x, y);
  289.    }
  290.  
  291.    /** Draws this Piece in the given Graphics object.  The current image
  292.     * will be drawn, at this Piece's current puzzle position.  */
  293.    protected void draw (Graphics g)
  294.    {
  295.     Image img = getImage();
  296.     if (img != null) g.drawImage (img, getPuzzleX(), getPuzzleY(), null);
  297.    }
  298.  
  299.    /** Returns whether this Piece currently contains the given point,
  300.     * relative to the puzzle panel's upper-left corner.
  301.     */
  302.    public boolean contains (int x, int y)
  303.    {
  304.     int puzX = getPuzzleX();
  305.     int puzY = getPuzzleY();
  306.     int w = getCurrentWidth();
  307.     int h = getCurrentHeight();
  308.  
  309.     return (puzX <= x) && (x <= (puzX+w-1)) && (puzY <= y) && (y <= (puzY+h-1)) &&
  310.         (getAlpha(x-puzX, y-puzY) != 0);
  311.    }
  312.  
  313.    /** Returns the alpha (transparency) value at the given coordinates in
  314.     * the current image data.
  315.     */
  316.    protected int getAlpha (int x, int y)
  317.    {
  318.     int pixel = curData[y*curWidth + x];
  319.     return (pixel >> 24) & 0xff;
  320.    }
  321.  
  322.    /** Returns whether this piece is located and oriented close enough to
  323.     * the given Piece to be fitted.
  324.     */
  325.    public boolean isCloseTo (Piece piece)
  326.    {
  327.     // Check if pieces are aligned
  328.     int rot = getRotation();
  329.     int rotD = Math.abs (piece.getRotation() - getRotation());
  330.     rotD = Math.min (rotD, 360-rotD);
  331.     if (rotD > rotClose) return false;
  332.     // If we're here - pieces are aligned
  333.     int puzXD = getPuzzleX() - piece.getPuzzleX();
  334.     int puzYD = getPuzzleY() - piece.getPuzzleY();
  335.     int rotXD = getRotatedX() - piece.getRotatedX(rot);
  336.     int rotYD = getRotatedY() - piece.getRotatedY(rot);
  337.     return (Math.abs(puzXD-rotXD) <= posClose) && (Math.abs(puzYD-rotYD) <= posClose) ;
  338.  
  339.    }
  340.  
  341.    // Joining pieces -------------------------------------------------------
  342.  
  343.    /** Checks whether any of this Piece's neighbors are located and oriented
  344.     * close enough to be joined to this one.
  345.     * @return an array of Pieces, or null if no neighbors were close enough;
  346.     * if the array is non-null, the first Piece will be the new one;
  347.     * subsequent Pieces will be the ones it was built from
  348.     */
  349.    public Piece[] join ()
  350.    {
  351.     ArrayList close = new ArrayList();
  352.     Iterator iter = neighbors.iterator();
  353.     while (iter.hasNext()) {
  354.      Piece piece = (Piece) iter.next();
  355.      if (piece.isCloseTo (this))
  356.      {
  357.       close.add (piece);
  358.      }
  359.     }
  360.     if (close.size() == 0) return null;
  361.     // We can't just return the new MultiPiece, because the JigsawPuzzle
  362.     // needs to know what pieces the new one was formed from that are
  363.     // currently in its list.  These might include other MultiPieces, which
  364.     // wouldn't be in the new Piece's subpiece list.
  365.     Piece newPiece = MultiPiece.join (this, close);
  366.     Piece[] ret = new Piece[close.size()+2];
  367.     ret[0] = newPiece;
  368.     ret[1] = this;
  369.     this.image.flush();
  370.     for (int i = 0; i < close.size(); i++) {
  371.      Piece piece = (Piece) close.get(i);
  372.      ret[i+2] = piece;
  373.      piece.image.flush();
  374.     }
  375.     System.gc();
  376.     return ret;
  377.    }
  378.  
  379.  
  380.    // 4-way rotation -------------------------------------------------------
  381.    /** Sets this Piece's rotated position and size, based on its current
  382.     * rotation.  The entire puzzle is rotated about the origin, and then
  383.     * translated so that its new upper left corner is at the origin.  Each
  384.     * piece's rotated position is then defined by its new upper left corner
  385.     * in the rotated puzzle.
  386.     */
  387.    protected void setRotatedPosition()
  388.    {
  389.     int rot = getRotation();
  390.     switch (rot) {
  391.      case   0: rotatedX =  imageX; rotatedY =  imageY;
  392.         curWidth = origWidth; curHeight = origHeight;
  393.         break;
  394.      case  90:   rotatedX = totalHeight-imageY-origHeight;
  395.         rotatedY = imageX;
  396.         curWidth = origHeight; curHeight = origWidth;
  397.         break;
  398.      case 180: rotatedX = totalWidth -imageX-origWidth;
  399.         rotatedY = totalHeight-imageY-origHeight;
  400.         curWidth = origWidth; curHeight = origHeight;
  401.         break;
  402.      case 270: rotatedX =  imageY;
  403.         rotatedY = totalWidth -imageX-origWidth;
  404.         curWidth = origHeight; curHeight = origWidth;
  405.         break;
  406.      default:    System.out.println ("sRotPos() can't handle rotation: "+rot);
  407.     }
  408.    }
  409.  
  410.    /** Recomputes this Piece's current image data and size from its original
  411.     * image data and rotation.
  412.     */
  413.    public void recomputeImageData()
  414.    {
  415.     setRotatedPosition();
  416.     if (rotation == 0) {
  417.      curData = (int[]) origData.clone();
  418.     } else if (rotation == 90) {
  419.      curData = new int[origData.length];
  420.      for (int i = 0; i < curWidth; i++) {
  421.       for (int j = 0; j < curHeight; j++) {
  422.        try {
  423.         curData[j*curWidth+i] = origData[(origHeight-i-1)*origWidth + j];
  424.        } catch (ArrayIndexOutOfBoundsException ex) {
  425.         //System.out.println ("ArrayIndexOutOfBoundsException" );
  426.         //System.out.println (" olen="+origData.length+" clen="+curData.length);
  427.         //System.out.println (" i="+i+" j="+j);
  428.         //System.out.println (" orgW="+origWidth+" orgH="+origHeight);
  429.         //System.out.println (" curW="+ curWidth+" curH="+ curHeight);
  430.         //System.out.println (" cIdx="+ (j*curWidth+i)+" oIdx="+ ((origWidth-j-1)*origHeight + i));
  431.         throw new NullPointerException();
  432.        }
  433.       }
  434.      }
  435.     } else if (rotation == 180) {
  436.      curData = new int[origData.length];
  437.      for (int i = 0; i < curWidth; i++) {
  438.       for (int j = 0; j < curHeight; j++) {
  439.        curData[j*curWidth+i] = origData[(origHeight-j-1)*origWidth + (origWidth-i-1)];
  440.       }
  441.      }
  442.     } else if (rotation == 270) {
  443.      curData = new int[origData.length];
  444.      for (int i = 0; i < curWidth; i++) {
  445.       for (int j = 0; j < curHeight; j++) {
  446.        curData[j*curWidth+i] = origData[i*origWidth + (origWidth-j-1)];
  447.       }
  448.      }
  449.     }
  450.      image = Toolkit.getDefaultToolkit().createImage (
  451.      new MemoryImageSource (curWidth,curHeight, curData, 0, curWidth));
  452.    }
  453. }


 
 
 

Code :
  1. public class JigsawPuzzle extends JPanel implements Serializable
  2. {
  3. /**
  4.  * Overriding origianl writeObject.
  5.  * @param out
  6.  * @throws IOException
  7.  */
  8. /*private void writeObject(ObjectOutputStream out) throws IOException {
  9.  Iterator iter = zOrder.iterator();
  10.  while (iter.hasNext()) {
  11.   Piece p = (Piece)iter.next();
  12.   out.writeObject(p);
  13.  }
  14. }*/
  15. /**
  16.  * Overriding original readObject
  17.  * @param in
  18.  * @throws IOException
  19.  * @throws ClassNotFoundException
  20.  */
  21. /*private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
  22.  
  23.  OrderedHashtable zOrder = new OrderedHashtable();
  24.  
  25.  try {
  26.   Piece p;
  27.   while(true) {
  28.    p = (Piece)in.readObject();
  29.    zOrder.put(new Integer(p.getId()), p);
  30.   }
  31.  } catch(OptionalDataException e) {
  32.   // Build the puzzle
  33.   this.image = null;
  34.   this.cutter = null;
  35.   this.zOrder = zOrder;
  36.   setOpaque (true);
  37.   setFocusable(true);
  38.   bgColor = 4;
  39.   setBackground (bgColors[bgColor]);
  40.   setCursor (NORMAL_CURSOR);
  41.   setClearColor();
  42.   addWiring();
  43.   computePreferredSize();
  44.  }  
  45. }*/
  46. // Class constants ------------------------------------------------------
  47. // ### Allow background to be changed.
  48. // ### Allow these to be configured.
  49. // Keyboard commands
  50. public static final char ROTATE_LEFT  = 'E';
  51. public static final char ROTATE_RIGHT = 'R';
  52. public static final char SHUFFLE      = 'S';
  53. public static final char PREV_BG      = 'V';
  54. public static final char NEXT_BG      = 'B';
  55. public static final char CLEAR        = 'C';
  56. // Available background colors
  57. public static final Color[] bgColors = {
  58.  Color.BLACK,
  59.  new Color ( 48,  0,  0),
  60.  new Color (  0, 48,  0),
  61.  new Color (  0,  0, 48),
  62.  new Color ( 48, 48, 48),
  63.  new Color ( 96,  0,  0),
  64.  new Color (  0, 96,  0),
  65.  new Color (  0,  0, 96),
  66.  new Color ( 96, 96, 96),
  67.  new Color (144,  0,  0),
  68.  new Color (  0,144,  0),
  69.  new Color (  0,  0,144),
  70.  new Color (144,144,144),
  71. };
  72. public static final Color CLEAR_COLOR_W = new Color (255,255,255,48);
  73. public static final Color CLEAR_COLOR_B = new Color (  0,  0,  0,48);
  74. public static final Cursor
  75.  NORMAL_CURSOR = new Cursor (Cursor.DEFAULT_CURSOR),
  76.     CLEAR_CURSOR  = new Cursor (Cursor.CROSSHAIR_CURSOR);
  77. // Constructor, fields, and supporting methods --------------------------
  78. /** Creates a new JigsawPuzzle.
  79.  * Implicitly - this is a single player game.
  80.  * @param image the final picture
  81.  * @param cutter the cut to use on the image
  82.  *  
  83.  */
  84. public JigsawPuzzle (Image image, JigsawCutter cutter)
  85. {
  86.  super (false);
  87.  this.image = image;
  88.  this.cutter = cutter;
  89.  this.zOrder = new OrderedHashtable();
  90.  computePreferredSize();
  91.  setOpaque (true);
  92.  setFocusable(true);
  93.  bgColor = 4;
  94.  setBackground (bgColors[bgColor]);
  95.  setCursor (NORMAL_CURSOR);
  96.  setClearColor();
  97.  addWiring();
  98. }
  99. public JigsawPuzzle() {
  100.  super (false);
  101.  this.image = null;
  102.  this.cutter = null;
  103.  this.zOrder = new OrderedHashtable();
  104.  computePreferredSize();
  105.  setOpaque (true);
  106.  setFocusable(true);
  107.  bgColor = 4;
  108.  setBackground (bgColors[bgColor]);
  109.  setCursor (NORMAL_CURSOR);
  110.  setClearColor();
  111.  addWiring();
  112. }
  113. /**
  114.  * Checks if puzzle is ready - in means of having the pieces.
  115.  * @return true = the puzzle is ready (all pieces are cut). false = the puzzle is not ready (has no cut pieces yet).  
  116.  */
  117. public boolean isPuzzleReady() {
  118.  return (!zOrder.isEmpty());
  119. }
  120. public boolean isImageExist() {
  121.  return (image != null);
  122. }
  123. Image image, finishedImage;
  124. JigsawCutter cutter;
  125. Dimension prefSize;
  126. boolean mouseDown = false;
  127. boolean finished  = false;
  128. boolean clearMode = false;
  129. // Last in list = topmost piece
  130. protected OrderedHashtable zOrder;
  131. int bgColor;
  132. int clearX0, clearY0, clearX1, clearY1;
  133. Color clearColor;
  134. int width;
  135. int height;
  136. // If a keyboard command can affect a piece, it'll be this one.
  137. // Typically, this piece should be last in zOrder, but you never know.
  138. Piece focusPiece;
  139. /**
  140.  * To null to focus piece - used after a puzzle is replace
  141.  *
  142.  */
  143. public void nullFocusPiece() {
  144.  focusPiece = null;
  145. }
  146. // Jigsaw Puzzle's properties:
  147. /**
  148.  * Gets the image of the puzzle
  149.  */
  150. public Image getImage() {
  151.  return image;
  152. }
  153. /**
  154.  * Gets the cutter of the puzzle.
  155.  * @return JigsawCutter
  156.  */
  157. public JigsawCutter getCutter() {
  158.  return cutter;
  159. }
  160. /** @return OrderedHashtable of the puzzle's pieces */
  161. public OrderedHashtable getPieces() {
  162.  return zOrder;
  163. }
  164. private void addWiring()
  165. {
  166.  addMouseListener (new MouseAdapter() {
  167.   public void mousePressed (MouseEvent e) {
  168.    JigsawPuzzle.this.requestFocusInWindow();
  169.    mousePressed0 (e);
  170.   }
  171.   public void mouseReleased(MouseEvent e) {
  172.    mouseReleased0(e);
  173.   }
  174.   public void mouseClicked(MouseEvent e) {
  175.    JigsawPuzzle.this.requestFocusInWindow();
  176.   }
  177.  });
  178.  addMouseMotionListener (new MouseMotionAdapter() {
  179.   public void mouseDragged (MouseEvent e) { mouseDragged0 (e); }
  180.  });
  181.  addKeyListener (new KeyAdapter() {
  182.   public void keyTyped (KeyEvent e) { keyTyped0 (e); }
  183.  });
  184. }
  185. // Accessors ------------------------------------------------------------
  186. /** Tells this puzzle to cut the image into pieces and randomize their
  187.  * positions.  This is a potentially time-consuming operation, and should
  188.  * not be done in the AWT thread.
  189.  */
  190. public void reset()
  191. {
  192.  this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
  193.  // Add progress listener:
  194.  JigsawProgressDialog progressDialog =
  195.   new JigsawProgressDialog((JFrame)this.getTopLevelAncestor(), null);
  196.  CuttingProgress listener = new CuttingProgress(progressDialog);
  197.  cutter.addPieceCreatedListener(listener);
  198.  Thread t = new Thread(new Runnable() {
  199.   public void run() {
  200.    zOrder = null;
  201.    Piece[] pieces = cutter.cut (image);
  202.    shuffle (pieces);
  203.   }
  204.  });
  205.  t.start();
  206.  progressDialog.setString("Création du puzzle..." );
  207.  progressDialog.show();
  208.  // Removing the progress listener:
  209.  cutter.removePieceCreatedListener(listener);
  210.  this.setCursor(null);
  211.  this.repaint();
  212. }
  213. // Event handlers for the cutting process:
  214. private class CuttingProgress implements PieceCreatedListener {
  215.  private JigsawProgressDialog progressDialog;
  216.  public CuttingProgress(JigsawProgressDialog progressDialog) {
  217.   this.progressDialog = progressDialog;
  218.  }
  219.  /**
  220.   * Updates the maximum value of the progress bar
  221.   */
  222.  public void totalPiecesComputed(int totalPieces) {
  223.   progressDialog.setMinimum(0);
  224.   progressDialog.setMaximum(totalPieces);
  225.  }
  226.  /**
  227.   * Advances the progress bar.  
  228.   * In case we reached the end of progress - closes the dialog.
  229.   */
  230.  public void pieceCreated(int currentCreated) {
  231.   progressDialog.setValue(currentCreated);
  232.   if (progressDialog.getValue() >= progressDialog.getMaximum()) {
  233.    progressDialog.hide();
  234.   }
  235.  }
  236. }
  237. /** Move current pieces around randomly, randomize z-order, but don't
  238.  * randomize rotation.
  239.  */
  240. public void shuffle()
  241. {
  242.  Piece[] pieces = new Piece[zOrder.size()];
  243.  zOrder.toArray(pieces);
  244.  shuffle (pieces);
  245.  repaint();
  246. }
  247. // Component methods ----------------------------------------------------
  248. public Dimension getMaximumSize() { return getPreferredSize(); }
  249. public Dimension getMinimumSize() { return getPreferredSize(); }
  250. public Dimension getPreferredSize() { return prefSize; }
  251. /** Returns whether the pieces have been prepared for this puzzle. */
  252. public boolean isCut()
  253. {
  254.  return zOrder != null;
  255. }
  256. protected void paintComponent (Graphics g)
  257. {
  258.  super.paintComponent(g);
  259.  if (zOrder == null) {
  260.   return;
  261.  }
  262.  int x = 0, y = 0;
  263.  Iterator iter = zOrder.iterator();
  264.  while (iter.hasNext()) {
  265.   Piece piece = (Piece) iter.next();
  266.   piece.draw (g);
  267.  }
  268.  if (clearMode && mouseDown) {
  269.   int cx = Math.min (clearX0, clearX1);
  270.   int cy = Math.min (clearY0, clearY1);
  271.   int cw = Math.abs (clearX0-clearX1);
  272.   int ch = Math.abs (clearY0-clearY1);
  273.   g.setColor (clearColor);
  274.   g.fillRect (cx, cy, cw, ch);
  275.  }
  276.  if (finished && (finishedImage != null)) {
  277.   Piece lastPiece = (Piece) zOrder.getFirst();
  278.   x = lastPiece.getPuzzleX();
  279.   y = lastPiece.getPuzzleY();
  280.   g.drawImage (finishedImage, x, y, null);
  281.  }
  282. }
  283. public void setClearMode (boolean flag)
  284. {
  285.  clearMode = flag;
  286.  setCursor (clearMode ? CLEAR_CURSOR : NORMAL_CURSOR);
  287.  // Just in case this is done from outside
  288.  if (!clearMode && mouseDown) clear();
  289. }
  290. // Private methods ------------------------------------------------------
  291. /** Ideally, the preferred area is roughly 1.5 times the area of the
  292.  * image, and the preferred width is 5/3 of the preferred height.
  293.  * However, if the result would be smaller than the image in either
  294.  * dimension, it is enlarged to allow the image to fit.
  295.  */
  296. private void computePreferredSize()
  297. {
  298.  Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
  299.  prefSize = screen;
  300. }
  301. // ### Should this be public?
  302. private void finish()
  303. {
  304.  if (zOrder.size() != 1) return;
  305.  finished = true;
  306.  Piece lastPiece = (Piece) zOrder.getFirst();
  307.  // Auto-rotate the puzzle to its correct position.
  308.  lastPiece.setRotation (0);
  309.  // Center the last piece in the middle of the panel.
  310.  int prevX = lastPiece.getPuzzleX();
  311.  int prevY = lastPiece.getPuzzleY();
  312.  final int width  = lastPiece.getImageWidth();
  313.  final int height = lastPiece.getImageHeight();
  314.  int curW = getWidth();
  315.  int curH = getHeight();
  316.  final int centerX = (curW - width ) / 2;
  317.  final int centerY = (curH - height) / 2;
  318.  lastPiece.moveTo (centerX, centerY);
  319.  repaint(0,   prevX,   prevY, width, height);
  320.  repaint(0, centerX, centerY, width, height);
  321.  // If we have the original image - fade into it - otherwise - finish here:
  322.  if (image == null) {
  323.   return;
  324.  }
  325.  // Draw the original image on top of the last piece in increasing
  326.  // opaqueness.  This should make the pieces appear to fade into the
  327.  // original image.
  328.  final int[] data = new int [width*height];
  329.  try {
  330.   new PixelGrabber(image, 0,0, width, height, data, 0, width).grabPixels();
  331.  } catch (InterruptedException ex) {
  332.   System.out.println ("interrupted on finish grab" );
  333.  }
  334.  for (int i = 0; i < data.length; i++) {
  335.   data[i] = data[i] & 0x00ffffff;
  336.  }
  337.  ActionListener fader = new ActionListener() {
  338.   int trans = 0x00;
  339.   public void actionPerformed (ActionEvent evt) {
  340.    for (int i = 0; i < data.length; i++)
  341.    {
  342.     data[i] = (data[i] & 0x00ffffff) | (trans << 24);
  343.    }
  344.    if (finishedImage != null) finishedImage.flush();
  345.    finishedImage = Toolkit.getDefaultToolkit().createImage (
  346.     new MemoryImageSource (width, height, data, 0, width));
  347.    repaint(0, centerX, centerY, width, height);
  348.    if (trans < 0xff) {
  349.     trans += 0x11;
  350.     if (trans >= 0xff) trans = 0xff;
  351.     Timer timer = new Timer (200, this);
  352.     timer.setRepeats (false);
  353.     timer.start();
  354.    }
  355.   }
  356.  };
  357.  Timer timer = new Timer (200, fader);
  358.  timer.setRepeats (false);
  359.  timer.start();
  360. }
  361. // Mouse event handling -------------------------------------------------
  362. private void mousePressed0 (MouseEvent e)
  363. {
  364.  if (finished) return;
  365.  mouseDown = true;
  366.  if (clearMode) startClearRect(e);
  367.  else grabPiece(e);
  368. }
  369. private void mouseDragged0 (MouseEvent e)
  370. {
  371.  if (finished) return;
  372.  if (clearMode) dragClearRect(e);
  373.  else dragPiece(e);
  374. }
  375. private void mouseReleased0 (MouseEvent e)
  376. {
  377.  if (finished) return;
  378.  mouseDown = false;
  379.  if (clearMode) finishClearRect(e);
  380.  else releasePiece (focusPiece, e);
  381. }
  382. private void grabPiece (MouseEvent e)
  383. {
  384.  int x = e.getX();
  385.  int y = e.getY();
  386.  focusPiece = null;
  387.  ListIterator iter = zOrder.listIterator(zOrder.size());
  388.  while ((focusPiece == null) && (iter.hasPrevious())) {
  389.   Piece piece = (Piece) iter.previous();
  390.   if (piece.contains (x, y)) {
  391.    focusPiece = piece;
  392.    iter.remove();
  393.   }
  394.  }
  395.  if (focusPiece != null) {
  396.   zOrder.put(new Integer(focusPiece.getId()), focusPiece);
  397.   focusPiece.transX = x - focusPiece.getPuzzleX();
  398.   focusPiece.transY = y - focusPiece.getPuzzleY();
  399.   // The focusPiece might have moved up in Z-order.  At worst, we have
  400.   // to repaint its bounding rectangle.
  401.   repaint(0, focusPiece.getPuzzleX(), focusPiece.getPuzzleY(),
  402.     focusPiece.getCurrentWidth(), focusPiece.getCurrentHeight());
  403.  }
  404. }
  405. private void dragPiece (MouseEvent e)
  406. {
  407.  if (focusPiece == null) return;
  408.  int prevX = focusPiece.getPuzzleX();
  409.  int prevY = focusPiece.getPuzzleY();
  410.  int prevW = focusPiece.getCurrentWidth();
  411.  int prevH = focusPiece.getCurrentHeight();
  412.  focusPiece.moveTo (e.getX()-focusPiece.transX, e.getY()-focusPiece.transY);
  413.  // Repaint the focusPiece' previous and current bounding rects.
  414.  repaint(0, prevX, prevY, prevW, prevH);
  415.  repaint(0, focusPiece.getPuzzleX(), focusPiece.getPuzzleY(),
  416.    focusPiece.getCurrentWidth(), focusPiece.getCurrentHeight());
  417. }
  418. public void releasePiece (Piece piece, MouseEvent e)
  419. {
  420.  //System.out.println("In release piece of JigsawPuzzle" );
  421.  if (piece == null) return;
  422.  Piece[] result = piece.join();
  423.  if (result != null) {
  424.   Piece newPiece = result[0];
  425.   for (int i = 1; i < result.length; i++)
  426.   {
  427.    Integer key = new Integer(result[i].getId());
  428.    zOrder.remove(key);
  429.   }
  430.   zOrder.put(new Integer(newPiece.getId()), newPiece);
  431.   focusPiece = newPiece;
  432.   // Joined pieces may be of any size and number.  Mouse release isn't
  433.   // a terribly frequent event, so just repaint the whole thing.  If
  434.   // it's really necessary later, the thing to do would be to repaint
  435.   // the bounding rect for every piece in the result array above.
  436.   repaint();
  437.   if (zOrder.size() == 1) finish();
  438.  }
  439. }
  440. private void startClearRect (MouseEvent e)
  441. {
  442.  clearX0 = e.getX();
  443.  clearY0 = e.getY();
  444. }
  445. private void dragClearRect (MouseEvent e)
  446. {
  447.  int prevX1 = clearX1;
  448.  int prevY1 = clearY1;
  449.  clearX1 = e.getX();
  450.  clearY1 = e.getY();
  451.  int x = Math.min (clearX0, prevX1);
  452.  int y = Math.min (clearY0, prevY1);
  453.  int w = Math.abs (clearX0-prevX1);
  454.  int h = Math.abs (clearY0-prevY1);
  455.  repaint (0, x,y,w,h);
  456.  x = Math.min (clearX0, clearX1);
  457.  y = Math.min (clearY0, clearY1);
  458.  w = Math.abs (clearX0-clearX1);
  459.  h = Math.abs (clearY0-clearY1);
  460.  repaint (0, x,y,w,h);
  461. }
  462. private void finishClearRect (MouseEvent e)
  463. {
  464.  clearX1 = e.getX();
  465.  clearY1 = e.getY();
  466.  int cx0 = Math.max (0, Math.min (clearX0, clearX1));
  467.  int cy0 = Math.max (0, Math.min (clearY0, clearY1));
  468.  int cx1 = Math.min (getWidth(), Math.max (clearX0, clearX1));
  469.  int cy1 = Math.min (getHeight(),Math.max (clearY0, clearY1));
  470.  Iterator iter = zOrder.iterator();
  471.  while (iter.hasNext())
  472.  {
  473.   Piece piece = (Piece) iter.next();
  474.   if (intersects (piece, cx0,cy0,cx1,cy1))
  475.   shuffle (piece, cx0,cy0,cx1,cy1);
  476.  }
  477.  repaint();
  478. }
  479. /** Return whether the piece intersects with the rectangle defined by the
  480.  * given points.  ### Not perfect; returns true for some pieces that it
  481.  * shouldn't.  Ideally, it should grab the part of the Piece in the
  482.  * rectangle, and search it for non-transparent pixels.  Costly, so be
  483.  * careful.
  484.  */
  485. private boolean intersects (Piece piece, int x0, int y0, int x1, int y1)
  486. {
  487.  int px = piece.getPuzzleX();
  488.  int py = piece.getPuzzleY();
  489.  int pw = piece.getCurrentWidth();
  490.  int ph = piece.getCurrentHeight();
  491.  int w = x1 - x0;
  492.  int h = y1 - y0;
  493.  Rectangle r  = new Rectangle (x0,y0,w,h);
  494.  Rectangle rp = new Rectangle (px,py,pw,ph);
  495.  return r.intersects(rp);
  496. }
  497. static final Rectangle emptyRect = new Rectangle (0,0,0,0);
  498. /** Shuffle piece randomly, but keeping it out of the rectangle defined
  499.  * by the given points. */
  500. private void shuffle (Piece piece, int x0, int y0, int x1, int y1)
  501. {
  502.  // Make the rectangle denoting where the Piece could be placed in the
  503.  // whole panel.  Top point will be (0,0).
  504.  int w = getWidth()  - piece.getCurrentWidth();
  505.  int h = getHeight() - piece.getCurrentHeight();
  506.  // If w or h is negative, the piece is too big to be shuffled, so quit.
  507.  if (w<0 || h<0) return;
  508.  // Define the endpoints of the rectangle the Piece must avoid.
  509.  int ax = Math.max (0, x0 - piece.getCurrentWidth());
  510.  int ay = Math.max (0, y0 - piece.getCurrentHeight());
  511.  int ah = y1 - ay;
  512.  // Now define four rectangles forming the shape where the NW piece
  513.  // corner could go.  I'll use BorderLayout rectangles as a guide.
  514.  Rectangle north = (ay==0) ? emptyRect : new Rectangle (0,0, w, ay);
  515.  Rectangle south = (y1>=h) ? emptyRect : new Rectangle (0,y1+1, w, h-y1);
  516.  Rectangle west  = (ax==0 || ah==0) ? emptyRect : new Rectangle (0,ay, ax,ah);
  517.  Rectangle east  = (x1>=w || ah==0) ? emptyRect : new Rectangle (x1,ay, w-x1,ah);
  518.  int nArea = north.width * north.height, sArea = south.width * south.height,
  519.   wArea = west .width * west .height,
  520.   eArea = east .width * east .height,
  521.   totalArea = nArea + sArea + wArea + eArea;
  522.  int rand = (int) (Math.random() * totalArea);
  523.  rand -= nArea; if (rand<0) { shuffle (piece,north); return; }
  524.      rand -= sArea; if (rand<0) { shuffle (piece,south); return; }
  525.      rand -= wArea; if (rand<0) { shuffle (piece,west ); return; }
  526.      shuffle (piece,east );
  527. }
  528. private void shuffle (Piece piece, Rectangle rect)
  529. {
  530.  int dx = (int) (Math.random() * rect.width);
  531.  int dy = (int) (Math.random() * rect.height);
  532.  piece.moveTo (rect.x+dx, rect.y+dy);
  533. }
  534. // Keyboard event handling ----------------------------------------------
  535. public void keyTyped0 (KeyEvent e)
  536. {
  537.  if (finished) return;
  538.  char ch = Character.toUpperCase (e.getKeyChar());
  539.  if (ch==ROTATE_LEFT) {
  540.   rotatePiece (focusPiece, 270);
  541.  }
  542.  else if (ch==ROTATE_RIGHT) {
  543.   rotatePiece (focusPiece, 90);
  544.  }
  545.  else if (ch==PREV_BG)      prevBackground();
  546.  else if (ch==NEXT_BG)      nextBackground();
  547.  // The following features are disabled when playing multi-players game
  548.  else if (ch==CLEAR) toggleClearMode();
  549.  else if (ch==SHUFFLE) shuffle();
  550.  else return;
  551. }
  552. public Piece findPiece(int pieceId) {
  553.  Piece remoteFocusPiece=null;
  554.  Iterator iter = zOrder.iterator();
  555.  while(iter.hasNext()) {
  556.   remoteFocusPiece = (Piece)iter.next();
  557.   if (remoteFocusPiece.getId()==pieceId) {
  558.    // Piece Found
  559.    return remoteFocusPiece;
  560.   }
  561.  }
  562.  return null;
  563. }
  564. public void rotatePiece (Piece piece, int amount)
  565. {
  566.  if (piece == null) return;
  567.  int newRotation = piece.getRotation()+amount;
  568.  newRotation %= 360;
  569.  int prevW = piece.getCurrentWidth();
  570.  int prevH = piece.getCurrentHeight();
  571.  int prevX = piece.getPuzzleX();
  572.  int prevY = piece.getPuzzleY();
  573.  piece.setRotation (newRotation);
  574.      // Make the piece appear to rotate about its center.
  575.      // ### Feature: When the mouse is down, rotate about the cursor instead
  576.      //   of the center.
  577.      int centerX = prevX + prevW/2;
  578.      int centerY = prevY + prevH/2;
  579.      int currW = piece.getCurrentWidth();
  580.      int currH = piece.getCurrentHeight();
  581.      int currX = centerX - currW/2;
  582.      int currY = centerY - currH/2;
  583.      piece.moveTo (currX, currY);
  584.      repaint(0, prevX, prevY, prevW, prevH);
  585.      repaint(0, currX, currY, currW, currH);
  586. }
  587. private void shuffle(Piece[] pieces)
  588. {
  589.  zOrder = null;
  590.  // Copy pieces in random order into zOrder, and randomize their
  591.  // positions.
  592.  OrderedHashtable zOrder0 = new OrderedHashtable();
  593.  int lastIdx = pieces.length-1;
  594.  while (lastIdx > 0) {
  595.   int pIdx = (int) (Math.random() * (lastIdx+1));
  596.   Piece piece = pieces[pIdx];
  597.   piece.setPuzzlePosition ((int) (Math.random() * (width  - piece.getCurrentWidth())) ,
  598.         (int)  (Math.random() * (height - piece.getCurrentHeight())) );
  599.   zOrder0.put(new Integer(piece.getId()), piece);
  600.   if (pIdx != lastIdx) {
  601.    Piece temp = pieces[lastIdx];
  602.    pieces[lastIdx] = pieces[pIdx];
  603.    pieces[pIdx] = temp;
  604.   }
  605.   lastIdx--;
  606.  }
  607.  zOrder0.put(new Integer(pieces[0].getId()), pieces[0]);
  608.  finished = false;
  609.  if (finishedImage != null) {
  610.   finishedImage.flush();
  611.   finishedImage = null;
  612.  }
  613.  zOrder = zOrder0;
  614. }
  615. private void prevBackground()
  616. {
  617.  bgColor--;
  618.  if (bgColor < 0) bgColor = bgColors.length-1;
  619.  setBackground (bgColors[bgColor]);
  620.  setClearColor();
  621.  repaint();
  622. }
  623. private void nextBackground()
  624. {
  625.  bgColor++;
  626.  if (bgColor >= bgColors.length) bgColor = 0;
  627.  setBackground (bgColors[bgColor]);
  628.  setClearColor();
  629.  repaint();
  630. }
  631. private void toggleClearMode()
  632. {
  633.  if (mouseDown) return; // can't toggle clear mode while dragging
  634.  setClearMode (!clearMode);
  635. }
  636. private void clear()
  637. {
  638.  // ### stub
  639. }
  640. private void setClearColor()
  641. { clearColor = getClearColor(); }
  642. private Color getClearColor()
  643. { return isBright (bgColors[bgColor]) ? CLEAR_COLOR_B : CLEAR_COLOR_W; }
  644. private boolean isBright (Color c)
  645. {
  646.  float[] hsb = new float[3];
  647.  Color.RGBtoHSB (c.getRed(),c.getGreen(),c.getBlue(), hsb);
  648.  return hsb[2] > 0.5;
  649. }
  650.     /**
  651.      * Retrieves a piece of the puzzle
  652.      * @param key The piece's key - of the piece to retrieve
  653.      * @return Returns the appropraite piece reference - or null, if no piece with the specified key was found.
  654.      */
  655.     public Piece getPiece(int key) {
  656.      Piece p = (Piece)zOrder.get(new Integer(key));
  657.         return p;
  658.     }
  659. public void setHeight(int height) {
  660.  this.height= height;
  661. }
  662. public void setWidth(int width) {
  663.  this.width = width;
  664. }
  665. }

Reply

Marsh Posté le 15-05-2011 à 16:16:46   

Reply

Marsh Posté le 16-05-2011 à 10:17:40    

Le coeur de l'algorithme se trouve dans les lignes suivantes

Citation :

while (iter.hasNext()) {
     Piece piece = (Piece) iter.next();
     if (piece.isCloseTo (this))
     {
      close.add (piece);
     }


Il y a une boucle sur toutes les pièces voisines potentielles. Celle qui convient (voir le code de isCloseTo) est celle avec qui la jointure est effectuée.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed