我一直试图制作一个简单的生命游戏模拟来让自己忙碌并且遇到两个问题。
其中一个,我的“board”在首次初始化时没有被绘制到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;
}
}
我慢慢发疯,我找不到我做错了什么。我真的很感激能帮助我的人。
答案 0 :(得分:1)
让我们首先考虑paint
JPanel
的{{1}}而不是super.paint
。
相反,您应该覆盖paintComponent
并确保在进行任何类型的自定义绘制之前调用super.paintComponent
。看看Performing Custom Painting
不要依赖static
值,尤其是宽度和高度,相反,您的组件应该是供应大小提示回系统。问题是,准确计算考虑到不同框架装饰要求的框架尺寸是非常困难的。相反,让您的组件定义它的首选大小,并使用框架的pack
方法来确保帧大小。
我也不鼓励使用java.util.Timer
支持javax.swing.Timer
,因为违反Swing单线程规则的可能性较小,并且确保模型同步的要求较少反对油漆...