Я пытаюсь создать простую симуляцию Game of Life, чтобы оставаться занятой и в нее вошли две проблемы.
Во-первых, моя "доска" не окрашивается в JFrame, когда она сначала инициализируется, но после ее запуска начнется симуляция. Два, мой код countNeighbours не работает. Или, по крайней мере, наблюдаемый результат не является ожидаемым.
Вот код: Интерфейс: -
public class UserInterface extends JFrame
{
/**
*
*/
private static final long serialVersionUID = 1L;
public static Screen screen;
private JPanel controls = new JPanel();
private JButton start = new JButton("Start");
private JButton reset = new JButton("Reset");
private JSlider speed = new JSlider();
Timer t;
int tSpeed = (speed.getValue()*10)+1;
public static void main(String[] args)
{
new UserInterface();
screen.repaint();
}
public UserInterface()
{
super("Game of Life");
setSize(600,600);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
screen = new Screen();
add(screen,BorderLayout.CENTER);
controls.add(start);
controls.add(reset);
controls.add(speed);
add(controls,BorderLayout.SOUTH);
setVisible(true);
start.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(start.getText().equals("Start"))
{
t = new Timer();
start.setText("Stop");
t.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
tSpeed = (speed.getValue()*10)+1;
screen.tick();
}
},0,tSpeed);
}
else
{
start.setText("Start");
t.cancel();
}
}
});
}
}
Экран: -
public class Screen extends JPanel
{
/**
*
*/
private static final long serialVersionUID = 1L;
private Rules rules = new Rules();
private int WIDTH;
private int HEIGHT;
public Screen()
{
repaint();
setVisible(true);
}
public void tick()
{
WIDTH = UserInterface.screen.getWidth();
HEIGHT = UserInterface.screen.getHeight();
rules.tick();
repaint();
}
public void paint(Graphics g)
{
boolean[][] b = rules.getBoard();
for(int y = 0; y < rules.HEIGHT; y++)
{
for(int x = 0; x < rules.WIDTH; x++)
{
if(b[x][y] == true) g.setColor(Color.YELLOW);
else g.setColor(Color.BLACK);
int w = x*(WIDTH/rules.WIDTH);
int wsize = (WIDTH/rules.WIDTH);
int h = y*(HEIGHT/rules.HEIGHT);
int hsize = (HEIGHT/rules.HEIGHT);
g.fillRect(w,h,wsize,hsize);
}
}
}
}
Правила: -
public class Rules
{
public final int WIDTH = 100;
public final int HEIGHT = 100;
private boolean[][] board = new boolean[WIDTH][HEIGHT];
private boolean[][] tempBoard = new boolean[WIDTH][HEIGHT];
public Rules()
{
for(int y = 0; y < HEIGHT; y++)
{
for(int x = 0; x < WIDTH; x++)
{
board[x][y] = false;
}
}
board[5][3] = true;
board[5][4] = true;
board[6][3] = true;
board[6][4] = true;
}
public void tick()
{
for(int y = 0; y < HEIGHT; y++)
{
for(int x = 0; x < WIDTH; x++)
{
int n = countNeighbors(x,y);
if(n>=4)
{
tempBoard[x][y] = false;
}
else if(n == 2 || n == 3)
{
tempBoard[x][y] = true;
}
else if(n<=1)
{
tempBoard[x][y] = false;
}
}
}
for(int y = 0; y < HEIGHT; y++)
{
for(int x = 0; x < WIDTH; x++)
{
board[x][y] = tempBoard[x][y];
}
}
}
private int countNeighbors(int x, int y)
{
int n = 0;
for(int j = 0; j < 3; j++)
{
for(int i = 0; i < 3; i++)
{
if(i == 1 && j == 1)
{}
else
{
try
{
if(board[x+1-i][y+1-j]==true)n++;
}
catch(Exception e)
{
}
}
}
}
return n;
}
public void alternate(int x, int y)
{
board[x][y] = !board[x][y];
}
public boolean[][] getBoard()
{
return board;
}
}
Я медленно схожу с ума, и я не могу найти то, что я сделал неправильно. Я бы очень признателен всем, кто мог мне помочь.
Начнем с того, что ваша основная paint
JPanel
и NOT вызывает super.paint
.
Вместо этого вы должны переопределить paintComponent
и super.paintComponent
что вы вызываете super.paintComponent
прежде чем выполнять какую-либо super.paintComponent
роспись. Взгляните на выполнение пользовательской живописи
Не полагайтесь на static
значения, особенно на ширину и высоту, вместо этого ваш компонент должен указывать подсказки по объему поставки в систему. Проблема в том, что очень сложно точно рассчитать размер рамки, который учитывает различные требования к декорированию рамы. Вместо этого укажите, что ваш компонент определяет его предпочтительный размер и использует метод pack
кадров, чтобы обеспечить размер кадра.
Я также не рекомендую использовать java.util.Timer
в пользу javax.swing.Timer
поскольку есть меньше шансов на нарушение правил единственного потока Swing и меньше требований к тому, чтобы модель была синхронизирована с красками...