2010-06-20 82 views
6

我有一個簡單的益智遊戲。有一張由16塊瓷磚組成的圖像(隨機放置)。圖像存儲在一個數組中,當遊戲啓動時,它們被添加到主JPanel。JPanel在益智遊戲不更新

alt text http://img248.imageshack.us/img248/7403/27632947.gif

遊戲作品中是這樣的:每個圖像都有atributes '地點', '數字'。 「地點」是網格上的當前位置(無論是否正確),「數字」是圖像的理想位置。當用戶點擊圖片時,他們的'地點'和'數字'屬性被檢查。如果他們沒有任何反應。如果不是遊戲檢查,如果任何圖像當前在內存中。如果沒有,則存儲該圖像的'地點'和'號碼'。如果內存中有一些圖像,則使用存儲的圖像的「編號」檢查當前點擊的圖像的平面。當他們匹配 - 他們的地方交換。這部分工作正常。但是現在,我使用更新的圖像在我的JPanel上調用了addComponent方法,並且根本沒有任何反應。新圖像不應該添加到JPanel替換舊圖像嗎?

package Bonus;

import javax.swing.*; 
import java.util.Random; 
import java.awt.event.*; 
import java.awt.*; 

class Puzzle extends JPanel implements ActionListener { 
    private int selected_nr=-1; 
    private int selected_pl=-1; 
    private boolean memory=false; 
    private static Img[] images; 

    public Puzzle(){ 
     JFrame f = new JFrame("Smile"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(this); 
     f.setSize(252,252); 
     f.setVisible(true); 

     setLayout(new GridLayout(4, 4)); 
     images = new Img[16]; 
     int[] buttons = new int[16]; 

     for(int i=0; i<16; i++){ 
      buttons[i] = i; 
     } 

     int rand; 
     int temp; 
     Random random; 

     random = new Random(System.currentTimeMillis()); 
     for (int i = 0; i < buttons.length; i++) { 
      rand = (random.nextInt() & 0x7FFFFFFF) % buttons.length; 
      temp = buttons[i]; 
      buttons[i] = buttons[rand]; 
      buttons[rand] = temp; 
     } 

     for (int i = 0; i < 16; i++) { 
      images[i] = new Img(i, buttons[i]); 
     } 
     addComponents(images); 
    } 

    public void addComponents(Img[] im){ 
     this.removeAll(); 
     for(int i=0; i<16; i++){ 
      im[i].addActionListener(this); 
      im[i].setPreferredSize(new Dimension(53,53)); 
      add(im[i]); 
     } 
     this.validate(); 
    } 

    public void actionPerformed(ActionEvent e) { 
     Img b = (Img)(e.getSource()); 
     int num = b.getNumber(); 
     int pl = b.getPlace(); 

     if(!(b.rightPlace())){ 
      if(memory){ 
       if(pl == selected_nr){ 
        images[pl].setPlace(selected_pl); 
        images[selected_pl].setPlace(selected_nr); 
        selected_nr = -1; 
        selected_pl = -1; 
        memory = false; 
        addComponents(images); 
       } 
       else{ 
        System.out.println("Try other image"); 
       } 
      } 
      else{ 
       memory = true; 
       selected_nr = num; 
       selected_pl = pl; 
      } 
     } 
     else{ 
      System.out.println("OK !"); 
     } 
    } 

    public static void main(String args[]) { 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       new Puzzle(); 
      } 
     }); 
    } 
} 

class Img extends JButton { 
    int number; 
    int place; 
    ImageIcon img; 

    public Img(int p, int n){ 
     number = n; 
     place = p; 
     img = new ImageIcon("u"+number+".jpg", BorderLayout.CENTER); 
     setIcon(img); 
    } 

    public boolean rightPlace(){ 
     boolean correct=false; 
     if(number == place){ 
      correct = true; 
     } 
     return correct; 
    } 
    public void setPlace(int i){ 
     place = i; 
    } 
    public int getNumber(){ 
     return number; 
    } 
    public int getPlace(){ 
     return place; 
    } 
} 

編輯:改變了代碼使用的答案,但仍然沒有運氣。 addComponents()獲取更新的圖像[],但不會重新驗證它們。

+0

考慮'隨機隨機=新的隨機()'。 – trashgod 2010-06-20 05:21:42

+0

好了,得到了錯誤。我只需要在圖像中切換圖像的位置[]。現在它可以工作。 – DevAno1 2010-06-20 09:24:07

回答

3

更改組件後,您需要通過調用invalidate()revalidate()來「刷新」Swing組件。

4

您正在將所有組件再次添加到您的JPanel中,而無需實際刪除它們中的任何一個。在您的addComponents()方法中,我會先致電removeAll()。您可能想要重命名該方法以突出副作用,因爲它不再只是添加組件。也許,resetComponents()會更好。

10

而不是依靠預切圖像文件,這裏是一個切片現有的圖像和洗牌結果片斷的例子。它結合了@Frederick和@akf的有用(+1)建議。

enter image description here

import java.awt.EventQueue; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 
import javax.imageio.ImageIO; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.Timer; 

public class ImageLabelPanel extends JPanel implements ActionListener { 

    private static final int N = 4; 
    private final List<JLabel> list = new ArrayList<JLabel>(); 
    private final Timer timer = new Timer(1000, this); 

    ImageLabelPanel() { 
     this.setLayout(new GridLayout(N, N)); 
     BufferedImage bi = null; 
     try { 
      bi = ImageIO.read(new File("image.jpg")); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     for (int r = 0; r < N; r++) { 
      for (int c = 0; c < N; c++) { 
       int w = bi.getWidth()/N; 
       int h = bi.getHeight()/N; 
       BufferedImage b = bi.getSubimage(c * w, r * h, w, h); 
       list.add(new JLabel(new ImageIcon(b))); 
      } 
     } 
     createPane(); 
     JFrame f = new JFrame(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(this); 
     f.pack(); 
     f.setVisible(true); 
     timer.start(); 
    } 

    private void createPane() { 
     this.removeAll(); 
     for (JLabel label : list) add(label); 
     this.validate(); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     Collections.shuffle(list); 
     createPane(); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new ImageLabelPanel(); 
      } 
     }); 
    } 
}