使用 GUI 的 Java 捕食者-猎物模拟无法运行模拟



我正在尝试为捕食者-猎物模拟添加一个GUI。它可以让用户选择他们想要进行的模拟(涉及物种(,设置他们想要的模拟字段大小,并显示模拟的进度和结果。

问题是,在我生成字段后,我无法通过单击我设置的按钮来重置模拟或运行下一步或运行下一百步,更不用说显示模拟的进度了。

这是我的GUI类的代码:

import java.awt.*;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JComboBox;
import javax.swing.JTextField;

/**
* Illustrate the GUI of the simulator.
* 
* @author Jeremy Chu
* @version 2021.06.02
*/
public class GUI extends JFrame
{
private JFrame frame;
private JPanel panel1;
private JPanel panel2;
private JPanel panel3;
private Simulator simulator;
private Animal animal;
private Field field;
private SimulatorView view;

//species2 = {"RF","RW","RB","RH","FW","FB","FH","WB","WH","BH"};
private SimulatorRF simulatorRF;
private SimulatorRW simulatorRW;
private SimulatorRB simulatorRB;
private SimulatorRH simulatorRH;
private SimulatorFW simulatorFW;
private SimulatorFB simulatorFB;
private SimulatorFH simulatorFH;
private SimulatorWB simulatorWB;
private SimulatorWH simulatorWH;
private SimulatorBH simulatorBH;
//species3 = {"RFW","RFB","RFH","RWB","RWH","RBH","FWB","FWH","FBH","WBH"};
private SimulatorRFW simulatorRFW;
private SimulatorRFB simulatorRFB;
private SimulatorRFH simulatorRFH;
private SimulatorRWB simulatorRWB;
private SimulatorRWH simulatorRWH;
private SimulatorRBH simulatorRBH;
private SimulatorFWB simulatorFWB;
private SimulatorFWH simulatorFWH;
private SimulatorFBH simulatorFBH;
private SimulatorWBH simulatorWBH;
//species4 = {"RFWB","RFWH","RFBH","RWBH","FWBH"};
private SimulatorRFWB simulatorRFWB;
private SimulatorRFWH simulatorRFWH;
private SimulatorRFBH simulatorRFBH;
private SimulatorRWBH simulatorRWBH;
private SimulatorFWBH simulatorFWBH;


JComboBox comboBox1;
JComboBox comboBox2;
JComboBox comboBox3;
JComboBox comboBox4;

JButton button;
JButton button1;
JButton button2;
JButton button3;
JButton button4;
JButton button5;
JButton reset_butt;
JButton nextstep_butt;
JButton longstep_butt;

JTextField depthtxt;
JTextField widthtxt;
int depth = 100;
int width = 100;
int version = 0;

public GUI() {
frame = new JFrame();
panel1 = new JPanel();
panel2 = new JPanel();
//panel3 = new JPanel();

panel1.setBackground(Color.lightGray);
panel2.setBackground(Color.gray);
//panel3.setBackground(Color.blue);


String[] species2 = {"","Rabbits & Foxes","Rabbits & Wolves","Rabbits & Bears","Rabbits & Hunters","Foxes & Wolves",
"Foxes & Bears","Foxes & Hunters","Wolves & Bears","Wolves & Hunters","Bears & Hunters"};
String[] species3 = {"","Rabbits & Foxes & Wolves","Rabbits & Foxes & Bears","Rabbits & Foxes & Hunters","Rabbits & Wolves & Bears",
"Rabbits & Wolves & Hunters","Rabbits & Bears & Hunters","Foxes & Wolves & Bears","Foxes & Wolves & Hunters",
"Foxes & Bears & Hunters","Wolves & Bears & Hunters"};
String[] species4 = {"","Rabbits & Foxes & Wolves & Bears","Rabbits & Foxes & Wolves & Hunters","Rabbits & Foxes & Bears & Hunters",
"Rabbits & Wolves & Bears & Hunters","Foxes & Wolves & Bears & Hunters"};
String[] species5 = {"","ALL"};

comboBox1 = new JComboBox(species2);
comboBox1.addActionListener(new Combobox1Handler());
comboBox1.setEnabled(false);
comboBox2 = new JComboBox(species3);
comboBox2.addActionListener(new Combobox2Handler());
comboBox2.setEnabled(false);
comboBox3 = new JComboBox(species4);
comboBox3.addActionListener(new Combobox3Handler());
comboBox3.setEnabled(false);
comboBox4 = new JComboBox(species5);
comboBox4.addActionListener(new Combobox4Handler());
comboBox4.setEnabled(false);


JLabel label1 = new JLabel("");
JLabel label2 = new JLabel("Choose Options to generate Simulation");
JLabel label3 = new JLabel("");
JLabel label4 = new JLabel("Choose species in the field: ");
JLabel label5 = new JLabel("");
JLabel label6 = new JLabel("<html><font size='4'color=gray> Rabbits</font> <font size='4'color=orange> Foxes</font><font size='4'color=blue> Wolves</font><font size='4'color=red> Bears</font><font size='4'color=black> Hunters</font></html>");
JLabel label7 = new JLabel("");
JLabel label17 = new JLabel("");
JLabel label18 = new JLabel("");
JLabel label8 = new JLabel("Simulate:");
JLabel label9 = new JLabel("");
JLabel label10 = new JLabel("");
JLabel label11 = new JLabel("depth:");
JLabel label12 = new JLabel("Width:");
JLabel label13 = new JLabel("");
JLabel label14 = new JLabel("Reset");
JLabel label15 = new JLabel("Next step");
JLabel label16 = new JLabel("Next hundred step");

button1 = new JButton("Two species");
button1.addActionListener(new Button1Handler());
button2 = new JButton("Three species");
button2.addActionListener(new Button2Handler());
button3 = new JButton("Four species");
button3.addActionListener(new Button3Handler());
button4 = new JButton("All");
button4.addActionListener(new Button4Handler());
button5 = new JButton("Reset");
button5.addActionListener(new Button5Handler());

button = new JButton("Generate Field");
button.addActionListener(new ButtonHandler());
reset_butt = new JButton("Reset");
reset_butt.addActionListener(new ResetbuttHandler());
nextstep_butt = new JButton("Next step");
nextstep_butt.addActionListener(new NextstepbuttHandler());
longstep_butt = new JButton("Next hundred steps");
longstep_butt.addActionListener(new LongstepbuttHandler());
depthtxt = new JTextField();
depthtxt.setText("100");
//depthtxt.setEnabled(false);
widthtxt = new JTextField();
widthtxt.setText("100");    


panel1.setLayout(new GridLayout(7,5,10,0));
panel1.add(label1);         panel1.add(label2);         panel1.add(label3);
panel1.add(label4);         panel1.add(label5);         panel1.add(label6);
panel1.add(button1);        panel1.add(button2);        panel1.add(button3);
panel1.add(comboBox1);      panel1.add(comboBox2);      panel1.add(comboBox3);
panel1.add(button4);        panel1.add(label7);         panel1.add(label18);
panel1.add(comboBox4);      panel1.add(label17);        panel1.add(button5);
panel2.setLayout(new GridLayout(5,4,10,0));
panel2.add(label8);         panel2.add(label9);         panel2.add(label10);
panel2.add(label11);        panel2.add(label12);        panel2.add(label13);
panel2.add(depthtxt);       panel2.add(widthtxt);       panel2.add(button);
panel2.add(reset_butt);     panel2.add(nextstep_butt);  panel2.add(longstep_butt);
//panel3.setLayout(new GridLayout(5,4,10,0));

frame.add(panel1,BorderLayout.NORTH);
frame.add(panel2,BorderLayout.SOUTH);
//frame.add(panel3,BorderLayout.SOUTH);


frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setTitle("Predator and Prey simulator");
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args){
new GUI();
}


private class Button1Handler implements ActionListener{//Two Species
public void actionPerformed(ActionEvent e){
button2.setEnabled(false);
button3.setEnabled(false);
button4.setEnabled(false);
comboBox1.setEnabled(true);
comboBox2.setEnabled(false);
comboBox3.setEnabled(false);
comboBox4.setEnabled(false);
}
}
private class Button2Handler implements ActionListener{//Three Species
public void actionPerformed(ActionEvent e){
button1.setEnabled(false);
button3.setEnabled(false);
button4.setEnabled(false);
comboBox1.setEnabled(false);
comboBox2.setEnabled(true);
comboBox3.setEnabled(false);
comboBox4.setEnabled(false);
}
}
private class Button3Handler implements ActionListener{//Four Species
public void actionPerformed(ActionEvent e){
button1.setEnabled(false);
button2.setEnabled(false);
button4.setEnabled(false);
comboBox1.setEnabled(false);
comboBox2.setEnabled(false);
comboBox3.setEnabled(true);
comboBox4.setEnabled(false);
}
}
private class Button4Handler implements ActionListener{//All Species
public void actionPerformed(ActionEvent e){
button1.setEnabled(false);
button2.setEnabled(false);
button3.setEnabled(false);
comboBox1.setEnabled(false);
comboBox2.setEnabled(false);
comboBox3.setEnabled(false);
comboBox4.setEnabled(true);
}
}
private class Button5Handler implements ActionListener{//Reset Species
public void actionPerformed(ActionEvent e){
button1.setEnabled(true);
button2.setEnabled(true);
button3.setEnabled(true);
button4.setEnabled(true);
comboBox1.setEnabled(false);
comboBox2.setEnabled(false);
comboBox3.setEnabled(false);
comboBox4.setEnabled(false);
comboBox1.setSelectedIndex(0);
comboBox2.setSelectedIndex(0);
comboBox3.setSelectedIndex(0);
comboBox4.setSelectedIndex(0);
}
}
private class Combobox1Handler implements ActionListener{
public void actionPerformed(ActionEvent e){
//species2 = {"RF","RW","RB","RH","FW","FB","FH","WB","WH","BH"}
if(comboBox1.getSelectedIndex() == 1){//RF
version = 1;
}
else if(comboBox1.getSelectedIndex() == 2){//RW
version = 2;
}
...
else if(comboBox1.getSelectedIndex() == 10){
version = 10;
}
}
}
private class Combobox2Handler implements ActionListener{
public void actionPerformed(ActionEvent e){
//species3 = {"RFW","RFB","RFH","RWB","RWH","RBH","FWB","FWH","FBH","WBH"};
if(comboBox2.getSelectedIndex() == 1){
version = 11;
}
else if(comboBox2.getSelectedIndex() == 2){
version = 12;
}
...
else if(comboBox2.getSelectedIndex() == 10){
version = 20;
}
}
}
private class Combobox3Handler implements ActionListener{
public void actionPerformed(ActionEvent e){
//species4 = {"RFWB","RFWH","RFBH","RWBH","FWBH"};
if(comboBox3.getSelectedIndex() == 1){
version = 21;
}
else if(comboBox3.getSelectedIndex() == 2){
version = 22;
}
...
else if(comboBox3.getSelectedIndex() == 5){
version = 25;
}
}
}
private class Combobox4Handler implements ActionListener{
public void actionPerformed(ActionEvent e){
//species5 = {"All"};
if(comboBox4.getSelectedIndex() == 1){
version = 0;
}
}
}  
private class ButtonHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
String depthstr = depthtxt.getText();
String widthstr = widthtxt.getText();
int depth = Integer.parseInt(depthstr);
int width = Integer.parseInt(widthstr);
switch(version) {
case 0:
Simulator setsize = new Simulator();
setsize.Simulator(depth,width);
break;
case 1:
SimulatorRF setsizeRF = new SimulatorRF();
setsizeRF.SimulatorRF(depth,width);
break;
case 2:
SimulatorRW setsizeRW = new SimulatorRW();
setsizeRW.SimulatorRW(depth,width);
break;
...
case 25:
SimulatorFWBH setsizeFWBH = new SimulatorFWBH();
setsizeFWBH.SimulatorFWBH(depth,width);
break;
}            
}
}      
private class ResetbuttHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
simulator = new Simulator();
Simulator reseting = new Simulator();
reseting.reset();//*Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
}
}   
private class NextstepbuttHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
simulator = new Simulator();
Simulator onestep = new Simulator();
onestep.simulateOneStep();//*Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
}
}
private class LongstepbuttHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
simulator = new Simulator();
Simulator longstep = new Simulator();
longstep.runLongSimulation();//*Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
}
}
}

无论我点击按钮";重置";或";"下一步";或";接下来的一百步";,它显示了相同的错误信息:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Simulator.simulateOneStep(Simulator.java:112)
at GUI.actionPerformed(GUI.java:463)
...
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Simulator.simulate(Simulator.java:95)
at Simulator.runLongSimulation(Simulator.java:85)
at GUI.actionPerformed(GUI.java:468)
...
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Simulator.reset(Simulator.java:132)
at GUI.actionPerformed(GUI.java:458)
...
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Simulator.simulate(Simulator.java:95)
at Simulator.runLongSimulation(Simulator.java:85)
...
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Simulator.simulateOneStep(Simulator.java:112)
at GUI$NextstepbuttHandler.actionPerformed(GUI.java:485)
...
java.lang.NullPointerException
at Simulator.simulateOneStep(Simulator.java:112)
java.lang.NullPointerException
at Simulator.simulateOneStep(Simulator.java:112)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Simulator.simulateOneStep(Simulator.java:112)
at GUI$NextstepbuttHandler.actionPerformed(GUI.java:481)
...
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Simulator.reset(Simulator.java:132)
at GUI$ResetbuttHandler.actionPerformed(GUI.java:474)
...

我知道这可能很难理解,但有人能找出我的代码可能出了什么问题吗?很抱歉给您带来不便。。。

这是我第一次发帖,所以如果有任何问题,请告诉我。

*编辑----------------------------------------------------------------------------------------------------------

以下是可能导致问题的模拟器类代码:

import java.util.Random;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.awt.Color;
/**
* A simple predator-prey simulator, based on a rectangular field
* 
* @author Jeremy Chu
* @version 2021.05.30
*/
public class Simulator
{
// Constants representing configuration information for the simulation.
// The default width for the grid.
private static final int DEFAULT_WIDTH = 100;
// The default depth of the grid.
private static final int DEFAULT_DEPTH = 100;
// The probability that a hunter will be created in any given grid position.
private static final double HUNTER_CREATION_PROBABILITY = 0.05;
// The probability that a bear will be created in any given grid position.
private static final double BEAR_CREATION_PROBABILITY = 0.01;
// The probability that a wolf will be created in any given grid position.
private static final double WOLF_CREATION_PROBABILITY = 0.02;
// The probability that a fox will be created in any given grid position.
private static final double FOX_CREATION_PROBABILITY = 0.03;
// The probability that a rabbit will be created in any given grid position.
private static final double RABBIT_CREATION_PROBABILITY = 0.08;    


// List of animals in the field.
private List<Animal> animals;
// The current state of the field.
private Field field;
// The current step of the simulation.
private int step;
// A graphical view of the simulation.
private SimulatorView view;

/**
* Construct a simulation field with default size.
*/
public void Simulator()
{
Simulator(100, 100);
}

/**
* Create a simulation field with the given size.
* @param depth Depth of the field. Must be greater than zero.
* @param width Width of the field. Must be greater than zero.
*/
public void Simulator(int depth, int width)
{
if(width <= 0 || depth <= 0) {
System.out.println("The dimensions must be greater than zero.");
System.out.println("Using default values.");
depth = DEFAULT_DEPTH;
width = DEFAULT_WIDTH;
}

animals = new ArrayList<Animal>();
field = new Field(depth, width);
// Create a view of the state of each location in the field.
view = new SimulatorView(depth, width);
view.setColor(Rabbit.class, Color.gray);
view.setColor(Fox.class, Color.orange);
view.setColor(Wolf.class, Color.blue);
view.setColor(Bear.class, Color.red);
view.setColor(Hunter.class, Color.black);

// Setup a valid starting point.
reset();
}

/**
* Run the simulation from its current state for a reasonably long period,
* e.g. 100 steps.
*/
public void runLongSimulation()
{
simulate(100);//*Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
}

/**
* Run the simulation from its current state for the given number of steps.
* Stop before the given number of steps if it ceases to be viable.
* @param numSteps The number of steps to run for.
*/
public void simulate(int numSteps)
{
for(int step = 1; step <= numSteps && view.isViable(field); step++) {//*Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
simulateOneStep();
}
}

/**
* Run the simulation from its current state for a single step.
* Iterate over the whole field updating the state of each
* wolf, fox and rabbit.
*/
public void simulateOneStep()
{
step++;
// Provide space for newborn animals.
List<Animal> newAnimals = new ArrayList<Animal>();        
// Let all rabbits act.
for(Iterator<Animal> it = animals.iterator(); it.hasNext(); ) {//*Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
Animal animal = it.next();
animal.act(newAnimals);
if(! animal.isAlive()) {
it.remove();
}
}

// Add the newly born wolves, foxes and rabbits to the main lists.
animals.addAll(newAnimals);
view.showStatus(step, field);
}

/**
* Reset the simulation to a starting position.
*/
public void reset()
{
step = 0;
animals.clear();//*Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
populate();

// Show the starting state in the view.
view.showStatus(step, field);
}

/**
* Randomly populate the field with wolves, foxes and rabbits.
*/
private void populate()
{
Random rand = Randomizer.getRandom();
field.clear();
for(int row = 0; row < field.getDepth(); row++) {
for(int col = 0; col < field.getWidth(); col++) {
if(rand.nextDouble() <= HUNTER_CREATION_PROBABILITY) {
Location location = new Location(row, col);
Hunter hunter = new Hunter(true, field, location);
animals.add(hunter);
}
else if(rand.nextDouble() <= BEAR_CREATION_PROBABILITY) {
Location location = new Location(row, col);
Bear bear = new Bear(true, field, location);
animals.add(bear);
}
else if(rand.nextDouble() <= WOLF_CREATION_PROBABILITY) {
Location location = new Location(row, col);
Wolf wolf = new Wolf(true, field, location);
animals.add(wolf);
}
else if(rand.nextDouble() <= FOX_CREATION_PROBABILITY) {
Location location = new Location(row, col);
Fox fox = new Fox(true, field, location);
animals.add(fox);
}
else if(rand.nextDouble() <= RABBIT_CREATION_PROBABILITY) {
Location location = new Location(row, col);
Rabbit rabbit = new Rabbit(true, field, location);
animals.add(rabbit);
}
// else leave the location empty.
}
}
}
}

当我使用其余按钮时,似乎无法访问我的生成按钮生成的数据,但我已经尝试了很长时间,仍然无法解决它…

以下是我的代码:https://github.com/KasmaJC/predator-prey-simulation-with-GUI

没关系。。。我找到了问题的原因:

当我单击这些按钮时,我会再次创建新的对象方法,这就是为什么当我使用其余按钮时,不会访问generate按钮生成的数据。

private class ResetbuttHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
simulator = new Simulator();
Simulator reseting = new Simulator();// HERE
reseting.reset();        
}
}   
private class NextstepbuttHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
simulator = new Simulator();
Simulator onestep = new Simulator();// HERE
onestep.simulateOneStep();        
}
}
private class LongstepbuttHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
simulator = new Simulator();
Simulator longstep = new Simulator();// HERE
longstep.runLongSimulation();        
}
} 

我应该使用与生成按钮使用相同的对象方法。

但后来它演变成了另一个问题。。。如何让按钮的其余部分使用与生成按钮相同的对象方法,但又不再次生成字段?(我想这可能是个逻辑问题…(

我可能会问另一个问题。。。

最新更新