2017-05-04 9 views
1

私はJavaでMinesweeperを作り直していますが、今はすべてのボタンをJFrameのグリッドに配置する必要があります。私のコードは以下の通りです:JFrameをJButtonで効率的かつ迅速に満たす方法を教えてください。

import javax.swing.*; 
import java.util.ArrayList; 
import java.awt.*; 
import javax.imageio.*; 

public class Graphics{ 
    private JFrame frame; 
    private JPanel panel; 
    private JLabel label; 
    private int boardSizeY; 
    private int boardSizeX; 

    private ImageIcon ImgEmpty = new ImageIcon("/Images/Empty.png"); 
    private ImageIcon ImgFull = new ImageIcon("/Images/UnSelected.png"); 

    public Graphics(int sizeY, int sizeX){ 
     boardSizeX = sizeX; 
     boardSizeY = sizeY; 
     gui(); 
     drawButtons(); 
    } 

    public void gui() { 
     frame = new JFrame("Minesweeper"); 
     frame.setVisible(true); 
     frame.setSize(boardSizeX*20, boardSizeY*20 + 2); 
     frame.setResizable(false); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     panel = new JPanel(); 
     panel.setLayout(null); 
    } 

    public void drawButtons(){ 
     ArrayList<JButton> buttons = new ArrayList<>(); 

     int x = 0; 
     int y = 0; 

     for(int t = 0; t < boardSizeX*boardSizeY; t++){ 
      buttons.add(new JButton(ImgFull)); 
      panel.add(buttons.get(t)); 

      buttons.get(t).setBounds(x*20, y*20, 20, 20); 

      if(y == boardSizeY-1){ 
       x++; 
       y = 0; 
      } 
      else y++; 
     } 
     frame.add(panel); 
    } 
} 

私が書いたコードは、10x10以上のボードサイズでは非常に遅いです。処理を迅速化するためにdrawButtons()関数にどのような変更を加えることができます。

+0

あなたはグリッドレイアウトを使用して考えたことはありますか?これにより、すべてのプレースメントの問題が処理されます。 –

+1

もし、すべてがうまくいけば、あなたの質問は[CodeReview。](https://codereview.stackexchange.com/)でうまくいくかもしれないと思います。質問:なぜレイアウトマネージャではなく 'setBounds()'を使うのですか? – markspace

答えて

3

このマシンでは、この30 x 30(900個のボタン)バージョンがほぼ即座に表示されます。 JButtonコンポーネントを使用し、GridLayoutを使用してそれらをレイアウトします。

これは10 x 10のサイズで、より大きなフォントで表示されます。

enter image description here

import java.awt.*; 
import java.util.*; 
import javax.swing.*; 
import javax.swing.border.EmptyBorder; 

public class MineSweeper { 

    public final static String BOMB = new String(Character.toChars(128163)); 
    private JComponent ui = null; 
    private MineFieldModel mineFieldModel; 
    private final Color[] colors = { 
     Color.BLUE, 
     Color.CYAN.darker(), 
     Color.GREEN.darker(), 
     Color.YELLOW.darker(), 
     Color.ORANGE.darker(), 
     Color.PINK.darker(), 
     Color.MAGENTA, 
     Color.RED 
    }; 
    private final int size = 30; 
    private final float fontSize = 10f; 
    private JButton[][] buttons; 
    private JLabel info = new JLabel("Enter the minefield!"); 

    MineSweeper() { 
     initUI(); 
    } 

    private JToolBar getToolBar() { 
     JToolBar tb = new JToolBar(); 
     tb.setFloatable(false); 
     tb.setLayout(new FlowLayout(FlowLayout.LEADING, 4, 2)); 

     tb.add(info); 

     return tb; 
    } 

    private final Point[] getExposableSquares(Point point) { 
     Point[] points = null; 
     int x = point.x; 
     int y = point.y; 
     if (mineFieldModel.isBomb(x, y)) { 

     } 

     return points; 
    } 

    public final void initUI() { 
     if (ui != null) { 
      return; 
     } 

     ui = new JPanel(new BorderLayout(4, 4)); 
     ui.setBorder(new EmptyBorder(4, 4, 4, 4)); 

     ui.add(getToolBar(), BorderLayout.PAGE_START); 

     mineFieldModel = new MineFieldModel(size, (int)(size*size*.4)); 

     JPanel mineFieldContainer = new JPanel(new GridLayout(
       size, size)); 
     ui.add(mineFieldContainer, BorderLayout.CENTER); 
     int in = 5; 
     Insets insets = new Insets(in, in, in, in); 
     Font f = getCompatibleFonts().firstElement().deriveFont(fontSize); 
     buttons = new JButton[size][size]; 
     for (int ii = 0; ii < size; ii++) { 
      for (int jj = 0; jj < size; jj++) { 
       JButton b = new SquareButton(); 
       b.setMargin(insets); 
       b.setFont(f); 
       b.setText("?"); 
       if (mineFieldModel.isExposed(ii, jj)) { 
        if (mineFieldModel.isBomb(ii, jj)) { 
         b.setForeground(Color.red); 
         b.setForeground(Color.BLACK); 
         b.setText(BOMB); 
        } else if (mineFieldModel.countSurroundingMines(ii, jj) > 0) { 
         int count = mineFieldModel.countSurroundingMines(ii, jj); 
         if (count > 0) { 
          b.setForeground(colors[count - 1]); 
          b.setText("" + count); 
         } 
        } else { 
         b.setText(""); 
        } 
       } 
       buttons[ii][jj] = b; 
       mineFieldContainer.add(b); 
      } 
     } 
    } 

    private static Vector<Font> getCompatibleFonts() { 
     Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); 
     Vector<Font> fontVector = new Vector<>(); 

     for (Font font : fonts) { 
      if (font.canDisplayUpTo("12345678?" + BOMB) < 0) { 
       fontVector.add(font); 
      } 
     } 

     return fontVector; 
    } 

    public JComponent getUI() { 
     return ui; 
    } 

    public static void main(String[] args) { 
     Runnable r =() -> { 
      try { 
       UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
      } catch (Exception useDefault) { 
      } 
      MineSweeper o = new MineSweeper(); 

      JFrame f = new JFrame(o.getClass().getSimpleName()); 
      f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
      f.setLocationByPlatform(true); 

      f.setContentPane(o.getUI()); 
      f.pack(); 
      f.setMinimumSize(f.getSize()); 

      f.setVisible(true); 
     }; 
     SwingUtilities.invokeLater(r); 

    } 
} 

class MineFieldModel { 

    public int size; 
    /** 
    * Records bomb locations. 
    */ 
    boolean[][] mineField; 
    /** 
    * Records whether this location has been exposed. 
    */ 
    boolean[][] fieldPlaceExposed; 
    int numberMines; 
    Random r = new Random(); 

    MineFieldModel(int size, int numberMines) { 
     this.size = size; 
     this.numberMines = numberMines; 

     mineField = new boolean[size][size]; 
     fieldPlaceExposed = new boolean[size][size]; 
     ArrayList<Point> locations = new ArrayList<>(); 
     for (int ii = 0; ii < this.size; ii++) { 
      for (int jj = 0; jj < size; jj++) { 
       mineField[ii][jj] = false; 
       // must change this to false for the actual game. 
       fieldPlaceExposed[ii][jj] = true; 
       Point p = new Point(ii, jj); 
       locations.add(p); 
      } 
     } 
     Collections.shuffle(locations, r); 
     for (int ii = 0; ii < numberMines; ii++) { 
      Point p = locations.get(ii); 
      mineField[p.x][p.y] = true; 
     } 
    } 

    public boolean isBomb(int x, int y) { 
     return mineField[x][y]; 
    } 

    public boolean isExposed(int x, int y) { 
     return fieldPlaceExposed[x][y]; 
    } 

    public int getSize() { 
     return size; 
    } 

    public int countSurroundingMines(int x, int y) { 
     int lowX = x - 1; 
     lowX = lowX < 0 ? 0 : lowX; 
     int highX = x + 2; 
     highX = highX > size ? size : highX; 

     int lowY = y - 1; 
     lowY = lowY < 0 ? 0 : lowY; 
     int highY = y + 2; 
     highY = highY > size ? size : highY; 

     int count = 0; 
     for (int ii = lowX; ii < highX; ii++) { 
      for (int jj = lowY; jj < highY; jj++) { 
       if (ii != x || jj != y) { 
        if (mineField[ii][jj]) { 
         count++; 
        } 
       } 
      } 
     } 

     return count; 
    } 
} 

class SquareButton extends JButton { 
    @Override 
    public Dimension getPreferredSize() { 
     Dimension d = super.getPreferredSize(); 
     int w = d.width; 
     int h = d.height; 
     int s = w>h ? w : h; 

     return new Dimension(s, s); 
    } 
} 
関連する問題