2015-03-02 297 views
2

我正在尝试在ArrayList中放入一组Picture对象,然后随机随机混合并将它们显示为3x3的网格。但是,洗牌方法不适合我。或者也许我在draw或drawImage方法中做了任何错误,我不知道。 我总是从9个图片按原始顺序显示图片,而不是随机洗牌。Java drawImage方法

看下面我的PicturePiece类以及主类。

package lab; 

import java.awt.Graphics2D; 
import java.awt.Image; 
import java.io.File; 
import javax.imageio.ImageIO; 


public class PicturePiece { 


    private int IMAGE_X = 266; 
    private int IMAGE_Y = 224; 
    private final int row; 
    private final int col; 
    private Image img; 
    private static int count = 0; 
    private int id = 0; 

    public PicturePiece(int row, int col, File f) { 
     try { 
      this.img = ImageIO.read(f); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     this.row = this.IMAGE_X * row; 
     this.col = this.IMAGE_Y * col; 
     PicturePiece.count++; 
     this.id = PicturePiece.count; 
    } 

    public void draw(Graphics2D g2) { 
     g2.drawImage(this.img, this.row, this.col, null); 
    } 

    public void setPosition(int row, int col) { 
     this.IMAGE_X = row; 
     this.IMAGE_Y = col; 
    } 

    public int getXposition() { 
     return this.IMAGE_X; 
    } 

    public int getYposition() { 
     return this.IMAGE_Y; 
    } 

    public int getRow() { 
     return this.row; 
    } 

    public int getCol() { 
     return this.col; 
    } 

    public String getImage() { 
     return this.img.toString(); 
    } 

    public static int getPictureCount() { 
     return PicturePiece.count; 
    } 

    public int getId() { 
     return this.id; 
    } 
} 

这里是我的主类:

/* 从网上找到一个漂亮的图像,并使用图像编辑器来 分解成9块(例如,您可以使用该应用程序在Windows中绘制)。 以随机顺序在3×3网格中显示9个图像。添加一个鼠标监听器。 允许用户通过点击交换两个图像。 游戏的目标是重新创建原始图像。 当用户获胜时显示适当的消息。 */

package lab; 

import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Image; 
import java.io.File; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import java.util.*; 

public class Puzzle { 

    public static void main(String[] args) throws Exception { 
     MyFrame frame = new MyFrame(); 
     frame.setSize(1000, 1000); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    } 
} 

class MyFrame extends JFrame { 

    MyPanel p; 

    public MyFrame() { 
     p = new MyPanel(); 
     add(p); 

     setVisible(true); 

    } 

}  

class MyPanel extends JPanel { 

    private ArrayList<PicturePiece> images = new ArrayList<PicturePiece>(); 

    public MyPanel() { 
     this.setFocusable(true); 
     try { 

      int j = 0, k = 0, pocet = 0; 
      for (int i = 1; i <= 9; i++) { 

       //g2.drawImage(images.get(i), (IMAGE_X * (j)), (IMAGE_Y * (k)), null); 
       images.add(new PicturePiece(j, k, new File(("/home/ivo/Pictures/domcek/domcek" + i + ".jpg")))); 

       pocet++; 
       //System.out.println("j = " + (j - 1) + "; k = " + (k - 1) + "; i = " + i + "; pocet = " + pocet); 
       if ((pocet % 3) == 0) { 
        j = 0; 
        k++; 

       } else { 
        j = j + 1; 
       } 

      } 

     } catch (Exception e) { 
     } 

     //Random rnd = new Random(); 
     //rnd.setSeed(400); 
     //Collections.shuffle(images, rnd); 
     Collections.shuffle(images); 
     } 

    public void draw(Graphics2D g2) { 
     try { 

      for (int i = 0; i <= images.size(); i++) { 
       images.get(i).draw(g2); 
      } 

     } catch (Exception my) { 
     } 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 
     draw(g2);  
    } 
} 
+0

您设置洗牌前的图像位置,所以尽管绘图顺序是随机的,但这些位置不是。 – kiheru 2015-03-02 12:47:29

回答

1

你的错误的出现是因为你设置在MyPanel功能行/列(J和K)。

所以洗牌只会改变列表中PicturePiece的顺序,而不是您用于位置的j/k。

为了实现你想要的行为,我会从列表中的顺序生成行/列。

1

问题在于,如果您在初始坐标中绘制基于图像的图像,即使您使用它们,坐标在PicturePiece对象中也保持不变。

简短的解决方案:

变化PicturePiece:

public void draw(Graphics2D g2, int i, int j) { 
    g2.drawImage(this.img, this.IMAGE_X *i, this.IMAGE_Y * j, null); 
} 

变化之谜:

public void draw(Graphics2D g2) { 
    try { 


     for (int i = 0; i < 3; i++) { 
      for (int j = 0; j < 3; j++) { 
       System.out.println(i*3+j); 
       images.get(i*3+j).draw(g2, i ,j); 
      } 
     } 

    } catch (Exception my) { 
    } 
} 

这种方式,您将获得该数组中的顺序相同的图像,但如果他们在数组内部进行混洗时,每次执行时图像都会有所不同。

注意:这是一个硬编码版本(只适用于3x3矩阵),但我希望你有ideea。还有很多其他解决方案,但这是我能想到的最短的解决方案。

1

而不是绘图,在JPanel/JComponent,这是明智的使用JLabel为此目的,这将使您的工作更容易一些,因为你只需要担心索引位置。

这里是一个例子:

import java.awt.*; 
import java.awt.event.*; 
import java.io.IOException; 
import java.util.*; 
import javax.imageio.ImageIO; 
import javax.swing.*; 

public class TestingImages { 
    private static final String IMAGE_HEADER = "/images/windowicon/windowicon"; 
    private GUIView guiView; 

    private void performTask() { 
     try { 
      guiView = new GUIView (IMAGE_HEADER); 
     } catch (Exception exp) { 
      exp.printStackTrace(); 
     } 
     Runnable runnable = new Runnable() { 
      @Override 
      public void run() { 
       guiView.displayGUI(); 
      } 
     }; 
     EventQueue.invokeLater (runnable); 
    } 

    public static void main (String[] args) { 
     new TestingImages().performTask(); 
    } 
} 

class GUIView { 

    private static final int ROWS = 3; 
    private static final int COLUMNS = 3; 
    private static final int GAP = 5; 
    private static final int TOTAL_IMAGES = 9; 

    private JLabel originalImageLabel; 
    private JLabel[] splitImageLabel; 

    private int counter; 
    private int[] imageMap; 
    private int previousIndex; 
    private int currentIndex; 

    private MouseAdapter labelAdapter = new MouseAdapter() { 
     private int counter = 0; 
     @Override 
     public void mouseClicked (MouseEvent me) { 
      JLabel label = (JLabel) me.getSource(); 
      if (counter == 0) { 
       /* 
       * On first click, we simply keeping track of on which label 
       * the user clicked in the first place 
       */ 
       previousIndex = findLabelIndex (label); 
       System.out.println("Previous Index: " + previousIndex); 
       counter = 1; 
      } else if (counter == 1) { 
       /* 
       * On second click, firstly we will get the location of the JLabel 
       * on which the user clicked, then we will simply swap the icon as 
       * well as the Name of this JLabel with the JLabel at previousIndex 
       */ 
       currentIndex = findLabelIndex (label); 
       System.out.println("Current Index: " + currentIndex); 
       ImageIcon tempIcon = (ImageIcon) splitImageLabel[previousIndex].getIcon(); 
       splitImageLabel[previousIndex].setIcon (splitImageLabel[currentIndex].getIcon()); 
       splitImageLabel[currentIndex].setIcon (tempIcon); 
       String labelName = splitImageLabel[previousIndex].getName(); 
       splitImageLabel[previousIndex].setName (splitImageLabel[currentIndex].getName()); 
       splitImageLabel[currentIndex].setName (labelName); 
       prepareModel(); 
       counter = 0; 
      } 
      if (hasWon()) { 
       System.out.println("CONGRATULATIONS you won :-)"); 
      } 
     } 
    }; 

    public GUIView (String imageHeader) throws IOException { 
     imageMap = new int[TOTAL_IMAGES]; 
     counter = 0; 
     originalImageLabel = new JLabel(); 
     originalImageLabel.setIcon (new ImageIcon (
      ImageIO.read (GUIView.class.getResource (
           imageHeader + ".jpg")))); 
     splitImageLabel = new JLabel[TOTAL_IMAGES]; 
     for (int i = 0; i < ROWS; ++i) { 
      for (int j = 0; j < COLUMNS; ++j) { 
       splitImageLabel[counter] = new JLabel();    
       String indexValue = "" + counter; 
       /* 
       * Since JLabel[] is a 1-D Array, hence we simply giving 
       * each JLabel, at each index a name, as 0 1 2 3 and so on 
       */ 
       splitImageLabel[counter].setName (indexValue); 
       splitImageLabel[counter].setIcon (new ImageIcon (ImageIO.read (
        GUIView.class.getResource (imageHeader + i + "-" + j + ".png")))); 
       splitImageLabel[counter].addMouseListener (labelAdapter); 
       ++counter; 
      } 
     } 
    } 

    public void displayGUI() { 
     JFrame frame = new JFrame("Testing Images"); 
     frame.setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE); 

     JPanel contentPane = new JPanel(); 
     contentPane.setBorder (BorderFactory.createEmptyBorder (GAP, GAP, GAP, GAP)); 
     contentPane.setLayout (new GridLayout (2, 1, GAP, GAP)); 

     JPanel headerPanel = new JPanel(); 
     headerPanel.setBorder (BorderFactory.createEmptyBorder (GAP, GAP, GAP, GAP)); 
     headerPanel.add (originalImageLabel); 
     contentPane.add (headerPanel); 

     JPanel footerPanel = new JPanel(); 
     footerPanel.setBorder (BorderFactory.createEmptyBorder (GAP, GAP, GAP, GAP)); 
     footerPanel.setLayout (new GridLayout (ROWS, COLUMNS, GAP, GAP)); 
     /* 
     * This will Shuffle the JLable[] array 
     */ 
     Collections.shuffle (Arrays.asList (splitImageLabel)); 
     prepareModel(); 
     for (int i = 0; i < TOTAL_IMAGES; ++i) { 
      footerPanel.add (splitImageLabel[i]); 
     } 

     contentPane.add (footerPanel); 

     frame.setContentPane (contentPane); 
     frame.pack(); 
     frame.setLocationByPlatform (true); 
     frame.setVisible (true); 
    } 

    private int findLabelIndex (JLabel label) { 
     int index = 0; 
     for (int i = 0; i < TOTAL_IMAGES; ++i) { 
      if (label.getName().equals(splitImageLabel[i].getName())) { 
       index = i; 
       break; 
      } 
     } 
     return index; 
    } 

    /* 
    * hasWon() is used to simply check, if the array has values 
    * 0 1 2 3 4 till TOTAL_IMAGES, i.e. in increasing order, then it 
    * means, that the image has been rightly placed, by the user. 
    * Hence, the GAME is OVER 
    */ 
    private boolean hasWon() { 
     boolean flag = true; 
     for (int i = 0; i < TOTAL_IMAGES; ++i) { 
      if (imageMap[i] != i) { 
       flag = false; 
      } 
     } 
     return flag; 
    } 

    /* 
    * PrepareModel() is used to assign values to imageMap[] array, 
    * in the same sequence, in which the JLabel is placed inside 
    * JLabel[] array. Say JLabel[] array has JLabels with names in 
    * this order 1 5 4 3 and so on, thus imageMap[] will contain 
    * values 1 5 4 3 and so on, once they are in sorted order, then 
    * we can easily check for winning condition 
    */ 
    private void prepareModel() { 
     System.out.println("Preparing MODEL"); 
     for (int i = 0; i < TOTAL_IMAGES; ++i) { 
      imageMap[i] = getIntValue(splitImageLabel[i].getName()); 
      System.out.println("i: " + i + " Name: " + splitImageLabel[i].getName()); 
     } 
     System.out.println("Exiting MODEL"); 
    } 

    private int getIntValue (String text) { 
     int value = 0; 
     try { 
      value = Integer.parseInt (text); 
     } catch (Exception exp) { 
      exp.printStackTrace(); 
     } 

     return value; 
    } 
} 

OUTPUT:

INITIALFINALOUTPUT

CMDOUTPUT

图像中使用:

  1. 原始图像:http://i.imgur.com/GNIZRQy.jpg
  2. 要拆分,我用这个网站:http://imagesplitter.net/
1

首先请允许我感谢你的时间和精力。 我写我的应用程序/实验是这样的:

package lab; 

import java.awt.Graphics2D; 
import java.awt.Image; 
import java.io.File; 
import javax.imageio.ImageIO; 
import javax.swing.JPanel; 

public class PicturePiece extends JPanel { 

    private Image img; 
    private int id = 0; 

    public PicturePiece(int id) { 
     this.id = id; 
    } 

    public void setImage(File f) { 
     try { 
      this.img = ImageIO.read(f); 
     } catch (Exception e) { 
     } 
    } 

    public String getImage() { 
     return this.img.toString(); 
    } 

    public int getId() { 
     return this.id; 
    } 

    public void draw(Graphics2D g2, int row, int col) { 
     g2.drawImage(this.img, row, col, null); 

    } 

} 


/** 
* Find a pretty image from the Internet and use an image editor to break it 
* down into 9 pieces (for example, you can use the application Paint in 
* Windows). Display the 9 images in a 3×3 grid in a random order. Add a mouse 
* listener. Allow the user to swap two images by clicking on them. The goal of 
* the game is to re-create the original image. Display an appropriate message 
* when the user wins. 
*/ 
package lab; 

import java.awt.Color; 
import java.awt.Font; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.awt.geom.Rectangle2D; 
import java.io.File; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import java.util.*; 

public class Puzzle { 

public static void main(String[] args) throws Exception { 
    MyFrame frame = new MyFrame(); 
    frame.setSize((266 * 3) + 10, (224 * 3) + 10); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
} 

}

类MyFrame扩展的JFrame {

MyPanel p; 

public MyFrame() { 
    p = new MyPanel(); 
    add(p); 
    setVisible(true); 
} 

}

class MyPanel extends JPanel implements MouseListener { 

    public static final int IMAGE_X = 266; 
    public static final int IMAGE_Y = 224; 
    public static final int PAD = 5; 

    private int counter = 0; 
    private int previouspicture = -1; 
    private int currentpicture = -1; 

    private boolean won = false; 

    private ArrayList<PicturePiece> images = new ArrayList<PicturePiece>(); 

    public MyPanel() { 

     this.setFocusable(true); 

     for (int i = 0; i < 9; i++) { 
      images.add(new PicturePiece(i)); 
     } 
     Random rnd = new Random(); 
     rnd.setSeed(40000); 
     Collections.shuffle(images, rnd); 

     try { 
      for (int i = 0; i < images.size(); i++) { 

       images.get(i).setImage(new File(("src/chapter/domcek/domcek" + (images.get(i).getId() + 1) + ".jpg"))); 
      } 
     } catch (Exception e) { 
     } 

     addMouseListener(this); 


    } 

    public void draw(Graphics2D g2) { 

     int j = 0, k = 0, pocet = 0; 
     for (int i = 0; i < 9; i++) { 
      images.get(i).draw(g2, j * (IMAGE_X + PAD), k * (IMAGE_Y + PAD)); 
      pocet++; 
      if ((pocet % 3) == 0) { 
       j = 0; 
       k++; 
      } else { 
       j = j + 1; 
      } 
     } 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 
     validate(); 
     draw(g2); 
     if (won == true) { 
      showMessage("You won!!!", g2); 
     } 
    } 

    /** 
    * checks whether user clicked on two different pictures and if yes, changes 
    * their order 
    * 
    * @param e - event object 
    */ 
    @Override 
    public void mouseClicked(MouseEvent e) { 

     int picturepiece_id; 

     if (counter == 0) { 
      previouspicture = getPicturePiece(e.getX(), e.getY()); 
      counter = 1; 

     } else if (counter == 1) { 
      counter = 0; 
      currentpicture = getPicturePiece(e.getX(), e.getY()); 

      if ((previouspicture != currentpicture) && (previouspicture != -1) && (currentpicture != -1)) { 
       swap(previouspicture, currentpicture); 

       repaint(); 

       int j = 0; 
       int i = 0; 

       i = 0; 
       while ((j == i) && (i < images.size()) && (j < images.size())) { 
        i++; 
        j = images.get(i).getId(); 
        if ((j == 8) && (i == 8)) { 
         won = true; 
         removeMouseListener(this); 
         repaint(); 

         break; 

        } 

       } 

      } 

     } 

    } 

    /** 
    * prints message on winning 
    * 
    * @param s - message to print 
    * @param g2 - graphical context 
    */ 
    public void showMessage(String s, Graphics2D g2) { 
     Font myFont = new Font(" SansSerif ", Font.BOLD, 100); 
     g2.setFont(myFont); 
     g2.setColor(Color.BLUE); 
     Rectangle2D textBox = myFont.getStringBounds(s,  g2.getFontRenderContext()); 
     g2.drawString(s, (int) (getWidth()/2 - textBox.getWidth()/2), (int) (getHeight()/2 - textBox.getHeight())); 
    } 

    /** 
    * returns order number of picture within 3x3 grid where user clicked 
    * 
    * @param x - X coordinate 
    * @param y - Y coordinate 
    * @return 
    */ 
    private int getPicturePiece(int x, int y) { 

     if ((x <= IMAGE_X) && (y <= IMAGE_Y)) { 
      return 0; 
     } else if (((x > IMAGE_X) && (x <= IMAGE_X * 2)) && (y <= IMAGE_Y)) { 
      return 1; 
     } else if (((x > IMAGE_X) && (x <= IMAGE_X * 3)) && (y <= IMAGE_Y)) { 
      return 2; 
     } else if ((x <= IMAGE_X) && ((y > IMAGE_Y) && (y <= (IMAGE_Y * 2)))) { 
      return 3; 
     } else if (((x > IMAGE_X) && (x <= (IMAGE_X * 2))) && ((y > IMAGE_Y) && (y <= (IMAGE_Y * 2)))) { 
      return 4; 
     } else if (((x > IMAGE_X) && (x <= (IMAGE_X * 3))) && ((y > IMAGE_Y) && (y <= (IMAGE_Y * 2)))) { 
      return 5; 
     } else if ((x <= IMAGE_X) && ((y > IMAGE_Y) && (y <= (IMAGE_Y * 3)))) { 
      return 6; 

     } else if (((x > IMAGE_X) && (x <= (IMAGE_X * 2))) && ((y > IMAGE_Y) && (y <= (IMAGE_Y * 3)))) { 
      return 7; 

     } else if (((x > IMAGE_X) && (x <= (IMAGE_X * 3))) && ((y > IMAGE_Y) && (y <= (IMAGE_Y * 3)))) { 
      return 8; 

     } else { 
      return -1; 
     } 
    } 

/** 
* swaps two clicked different pictures 
* 
* @param previouspic - first picture 
* @param currentpic - second picture 
*/ 
    public void swap(int previouspic, int currentpic) { 

     int temp = 0; 
     int a = previouspic; 
     int b = currentpic; 
     PicturePiece p = images.get(a); 
     PicturePiece p2 = images.get(b); 
     images.set(a, p2); 
     images.set(b, p); 
    } 

    @Override 
    public void mousePressed(MouseEvent e) { 

    } 

    @Override 
    public void mouseReleased(MouseEvent e) { 

    } 

    @Override 
    public void mouseEntered(MouseEvent e) { 

    } 

    @Override 
    public void mouseExited(MouseEvent e) { 

    } 
}