我尝试实现生命游戏的基本版本并且它起作用了,但是今天我尝试为它制作一个 GUI 并且我遇到了问题。
问题是我有一个if声明来检查游戏规则之一。IDE 告诉我它总是返回 false。
if (!grid[row][col].isAlive() && aliveNeighbours == 3)
Run Code Online (Sandbox Code Playgroud)
我检查了我的方法并进行了各种测试,但可能我太累了,看不到问题所在。
这是完整的课程:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.*;
public class Main extends JFrame {
int size = 50;
Cell[][] grid = new Cell[size][size];
//Swing components
JPanel p = new JPanel();
JPanel top = new JPanel();
JButton startButton = new JButton("Start");
JButton randomButton = new JButton("Randomize");
JPanel center = new JPanel();
public static void main(String[] args){
new Main();
}
public Main(){
super("Game of Life GUI");
setSize(1200,900);
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
p.setLayout(new BorderLayout());
center.setLayout(new GridLayout(size, size));
setupButtons();
createFirstGrid();
top.add(startButton);
top.add(randomButton);
p.add(top, BorderLayout.NORTH);
p.add(center, BorderLayout.CENTER);
add(p);
setVisible(true);
}
void startLoop(){
Timer timer = new Timer();
System.out.println("Started");
timer.schedule(new TimerTask() {
@Override
public void run() {
step();
}
}, 1000, 1000);
}
void step() {
Cell[][] newGrid = grid;
for (int row = 1; row < grid.length - 1; row++) {
for (int col = 1; col < grid[row].length - 1; col++) {
int aliveNeighbours = getAliveNeighbours(grid, row, col);
if (grid[row][col].isAlive() && aliveNeighbours == 2 || aliveNeighbours == 3){
newGrid[col][row].setAliveStatus(true);
} else if (!grid[row][col].isAlive() && aliveNeighbours == 3){
newGrid[col][row].setAliveStatus(true);
} else if (aliveNeighbours < 2 || aliveNeighbours > 3) {
newGrid[col][row].setAliveStatus(false);
}
}
}
grid = newGrid;
}
private int getAliveNeighbours(Cell[][] grid, int row, int col){
int aliveCells = 0;
for (int x = row - 1; x <= row + 1; x++){
for (int y = col - 1; y <= col; y++){
if (x < 0 || x >= grid.length || y<0 || y >= grid.length){
continue;
}
if (grid[x][y].equals(grid[row][col])){
continue;
}
if (grid[x][y].isAlive()){
aliveCells++;
}
}
}
System.out.println(aliveCells);
return aliveCells;
}
private void setupButtons() {
startButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
startLoop();
}
});
randomButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int initialAliveCells = ((size/2) * (size/5)); //totally random, but it makes up a good amount of alive points
if (initialAliveCells % 2 != 0){ //need a pair number to form couples
initialAliveCells--;
}
Random randomSeed = new Random();
ArrayList<Integer> initialIndexes = new ArrayList<Integer>();
for (int p = 0; p <initialAliveCells; p++){
initialIndexes.add(randomSeed.nextInt(size));
}
for (int x = 1; x <= initialIndexes.size(); x += 2){
grid[initialIndexes.get(x - 1)][initialIndexes.get(x)].setAliveStatus(true);
}
}
});
}
private void createFirstGrid(){
for (int row = 0; row < grid.length; row++) {
for (int col = 0; col < grid[row].length; col++) {
grid[row][col] = new Cell();
grid[row][col].setAliveStatus(false);
center.add(grid[row][col]);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是 Cell 类
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Cell extends JButton implements ActionListener {
boolean isAlive;
Color aliveColor = Color.BLACK;
Color deadColor = Color.WHITE;
public Cell(){
this.addActionListener(this);
setPreferredSize(new Dimension(5,5));
setBackground(deadColor);
}
@Override
public void actionPerformed(ActionEvent e) {
setAliveStatus(!isAlive);
updateColor();
}
private void updateColor() {
if (isAlive){
setBackground(aliveColor);
} else {
setBackground(deadColor);
}
}
public void setAliveStatus(boolean status){
this.isAlive = status;
updateColor();
}
public boolean isAlive(){
return isAlive;
}
}
Run Code Online (Sandbox Code Playgroud)
有问题的方法是 getAliveNeighbours 之一:
private int getAliveNeighbours(Cell[][] grid, int row, int col){
int aliveCells = 0;
for (int x = row - 1; x <= row + 1; x++){
for (int y = col - 1; y <= col; y++){
if (x < 0 || x >= grid.length || y<0 || y >= grid.length){ //This check shouldn't be needed as i never pass cells in the border
continue;
}
if (grid[x][y].equals(grid[row][col])){ //this is to avoid counting the current cell
continue;
}
if (grid[x][y].isAlive()){
aliveCells++;
}
}
}
System.out.println(aliveCells);
return aliveCells;
}
Run Code Online (Sandbox Code Playgroud)
它永远不会返回正确的金额,但我不明白为什么。
错误信息具有欺骗性。问题其实出在前面的if语句中:
Run Code Online (Sandbox Code Playgroud)if (grid[row][col].isAlive() && aliveNeighbours == 2 || aliveNeighbours == 3)
&&具有比 更高的优先级||。添加括号以将||条件组合在一起。
if (grid[row][col].isAlive() && (aliveNeighbours == 2 || aliveNeighbours == 3))
Run Code Online (Sandbox Code Playgroud)
没有它们,它被解析为:
if ((grid[row][col].isAlive() && aliveNeighbours == 2) || aliveNeighbours == 3)
Run Code Online (Sandbox Code Playgroud)
以这种方式解释,编译器注意到else if (!grid[row][col].isAlive() && aliveNeighbours == 3)永远不会触发。当aliveNeighbors == 3代码总是输入第一个时if,从不输入else if。这就是它抱怨的原因。但这else if不是问题,而是if上述问题。
经验教训:错误并不总是在标记线上。有时您必须查找才能找到真正的问题。
| 归档时间: |
|
| 查看次数: |
69 次 |
| 最近记录: |