3

これは宿題です。関連するコードを下部に含めました。

問題: ユーザーがグリッドのサイズを変更できるようにしようとすると、グリッドが非常に過密に描画されます。

スクリーンショット: 「人口過剰」 - http://i.imgur.com/zshAC6n.png 「望ましい人口」 - http://i.imgur.com/5Rf6P42.png

背景: コンウェイのライフ ゲームのバージョンです。クラスでは、ゲーム ロジックを処理する LifeState、ゲームを含む JPanel である LifePanel、JFrame を作成して LifePanel を追加するドライバーの 3 つのクラスを完成させました。課題は、さまざまな要件を備えた完全な GUI アプリケーションに開発することでした。私の解決策は、JFrame を拡張し、そのクラスでほとんどの作業を行うことでした。

actionlistener の外部で LifePanel を初期化すると、通常の人口が得られますが、actionlistener で LifePanel を初期化すると、グリッドが「過密」になります。

質問:人口過密はなぜ起こっているのですか?

LifePanel クラス

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

public class LifePanel extends JPanel implements MouseListener
{
private int row;
private int col;
private int scale;
private LifeState life;
boolean state;
boolean wrap;
int delay;
Timer timer;

public LifePanel(int r, int c, int s, int d)
{
    row = r;
    col = c;
    scale = s;
    delay = d;
    life = new LifeState(row,col);
    Random rnd = new Random();
    for(int i=0;i<row;i++)
        for(int j=0;j<col;j++)
            life.setCell(i,j,rnd.nextBoolean());
    timer = new Timer(delay, new UpdateListener());
    setPreferredSize( new Dimension(scale*row, scale*col));
    addMouseListener(this);
    timer.start();
}

public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    for(int i=0;i<row;i++)
        for(int j=0;j<col;j++)
            if(life.getCell(i,j))
                g.fillRect(scale*i,scale*j,scale,scale);
}

public int getRow() {
    return row;
}

public void setRow(int row) {
    this.row = row;
}

public int getCol() {
    return col;
}

public void setCol(int col) {
    this.col = col;
}

public int getScale() {
    return scale;
}

public void setScale(int scale) {
    this.scale = scale;
}

public int getDelay() {
    return delay;

}

public void setDelay(int delay) {
    this.delay = delay;
    timer.setDelay(delay);
}

public void pauseGame(){
    timer.stop();
}
public void playGame(){
    timer.restart();
}
public void setInitState(boolean set){
    state = set;
    if(state){
      timer.stop();
    }
}
public void setWrap(boolean set){
    wrap = set;
    if(wrap){
    //implement allow wrap
    }
}

@Override
public void mouseClicked(MouseEvent e) {
  if(state){
    int x=e.getX(); 
    int y=e.getY();
    boolean isFilled;
    isFilled = life.getCell(x,y);
    //Test pop-up
    JOptionPane.showMessageDialog(this, x+","+y+"\n"+life.getCell(x,y));
    if(isFilled){
      life.setCell(x,y,false);
    }else{
      life.setCell(x,y,true);
    }
    repaint();
  }
}


@Override
public void mousePressed(MouseEvent e) {}

@Override
public void mouseReleased(MouseEvent e) {}

@Override
public void mouseEntered(MouseEvent e) {}

@Override
public void mouseExited(MouseEvent e) {}

private class UpdateListener implements ActionListener
{
    public void actionPerformed(ActionEvent e)
    {
        life.iterate();
        repaint();
    }
}


}

LifeFrame クラス

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

public class LifeFrame extends JFrame implements ActionListener{ 

JMenuBar menuBar; 
JMenu mainMenu, helpMenu; 
JMenuItem restartItem, quitItem, helpItem; 
JButton stopButton, playButton, pauseButton, startButton; 
CardLayout cardLayout = new MyCardLayout(); 
CardLayout cardLayout2 = new MyCardLayout(); 
SetupPanel setupPanel; //panel for input 
LifePanel gamePanel;  //game panel 
JPanel controls = new JPanel(); //controls for game 
JPanel controls2 = new JPanel(); //controls for input panel 
JPanel cardPanel = new JPanel(cardLayout); 
JPanel cardPanel2 = new JPanel(cardLayout2); 
int gridRow=480; 
int gridCol=480; 
int scale=1; 
int delay=2;
boolean setState = false; 
boolean setWrap = false; 

public LifeFrame() { 
    setTitle("Game of Life"); 
    setLayout(new BorderLayout()); 

    //Add the Panels 
    setupPanel = new SetupPanel(); 
    gamePanel = new LifePanel(gridRow,gridCol,scale,delay); 
    cardPanel.add(setupPanel, "1");
    cardPanel.add(gamePanel, "2");
    add(cardPanel, BorderLayout.NORTH); 

    cardPanel2.add(controls2, "1"); 
    cardPanel2.add(controls, "2"); 
    add(cardPanel2, BorderLayout.SOUTH); 
    //init menu 
    menuBar = new JMenuBar(); 

    //button listener setup 
    stopButton = new JButton("Stop"); 
    pauseButton = new JButton("Pause"); 
    playButton = new JButton("Play"); 
    startButton = new JButton("Start"); 
    stopButton.addActionListener(this); 
    pauseButton.addActionListener(this); 
    playButton.addActionListener(this); 
    startButton.addActionListener(this); 
    //menu listener setup 
    restartItem = new JMenuItem("Restart", KeyEvent.VK_R); 
    quitItem = new JMenuItem("Quit", KeyEvent.VK_Q); 
    helpItem = new JMenuItem("Help", KeyEvent.VK_H); 
    restartItem.addActionListener(this); 
    quitItem.addActionListener(this); 
    helpItem.addActionListener(this); 
    //add buttons 
    controls.add(stopButton); 
    controls.add(pauseButton); 
    controls.add(playButton); 
    controls2.add(startButton); 
    //build the menus 
    mainMenu = new JMenu("Menu"); 
    mainMenu.setMnemonic(KeyEvent.VK_M); 
    helpMenu = new JMenu("Help"); 
    helpMenu.setMnemonic(KeyEvent.VK_H); 
    menuBar.add(mainMenu); 
    menuBar.add(helpMenu); 
    setJMenuBar(menuBar); 
    //add JMenuItems 
    restartItem.getAccessibleContext().setAccessibleDescription("Return to setup screen"); 
    mainMenu.add(restartItem); 
    mainMenu.add(quitItem); 
    helpMenu.add(helpItem); 


    this.addWindowListener(new WindowAdapter(){ 
        public void windowClosing(WindowEvent e){ 
            System.exit(0); 
        } 
    }); 

    pack(); 
    setLocationRelativeTo(null); 
    setVisible(true); 
    setDefaultCloseOperation(EXIT_ON_CLOSE); 
} 
@Override 
public void actionPerformed(ActionEvent e) { 
    try{ 
    gridRow = setupPanel.getRowSize(); 
    gridCol = setupPanel.getColSize(); 
    scale = setupPanel.getScale(); 
    delay = setupPanel.getDelay(); 
    setWrap = setupPanel.getSetWrap(); 
    setState = setupPanel.getSetState(); 
    }catch (NumberFormatException n){ 
        JOptionPane.showMessageDialog(LifeFrame.this, "Make sure the fields contain only digits and are completed!"); 
        return; 
    } 
    if(e.getSource() == pauseButton){ 
        gamePanel.pauseGame(); 
    }else if(e.getSource() == playButton){ 
        gamePanel.playGame(); 
    }else if(e.getSource() == quitItem){ 
        System.exit(0); 
    }else if(e.getSource() == restartItem || e.getSource() == stopButton){ 
        cardLayout.show(cardPanel, "1"); 
        cardLayout2.show(cardPanel2, "1"); 
        pack();
        setLocationRelativeTo(null);
    }else if(e.getSource() == helpItem){ 
        String helpText = "Help\nPlease make sure every field is completed and contains only digits\nCurrent Stats:\nGrid Size: "+gamePanel.getRow()+" by "+gamePanel.getCol()+"\nScale: "+ gamePanel.getScale() +"\nDelay: "+gamePanel.getDelay()+"\nManual Initial State: "+setState+"\nEnable Wrapping: "+setWrap;
        JOptionPane.showMessageDialog(LifeFrame.this, helpText); 
    }else if(e.getSource() == startButton){ 

        gamePanel = new LifePanel(gridRow,gridCol,scale,delay); 
        cardPanel.add(gamePanel, "2");
        /*
         * Alternate solution, throws array index out of bounds due to array usage in the LifePanel, but properly 
         * populates the grid.
         * 
        gamePanel.setRow(gridRow);
        gamePanel.setCol(gridCol);
        gamePanel.setScale(scale);
        gamePanel.setDelay(delay);
        */
        if(setWrap){ 
            gamePanel.setWrap(true); 
            gamePanel.playGame(); 
        }else if(setState){ 
            gamePanel.setInitState(true); 
        }else{ 
            gamePanel.setWrap(false); 
            gamePanel.setInitState(false); 
            gamePanel.playGame(); 
        }
        gamePanel.repaint(); 
        cardLayout.show(cardPanel, "2"); 
        cardLayout2.show(cardPanel2, "2"); 
        pack();
        setLocationRelativeTo(null);
    } 
} 
public static class MyCardLayout extends CardLayout { 

    @Override 
    public Dimension preferredLayoutSize(Container parent) { 

        Component current = findCurrentComponent(parent); 
        if (current != null) { 
            Insets insets = parent.getInsets(); 
            Dimension pref = current.getPreferredSize(); 
            pref.width += insets.left + insets.right; 
            pref.height += insets.top + insets.bottom; 
            return pref; 
        } 
        return super.preferredLayoutSize(parent); 
    } 

    public Component findCurrentComponent(Container parent) { 
        for (Component comp : parent.getComponents()) { 
            if (comp.isVisible()) { 
                return comp; 
            } 
        } 
        return null; 
    } 

} 
}

このすべてを読んでくれてありがとう、そしてあなたが提供する助け/アドバイスを事前に。

編集: スクリーン ショットと洗練された質問を追加しました。

4

1 に答える 1