Почему не работает моя программа Java Game of Life? - PullRequest
1 голос
/ 01 апреля 2012

Я работаю над программой, которая создает графическую модель игры жизни Конвея, но она не позволяет мне делать что-либо после ее запуска;кнопки не работают и сетка не меняется.Что я делаю не так?

import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;


public class gameOfLife extends JApplet{
    private static final long serialVersionUID = 1L;

cellClass cell;

public void init() {
    Container contentWindow = getContentPane();
    cell = new cellClass();{{
    setLayout(new FlowLayout()) }};
    contentWindow.add(cell);    
    }
} 

class grid extends JComponent{ 
    private static final long serialVersionUID = 2L;

    int XSIZE = 500;
    int YSIZE = 500;
    private int row;
    private int col;
    private int size = 5;
    private cellClass c;
    private Dimension preferredSize = new Dimension(XSIZE, YSIZE);

    public void paint(Graphics a) {
    int x, y;
        for(x=0; x<row; x++){
        for(y=0; y<col; y++){
            if(c.grid[x][y] != 0){
                a.drawRect(x * size, y * size, 5, 5);
            }
        }
    }
    a.drawRect(0, 0, XSIZE, YSIZE);

}

public grid(cellClass newGrid, int newRow, int newCol, int newSize) {
    setMinimumSize(preferredSize);
    setMaximumSize(preferredSize);
    setPreferredSize(preferredSize);
    this.row = newRow;
    this.col = newCol;
    this.size = newSize;
    this.c = newGrid;

}
}

class cellClass extends JPanel implements ActionListener{
private static final long serialVersionUID = 3L;

static final int ROW = 100;
static final int COL = 100;
static final int SIZE = 5;
static final int min = 2;
static final int max = 3;
static final int birth = 3;
public int genCount = 0;

public int[][] grid;
private int[][] nextGrid;

private GridBagLayout gridBag = new GridBagLayout();
private GridBagConstraints c = new GridBagConstraints();

JLabel title;
JLabel genCounter;
JButton oneGen;
JButton contPlay;
JButton stop;
public grid board;
public boolean paused = true;
public boolean canChange = true;

cellClass() {
    grid = new int [ROW][COL];
    nextGrid = new int[ROW][COL];

    makeGrid(grid);

    setLayout(gridBag);

    title = new JLabel("Game of Life Applet");
    c.gridx = 0;
    c.gridy = 0;
    c.gridwidth = 2;
    c.insets = new Insets(2,0,0,0);
    c.anchor = GridBagConstraints.WEST;
    add(title);

    board = new grid(this,ROW,COL,SIZE);
    c.gridx = 0;
    c.gridy = 2;
    c.gridwidth = 1;
    gridBag.setConstraints(board, c);
    add(board);

    oneGen = new JButton("Move one Generation");
    c.gridx = 0;
    c.gridy = 3;
    c.gridwidth = 1;
    gridBag.setConstraints(oneGen, c);
    add(oneGen);

    contPlay = new JButton("Play");
    c.gridx = 1;
    c.gridy = 3;
    c.gridwidth = 1;
            contPlay.setVisible(true);
    gridBag.setConstraints(contPlay, c);
    add(contPlay);

    stop = new JButton("Stop");
    c.gridx = 2;
    c.gridy = 3;
    c.gridwidth = 1;
            stop.setVisible(false);
    gridBag.setConstraints(stop, c);
    add(stop);

    genCounter = new JLabel("Generation: 0");
    c.gridx = 0;
    c.gridy = 1;
    c.gridwidth = 1;
    gridBag.setConstraints(genCounter, c);
    add(genCounter);
}

class ButtonListener {
    public void addActionListener(ActionEvent e) throws InterruptedException {
        JButton source = (JButton)e.getSource();

        if(source == oneGen){
            nextGen();
        }
        if(source == contPlay){
            paused = false;
            canChange = false;
                            contPlay.setVisible(false);
                            stop.setVisible(true);
            while (paused = false) {
                nextGen();
                Thread.sleep(1000);
            }
        }
        if(source == stop) {
            paused = true;
            canChange = false;
                            stop.setVisible(false);
                            contPlay.setVisible(true);
        }
    }
}

public void mouseClicked(MouseEvent e){
    int xco = e.getX() - board.getX();
    int yco = e.getY() - board.getY();
    if((e.getComponent() == board) && (paused == true)){
        if(grid[xco/5][yco/5] == 1){
            grid[xco/5][yco/5] = 0;
            board.repaint();
        }else if(grid[xco/5][yco/5] == 0){
            grid[xco/5][yco/5] = 1;
            board.repaint();
        }
    }
}

public void makeGrid(int[][] emptyGrid) {
    int x, y;
    for(x = 0; x < ROW; x++){
        for(y = 0; y < COL; y++){
            emptyGrid[x][y] = 0;
        }
    }
}

public void nextGen() {
    getNextGen();
    board.repaint();
    genCount++;
    genCounter.setText("Generation: " + Integer.toString(genCount));        
}

public void getNextGen() {
    int x, y, neighbor;
    makeGrid(nextGrid);
    for(x = 0; x < ROW; x++){
        for(y=0; y<COL; y++){
            neighbor = calculate(x,y);

            if(grid[x][y] != 0){
                if((neighbor >= min) && (neighbor <= max)) {
                    nextGrid[x][y] = neighbor;
                }
            }else {
                if(neighbor == birth){
                    nextGrid[x][y] = birth;
                }
            }
        }
    }
    makeGrid(grid);
    copyGrid(nextGrid,grid);
}

public void copyGrid(int[][] source, int[][] newGrid) {
    int x, y;
    for(x=0; x<ROW; x++){
        for(y=0; y<COL; y++){
            newGrid[x][y] = source[x][y];
        }
    }
}

private int calculate(int x, int y){
    int a, b, total;

    total = (grid[x][y]);
    for (a = -1; a<= 1; a++) {
        for (b = -1; b <= 1; b++){
            if(grid[(ROW + (x + a)) % ROW][(COL + (y + b)) % COL] != 0) {
                total++;
            }
        }
    }
    return total;
}

@Override
public void actionPerformed(ActionEvent arg0) {
    // TODO Auto-generated method stub

    }
}       

Если бы кто-нибудь мог сказать мне, что с ним не так, это было бы здорово.

Ответы [ 3 ]

5 голосов
/ 01 апреля 2012

Одна из ваших основных проблем заключается в том, что вы пытаетесь запустить длинный процесс в потоке событий Swing, также известном как поток обработки событий или EDT, и это фактически приведет к зависанию вашей программы. Я вижу эту проблему, возникающую здесь:

class ButtonListener {
  public void addActionListener(ActionEvent e) throws InterruptedException {
     JButton source = (JButton) e.getSource();

     // ...

        while (paused = false) { // *******
           nextGen();
           Thread.sleep(1000);  // ******
        }
     }

     // ...

}

у вас есть и цикл while(true), и Thread.sleep(...), ни один из которых не должен вызываться в потоке событий.

Вместо этого вы должны использовать Swing Timer .

Подробнее о ветке событий Swing читайте Параллельность в Swing .

Также (1), где вы позволяете клеткам инициализироваться, чтобы они были живы? Без живых клеток для начала все поколения не покажут ничего, кроме пустой сетки? Вам нужно добавить MouseListener к одному или нескольким вашим компонентам? Я думаю, что это было бы хорошей идеей.

Также (2) кнопки обычно работают намного лучше, когда вы добавляете к ним ActionListener, как хорошо описано в руководстве по Swing button . Вы прошли учебники Swing? Если нет, пожалуйста, проверьте их (найдите их здесь ), так как они, я думаю, вам очень помогут.

Также (3) вы можете откусывать больше, чем можете прожевать, пытаясь решить слишком много проблем за один раз. Когда я создаю GUI, похожий на этот, мне нравится работать над каждой частью программы изолированно и сначала заставить ее работать, прежде чем объединить все в одну большую программу. Так, например, сначала поработайте над моделью без графического интерфейса и заставьте поколения работать, запустив ее через тестовый код, который вызывает методы модели. Затем поочередно работайте с каждой частью графического интерфейса, включая JButtons, затем MouseListener, затем отображение игры жизни, затем реализацию поколений.

Намного легче отлаживать тестовые программы меньшего размера, чем пытаться отлаживать весь shebang, поверьте мне.

1 голос
/ 01 апреля 2012

Ваша программа запускается для меня, но есть другие проблемы. Это поможет вам решить проблемы:

Изменение:

cell = new cellClass();

Кому:

cell = new cellClass(){{
  setLayout(new FlowLayout());
}}; 
0 голосов
/ 01 апреля 2012

может попробовать super.init () в init ()?

...