2016-12-08 10 views
1

N-Queens 문제를 해결하기 위해 찾고 있는데, 제가 가지고있는 문제를 정확히 지적했습니다. 그들의 솔루션이 맞는지 아닌지를 사용자에게 텍스트로 알려주기 위해 눌려지는 JButton이 있습니다. 이 버튼은 퀸즈가 보드에 놓여 있지 않은 경우에만 작동하는 것 같습니다. 문제는 내 JLabel "ifNotSafe"에 대한 setText() 메서드가 제대로 작동하지 않는 것 같습니다. 해당 메서드 호출에서 print 문을 넣으면 올바른 메시지가 콘솔로 보내지지만 레이블은 변경되지 않습니다. 이 라벨은 퀸즈가 아직 이사회에 올라 있지 않은 경우에만 이상하게 작동합니다. x 값과 y 값을 가진 Boxes 객체와 각각에 대한 getter 메서드가 있습니다.JLabel의 setText() 메서드가 제대로 작동하지 않습니다.

import javax.swing.*; 
import javax.swing.border.LineBorder; 
import java.awt.Color; 
import java.awt.GridLayout; 
import java.awt.Image; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.*; 


/* 
* Overall class to make the whole ChessBoard and all the helper methods to 
* tell the user whether their solution is correct or not 
*/ 
public class ChessBoardGUI extends JFrame { 
    /** 
* 
*/ 
private static final long serialVersionUID = 1L; 
//ImageIcon queenP = new //ImageIcon(getClass().getResource("/images/queen.png")); 
//Image img = queenP.getImage(); 
//Image newImg = img.getScaledInstance(40, 40, java.awt.Image.SCALE_SMOOTH); 
ImageIcon queenPic = new ImageIcon(newImg); 
private static JButton tip; 
private static JButton safe; 
private static JLabel ifNotSafe; 
private JButton[][] chessBoxes = new JButton[8][8]; 
public static JPanel chessBoard; 
public static ArrayList<Boxes> queensOnBoard = new ArrayList<Boxes>(); 

/* 
* Makes the whole frame for the ChessBoard 
*/ 
public ChessBoardGUI() { 
    createBoard(); 
    createOtherThings(); 
    setSize(500, 500); 

} 

/* 
* Creates the Tip and Safe buttons And Label to display when the solution 
* is incorrect 
*/ 
public void createOtherThings() { 
    safe = new JButton("Safe?"); 
    tip = new JButton("Tip"); 
    ifNotSafe = new JLabel("Status of Board is displayed here..."); 

    ButtonListen1 safeListener = new ButtonListen1(); 
    ButtonListen2 tipListener = new ButtonListen2(); 

    safe.addActionListener(safeListener); 
    tip.addActionListener(tipListener); 

} 

/* 
* ActionListener for the safe button 
*/ 
class ButtonListen1 implements ActionListener { 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     // Tells user which queens are not safe 
     if (checkSolution(queensOnBoard) == true) { 
      //****THIS IS WHERE THE PROBLEM IS ******* 
      ifNotSafe.setText("This Solution is correct so far"); 
      System.out.println("Solution is correct"); 

     } else{ 
      ifNotSafe.setText("This Solution is incorrect so far"); 
      // *********Also highlight the queens that are not safe****** 
      System.out.println("Solution is incorrect"); 
     } 
    } 

} 


/* 
* ActionListener for the tip button 
*/ 
class ButtonListen2 implements ActionListener { 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     // ********Tells the user other places to put queens******** 
    } 
} 

/* 
* Creates the overall ChessBoard 
*/ 
public void createBoard() { 
    GridLayout gridLayout = new GridLayout(); 
    gridLayout.setRows(8); 
    gridLayout.setColumns(8); 
    chessBoard = new JPanel(gridLayout); 
    chessBoard.setSize(400, 400); 
    chessBoard.setBorder(new LineBorder(Color.BLACK)); 
    chessBoard.setVisible(true); 

    /* 
    * Loops through to add each chessBox to the chessBoard 
    */ 
    for (int x = 0; x < 8; x++) { 
     for (int y = 0; y < 8; y++) { 
      chessBoxes[x][y] = new JButton(); 
      chessBoxes[x][y].setBorderPainted(false); 
      /* 
      * Assigns a color to every other box 
      */ 
      if ((x + y) % 2 == 0) { 
       chessBoxes[x][y].setBackground(Color.BLACK); 
      } else { 
       chessBoxes[x][y].setBackground(Color.WHITE); 
      } 
      chessBoxes[x][y].setOpaque(true); 
      chessBoard.add(chessBoxes[x][y]); 

      // Adds the ActionListener to each chessBox 
      BoxListener boxListen = new BoxListener(); 
      chessBoxes[x][y].addActionListener(boxListen); 
     } 
    } 
} 

/* 
* Action Listener for if the individual boxes on the ChessBoard are clicked 
*/ 
class BoxListener implements ActionListener { 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     JButton button = ((JButton) e.getSource()); 

     // Runs through a loop to find the X and Y coordinate of the 
     // JButton(Box) that was clicked 
     for (int x = 0; x < 8; x++) { 
      for (int y = 0; y < 8; y++) { 
       if (chessBoxes[x][y] == button) { 
        /* 
        * If there is No Queen at that JButton 
        */ 
        if ((isOnBoard(queensOnBoard, x, y) == false)) { 
         // Makes sure the user can not place more than 
         // 8 Queens on the board 
         if (queensOnBoard.size() < 8) { 
          // Sets Picture of Queen on box 
          //button.setIcon(queenPic); 
        button.setText("Occupied"); 
          // Adds box to the ArrayList of occupied boxes 
          queensOnBoard.add(new Boxes(x, y)); 
         } 
        } 
        /* 
        * If there is a Queen at that JButton 
        */ 
        else { 
         removeQueen(queensOnBoard, x, y); 
         //button.setIcon(null); 
      button.setText(""); 
        } 
       } 
      } 
     } 
    } 
} 

/* 
* Checks if a certain Box has a Queen in it or not 
* 
* @param a Is the ArrayList of the Boxes currently occupied by Queens 
* 
* @param x Is the X coordinate of the Box that was clicked 
* 
* @param y Is the Y coordinate of the Box that was clicked 
*/ 
public boolean isOnBoard(ArrayList<Boxes> a, int x, int y) { 
    for (int i = 0; i < a.size(); i++) { 
     if (((a.get(i)).getX() == x) && ((a.get(i)).getY() == y)) { 
      return true; 
     } 
    } 
    return false; 
} 

/* 
* Removes a Queen from the GUI at the specified Box (JButton) 
* 
* @param a Is the ArrayList of the Boxes currently occupied by Queens 
* 
* @param x Is the X coordinate of the Box that was clicked 
* 
* @param y Is the Y coordinate of the Box that was clicked 
*/ 
public void removeQueen(ArrayList<Boxes> a, int x, int y) { 
    /* 
    * Removes the box from the overall ArrayList of Boxes Occupied by 
    * queens according to the x and y location 
    */ 
    for (int i = 0; i < a.size(); i++) { 
     if (((a.get(i)).getX() == x) && ((a.get(i)).getY() == y)) { 
      queensOnBoard.remove(i); 
     } 
    } 
} 

/* 
* Return to the user which queens need to be highlighted 
* 
* @param queensOnBoard Is the ArrayList of Boxes that are occupied by 
* Queens currently on the ChessBoard 
*/ 
public void conflictingQueens(ArrayList<Boxes> queensOnBoard) { 
    // *******Call the highlightBoxes method using the ArrayList 
    // Of Boxes you get from this method 

} 

/* 
* Checks to see if solution is correct thusfar 
* 
* @param queensOnBoard Is the ArrayList of Boxes that are occupied by 
* Queens currently on the ChessBoard 
*/ 
public boolean checkSolution(ArrayList<Boxes> queensOnBoard) { 
    int size = queensOnBoard.size(); 
    if (size < 1) { 
     return true; 
    } 
    if (size == 1) { 
     return true; 
    } 
    for (int x = 0; x < size - 1; x++) { 
     for (int y = 1; y < size; y++) { 
      // Checks if Queen is safe from horizontal attacks 
      if (queensOnBoard.get(x).getX() == queensOnBoard.get(y).getX()) { 
       return false; 
       // Checks if Queen is safe from vertical attacks 
      } else if (queensOnBoard.get(x).getY() == queensOnBoard.get(y).getY()) { 
       return false; 
       // Checks if Queen is safe from diagonal attacks 
       // Uses diagonalAttack(queensOnBoard) as a helper method 
      } // else if(){ 
       // return false; 
       // } 
     } 
    } 

    return true; 
} 

/* 
* Checks to see if the queen is safe from diagonal attacks 
* 
* 
*/ 
// public boolean diagonalAttack(ArrayList<Boxes> queensOnBoard){ 
//******** 
// } 

/* 
* Highlights boxes that are conflicting with one another 
* 
* @param highlight Is the ArrayList of Boxes that are occupied by Queens 
* currently on the ChessBoard 
*/ 
public void highlightBoxes(ArrayList<Boxes> highlight) { 
    int size1 = highlight.size(); 
    int size2 = queensOnBoard.size(); 

    // When there aren't any queens at risk, this block 
    // changes the background colors of the boxes back to 
    // Their respective color 
    if ((size1 == 0) && size1 == 1) { 
     for (int x = 0; x < 8; x++) { 
      for (int y = 0; y < 8; y++) { 
       chessBoxes[x][y] = new JButton(); 
       chessBoxes[x][y].setBorderPainted(false); 
       /* 
       * Assigns a color to every other box 
       */ 
       if ((x + y) % 2 == 0) { 
        chessBoxes[x][y].setBackground(Color.BLACK); 
       } else { 
        chessBoxes[x][y].setBackground(Color.WHITE); 
       } 
      } 
     } 
    } 

    // Runs through both the highlight and queensOnBoard ArrayLists and 
    // changes the background for the Queens at risk 
    for (int b = 0; b < size2; b++) { 
     for (int a = 0; a < size1; a++) { 
      if ((highlight.get(a).getX() == queensOnBoard.get(b).getX()) 
        && (highlight.get(a).getY() == queensOnBoard.get(b).getY())) { 
       int x = queensOnBoard.get(b).getX(); 
       int y = queensOnBoard.get(b).getY(); 
       chessBoxes[x][y].setBackground(Color.RED); 
      } 
     } 
    } 
} 

/* 
* Main method to run the program 
* 
* @param args Is the String of args given to the console to run the 
* operations of the program 
*/ 
public static void main(String[] args) { 
    JFrame frame = new ChessBoardGUI(); 
    frame.add(chessBoard); 
    chessBoard.setLocation(50, 50); 

    JPanel panel1 = new JPanel(); 
    panel1.add(ifNotSafe); 
    panel1.add(safe); 
    panel1.add(tip); 


    frame.add(panel1); 
    frame.setTitle("ChessBoard"); 
    frame.setVisible(true); 
    frame.setDefaultCloseOperation(EXIT_ON_CLOSE); 
} 

}

+1

왜이 태그는 '신속한'태그가 붙습니까? '스윙'이란 말이야? – shmosel

+1

제 생각에는 코드에 문제가 있습니다. 아마도 프로그램이'ifNotSafe' 변수를 숨길 수도 있지만, 게시 한 작은 코드 스 니펫을 보는 것만으로는 어렵습니다. 진지한 도움이 필요하다면, 여전히 컴파일 및 실행되는 가장 작은 비트로 코드를 압축하고 외부 종속성이없는 [mcve]를 작성 및 게시하는 것을 고려하십시오 (예 : 데이터베이스 또는 이미지에 대한 링크 필요) 문제와 관련이없는 추가 코드가 없지만 여전히 문제를 보여줍니다. –

+1

죄송하지만 그림자가 무엇입니까? –

답변

2

당신은 당신의 JLabel이 잘 표시되지 않는다는 점에서 레이아웃에 문제가있을 수 있습니다 때문에이 GUI에 잘못 추가되었습니다 보유하고있는 JPanel의. JFrame의 contentPane은 기본적으로 BorderLayout을 사용하므로 구성 요소를 추가 할 때 구성 요소가 배치되어야하는 BorderLayout 위치를 지정해야합니다. 그리드는 BorderLayout.CENTER에 배치되고 panel1은 BorderLayout.PAGE_START에 배치되어야합니다. 또한 그리드의 기본 크기를 설정해야하며, 에 을 추가 한 후 을 제외한 모든 구성 요소를 추가 한 후 전에 표시하거나 위치를 설정해야 JFrame에 pack()을 호출해야합니다.

기타 사소한 quibbles : 현재 필드의

  • 없음 공개 또는 정적해야합니다.
  • main 메소드가 아닌 비 정적 코드 내에서 JFrame에 컴포넌트를 추가해야합니다.
  • 정적 인 외부 세계에 속성을 노출해야하는 경우 클래스에 공개 게터 메서드를 제공하면 필요한 방식으로 제어 된 방식으로 만 노출 할 수 있습니다.

테스트 코드는 다음과 같습니다. 퀸 이미지를 사용할 수 없으므로 필요하지 않은 방법 인 private Icon createQueenIcon()을 만들었습니다. 이렇게하면 코드가 내 시스템에서 실행됩니다. 또한 코드를 실행하고 컴파일하기 위해 필자는 필요한 Boxes 클래스를 만들고 포함 시켰습니다. 앞으로는 코드를 컴파일하고 실행하는 데 필요한 모든 것을 포함시켜야합니다.

import javax.swing.*; 
import javax.swing.border.LineBorder; 

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Font; 
import java.awt.FontMetrics; 
import java.awt.Graphics2D; 
import java.awt.GridLayout; 
import java.awt.Image; 
import java.awt.RenderingHints; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.image.BufferedImage; 
import java.util.*; 

public class ChessBoardGUI extends JFrame { 
    private static final long serialVersionUID = 1L; 

    // !! code changes below only to allow me to run your code without 
    // your images. !! 
    // ImageIcon queenP = new ImageIcon(getClass().getResource("/images/queen.png")); 
    // Image img = queenP.getImage(); 
    // Image newImg = img.getScaledInstance(40, 40, 
    // java.awt.Image.SCALE_SMOOTH); 
    private ImageIcon queenPic = createQueenIcon(); //!! delete this 

    // all fields should be private and non-static 
    private JButton tip; 
    private JButton safe; 
    private JLabel ifNotSafe; 
    private JButton[][] chessBoxes = new JButton[8][8]; 
    private JPanel chessBoard; 
    private ArrayList<Boxes> queensOnBoard = new ArrayList<Boxes>(); 

    public ChessBoardGUI() { 
     createBoard(); 

     add(chessBoard, BorderLayout.CENTER); // Do this here 

     // !! createOtherThings(); // get rid of -- put in constructor 
     safe = new JButton("Safe?"); 
     tip = new JButton("Tip"); 
     ifNotSafe = new JLabel("Status of Board is displayed here..."); 

     ButtonListen1 safeListener = new ButtonListen1(); 
     ButtonListen2 tipListener = new ButtonListen2(); 

     safe.addActionListener(safeListener); 
     tip.addActionListener(tipListener); 

     // !! add the panel1 here! 
     JPanel panel1 = new JPanel(); 
     panel1.add(ifNotSafe); 
     panel1.add(safe); 
     panel1.add(tip); 
     add(panel1, BorderLayout.PAGE_START); // using BorderLayout constants 

     // !! setSize(500, 500); 

    } 

    // !! so I can use images without having an image 
    // !! you won't need this 
    private Icon createQueenIcon() { 
     int w = 40; 
     BufferedImage img2 = new BufferedImage(w, w, BufferedImage.TYPE_INT_ARGB); 
     Graphics2D g2 = img2.createGraphics(); 
     g2.setColor(new Color(183, 65, 14)); 
     g2.fillRect(0, 0, w, w); 
     g2.setColor(new Color(255, 215, 0)); 
     Font font = new Font(Font.SANS_SERIF, Font.BOLD, 30); 
     g2.setFont(font); 
     g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 
       RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 
     FontMetrics fontMetrics = g2.getFontMetrics(); 
     int textX = (w - fontMetrics.charWidth('Q'))/2; 
     int textY = (w - fontMetrics.getHeight())/2 + fontMetrics.getAscent(); 
     g2.drawString("Q", textX, textY); 
     g2.dispose(); 
     return new ImageIcon(img2); 
    } 

    class ButtonListen1 implements ActionListener { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      if (checkSolution(queensOnBoard) == true) { 
       // ****THIS IS WHERE THE PROBLEM IS ******* !! 
       ifNotSafe.setText("This Solution is correct so far"); 
       System.out.println("Solution is correct"); 

      } else { 
       ifNotSafe.setText("This Solution is incorrect so far"); 
       // *********Also highlight the queens that are not safe****** 
       System.out.println("Solution is incorrect"); 
      } 
     } 

    } 

    /* 
    * ActionListener for the tip button 
    */ 
    class ButtonListen2 implements ActionListener { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
     } 
    } 

    /* 
    * Creates the overall ChessBoard 
    */ 
    public void createBoard() { 
     GridLayout gridLayout = new GridLayout(); 
     gridLayout.setRows(8); 
     gridLayout.setColumns(8); 
     chessBoard = new JPanel(gridLayout); 
     chessBoard.setPreferredSize(new Dimension(640, 640)); 
     chessBoard.setBorder(new LineBorder(Color.BLACK)); 
     chessBoard.setVisible(true); 

     for (int x = 0; x < 8; x++) { 
      for (int y = 0; y < 8; y++) { 
       chessBoxes[x][y] = new JButton(); 
       chessBoxes[x][y].setBorderPainted(false); 
       if ((x + y) % 2 == 0) { 
        chessBoxes[x][y].setBackground(Color.BLACK); 
       } else { 
        chessBoxes[x][y].setBackground(Color.WHITE); 
       } 
       chessBoxes[x][y].setOpaque(true); 
       chessBoard.add(chessBoxes[x][y]); 

       BoxListener boxListen = new BoxListener(); 
       chessBoxes[x][y].addActionListener(boxListen); 
      } 
     } 
    } 

    class BoxListener implements ActionListener { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      JButton button = ((JButton) e.getSource()); 

      for (int x = 0; x < 8; x++) { 
       for (int y = 0; y < 8; y++) { 
        if (chessBoxes[x][y] == button) { 
         if ((isOnBoard(queensOnBoard, x, y) == false)) { 
          if (queensOnBoard.size() < 8) { 
           button.setIcon(queenPic); 
           queensOnBoard.add(new Boxes(x, y)); 
          } 
         } 
         /* 
         * If there is a Queen at that JButton 
         */ 
         else { 
          removeQueen(queensOnBoard, x, y); 
          button.setIcon(null); 
         } 
        } 
       } 
      } 
     } 
    } 

    /* 
    * Checks if a certain Box has a Queen in it or not 
    * 
    * @param a Is the ArrayList of the Boxes currently occupied by Queens 
    * 
    * @param x Is the X coordinate of the Box that was clicked 
    * 
    * @param y Is the Y coordinate of the Box that was clicked 
    */ 
    public boolean isOnBoard(ArrayList<Boxes> a, int x, int y) { 
     for (int i = 0; i < a.size(); i++) { 
      if (((a.get(i)).getX() == x) && ((a.get(i)).getY() == y)) { 
       return true; 
      } 
     } 
     return false; 
    } 

    /* 
    * Removes a Queen from the GUI at the specified Box (JButton) 
    * 
    * @param a Is the ArrayList of the Boxes currently occupied by Queens 
    * 
    * @param x Is the X coordinate of the Box that was clicked 
    * 
    * @param y Is the Y coordinate of the Box that was clicked 
    */ 
    public void removeQueen(ArrayList<Boxes> a, int x, int y) { 
     /* 
     * Removes the box from the overall ArrayList of Boxes Occupied by 
     * queens according to the x and y location 
     */ 
     for (int i = 0; i < a.size(); i++) { 
      if (((a.get(i)).getX() == x) && ((a.get(i)).getY() == y)) { 
       queensOnBoard.remove(i); 
      } 
     } 
    } 

    /* 
    * Return to the user which queens need to be highlighted 
    * 
    * @param queensOnBoard Is the ArrayList of Boxes that are occupied by 
    * Queens currently on the ChessBoard 
    */ 
    public void conflictingQueens(ArrayList<Boxes> queensOnBoard2) { 

    } 

    /* 
    * Checks to see if solution is correct thusfar 
    * 
    * @param queensOnBoard Is the ArrayList of Boxes that are occupied by 
    * Queens currently on the ChessBoard 
    */ 
    public boolean checkSolution(ArrayList<Boxes> queensOnBoard2) { 
     int size = queensOnBoard2.size(); 
     if (size < 1) { 
      return true; 
     } 
     if (size == 1) { 
      return true; 
     } 
     for (int x = 0; x < size - 1; x++) { 
      for (int y = 1; y < size; y++) { 
       if (queensOnBoard2.get(x).getX() == queensOnBoard2.get(y).getX()) { 
        return false; 
       } else if (queensOnBoard2.get(x).getY() == queensOnBoard2.get(y).getY()) { 
        return false; 
       } 
      } 
     } 

     return true; 
    } 

    /* 
    * Checks to see if the queen is safe from diagonal attacks 
    */ 

    /* 
    * Highlights boxes that are conflicting with one another 
    * 
    * @param highlight Is the ArrayList of Boxes that are occupied by Queens 
    * currently on the ChessBoard 
    */ 
    public void highlightBoxes(ArrayList<Boxes> highlight) { 
     int size1 = highlight.size(); 
     int size2 = queensOnBoard.size(); 
     if ((size1 == 0) && size1 == 1) { 
      for (int x = 0; x < 8; x++) { 
       for (int y = 0; y < 8; y++) { 
        chessBoxes[x][y] = new JButton(); 
        chessBoxes[x][y].setBorderPainted(false); 
        /* 
        * Assigns a color to every other box 
        */ 
        if ((x + y) % 2 == 0) { 
         chessBoxes[x][y].setBackground(Color.BLACK); 
        } else { 
         chessBoxes[x][y].setBackground(Color.WHITE); 
        } 
       } 
      } 
     } 
     for (int b = 0; b < size2; b++) { 
      for (int a = 0; a < size1; a++) { 
       if ((highlight.get(a).getX() == queensOnBoard.get(b).getX()) 
         && (highlight.get(a).getY() == queensOnBoard.get(b).getY())) { 
        int x = queensOnBoard.get(b).getX(); 
        int y = queensOnBoard.get(b).getY(); 
        chessBoxes[x][y].setBackground(Color.RED); 
       } 
      } 
     } 
    } 

    public static void main(String[] args) { 
     // !! create the GUI in a Swing thread-safe manner 
     SwingUtilities.invokeLater(() -> createGui()); 
    } 

    public static void createGui() { 
     JFrame frame = new ChessBoardGUI(); 
     // !! frame.add(chessBoard); // not here 
     // !! chessBoard.setLocation(50, 50); 

     // !! this does not belong within main 
     // !! JPanel panel1 = new JPanel(); 
     // panel1.add(ifNotSafe); 
     // panel1.add(safe); 
     // panel1.add(tip); 
     // frame.add(panel1); 

     frame.setTitle("ChessBoard"); 
     frame.pack(); // !! call this to have your GUI size itself 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
     frame.setDefaultCloseOperation(EXIT_ON_CLOSE); 
    } 

    private static class Boxes { 

     private int x; 
     private int y; 

     public Boxes(int x, int y) { 
      this.x = x; 
      this.y = y; 
     } 

     public int getY() { 
      return x; 
     } 

     public int getX() { 
      return y; 
     } 

    } 
} 
+0

정말 고마워요. 나는이 설정을 사용했다. 완벽하게 작동합니다. –