我正在练习中将一组Picture对象放入ArrayList中,然后随机随机播放它们并将它们显示为3x3的网格。但是,shuffle方法对我来说无法正常工作。或许我在draw或drawImage方法中做错了什么,我不知道。 我总是以原始顺序从9件中显示图片,而不是随机洗牌。
请参阅下面的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中使用应用程序Paint)。 以随机顺序在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 :(得分:1)
出现错误是因为您在MyPanel函数中设置了行/列(j和k)。
因此,shuffle仅改变列表中PicturePiece的顺序,而不是用于该位置的j / k。
为了实现您想要的行为,我将从列表中的顺序生成行/列。
答案 1 :(得分: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矩阵),但我希望你有了想法。还有很多其他解决方案,但这是我能想到的最短的解决方案。
答案 2 :(得分: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;
}
}
输出:
使用的图片:
答案 3 :(得分: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) {
}
}