我正在用Java创建一个程序来模拟进化。我设置它的方式,每一代都由一系列有机体对象组成。这些数组中的每一个都是ArrayList orgGenerations中的元素。在所有动物死亡之前可能有任何数量的每一代都可以拥有任何数量的生物体。
出于某种原因,在我的主循环中,当代数经过时,我可以使这个代码没有错误,其中allOrgs是当前一代的Organism数组,而generationNumber是自第一代以来的数字代。
orgGenerations.add(allOrgs);
printOrgs(orgGenerations.get(generationNumber));
printOrgs是一种显示有机体数组的方法,其中速度和强度是有机体场变量:
public void printOrgs(Organism[] list)
{
for (int x=0; x<list.length; x++)
{
System.out.println ("For organism number: " + x + ", speed is: " + list[x].speed + ", and strength is " + list[x].strength + ".");
}
}
稍后,在此循环之后,当我尝试检索要显示的数据时,我称之为非常相似的代码:
printOrgs(orgGenerations.get(0));
这个以及orgGenerations中的每个其他数组都会在for循环的打印行上返回一个空指针异常。为什么有机体会失去他们的价值?
好的,这是我的主要Simulation类的所有代码。我承认,这可能有点混乱。重要的部分是开始和模拟器方法。战斗力并不适用于这个问题。我想。
import java.awt.FlowLayout;
import java.util.*;
import javax.swing.JFrame;
public class Simulator {
//variables for general keeping track
static Organism[] allOrgs;
static ArrayList<Organism[]> orgGenerations = new ArrayList <Organism[]>();
ArrayList<Integer> battleList = new ArrayList<Integer>();
int deathCount;
boolean done;
boolean runOnce;
//setup
Simulator()
{
done = false;
Scanner asker = new Scanner(System.in);
System.out.println("Input number of organisms for the simulation: ");
int numOfOrgs = asker.nextInt();
asker.close();
Organism[] orgArray = new Organism[numOfOrgs];
for (int i=0; i<numOfOrgs; i++)
{
orgArray[i] = new Organism();
}
allOrgs = orgArray;
}
//graphsOrgs
public void graphOrgs() throws InterruptedException
{
JFrame f = new JFrame("Evolution");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(1000,500);
f.setVisible(true);
Drawer bars = new Drawer();
//System.out.println(orgGenerations.size());
for (int iterator=0;iterator<(orgGenerations.size()-1); iterator++)
{
printOrgs(orgGenerations.get(0));
//The 0 can be any number, no matter what I do it wont work
//System.out.println("first");
f.repaint();
bars.data = orgGenerations.get(iterator);
f.add(bars);
//System.out.println("before");
Thread.sleep(1000);
//System.out.println("end");
}
}
//prints all Orgs and their statistics
public void printOrgs(Organism[] list)
{
System.out.println("Number Of Organisms: " + list.length);
for (int x=0; x<list.length; x++)
{
System.out.println ("For organism number: " + x + ", speed is: " + list[x].speed + ", and strength is " + list[x].strength + ".");
}
System.out.println();
}
//general loop for the organisms lives
public void start(int reproductionTime) throws InterruptedException
{
int generationNumber = 0;
orgGenerations.add(allOrgs);
printOrgs(orgGenerations.get(0));
generationNumber++;
while(true)
{
deathCount = 0;
for(int j=0; j<reproductionTime; j++)
{
battleList.clear();
for(int m=0; m<allOrgs.length; m++)
{
if (allOrgs[m].alive == true)
oneYearBattleCheck(m);
}
battle();
}
reproduction();
if (done == true)
break;
orgGenerations.add(allOrgs);
printOrgs(orgGenerations.get(generationNumber));
generationNumber++;
}
printOrgs(orgGenerations.get(2));
}
//Checks if they have to fight this year
private void oneYearBattleCheck(int m)
{
Random chaos = new Random();
int speedMod = chaos.nextInt(((int)Math.ceil(allOrgs[m].speed/5.0))+1);
int speedSign = chaos.nextInt(2);
if (speedSign == 0)
speedSign--;
speedMod *= speedSign;
int speed = speedMod + allOrgs[m].speed;
if (speed <= 0)
speed=1;
Random encounter = new Random();
boolean battle = false;
int try1 =(encounter.nextInt(speed));
int try2 =(encounter.nextInt(speed));
int try3 =(encounter.nextInt(speed));
int try4 =(encounter.nextInt(speed));
if (try1 == 0 || try2 == 0 || try3 == 0 || try4 == 0 )
{
battle = true;
}
if(battle == true)
{
battleList.add(m);
}
}
//Creates the matches and runs the battle
private void battle()
{
Random rand = new Random();
if (battleList.size()%2 == 1)
{
int luckyDuck = rand.nextInt(battleList.size());
battleList.remove(luckyDuck);
}
for(int k=0; k<(battleList.size()-1);)
{
int competitor1 = rand.nextInt(battleList.size());
battleList.remove(competitor1);
int competitor2 = rand.nextInt(battleList.size());
battleList.remove(competitor2);
//Competitor 1 strength
int strengthMod = rand.nextInt(((int)Math.ceil(allOrgs[competitor1].strength/5.0))+1);
int strengthSign = rand.nextInt(2);
if (strengthSign == 0)
strengthSign--;
strengthMod *= strengthSign;
int comp1Strength = strengthMod + allOrgs[competitor1].strength;
//Competitor 2 strength
strengthMod = rand.nextInt(((int)Math.ceil(allOrgs[competitor2].strength/5.0))+1);
strengthSign = rand.nextInt(2);
if (strengthSign == 0)
strengthSign--;
strengthMod *= strengthSign;
int comp2Strength = strengthMod + allOrgs[competitor2].strength;
//Fight!
if (comp1Strength>comp2Strength)
{
allOrgs[competitor1].life ++;
allOrgs[competitor2].life --;
}
else if (comp2Strength>comp1Strength)
{
allOrgs[competitor2].life ++;
allOrgs[competitor1].life --;
}
if (allOrgs[competitor1].life == 0)
{
allOrgs[competitor1].alive = false;
deathCount++;
}
if (allOrgs[competitor2].life == 0)
{
allOrgs[competitor2].alive = false;
deathCount ++ ;
}
}
}
//New organisms
private void reproduction()
{
//System.out.println("Number of deaths: " + deathCount + "\n");
if (deathCount>=(allOrgs.length-2))
{
done = true;
return;
}
ArrayList<Organism> tempOrgs = new ArrayList<Organism>();
Random chooser = new Random();
int count = 0;
while(true)
{
int partner1 = 0;
int partner2 = 0;
boolean partnerIsAlive = false;
boolean unluckyDuck = false;
//choose partner1
while (partnerIsAlive == false)
{
partner1 = chooser.nextInt(allOrgs.length);
if (allOrgs[partner1] != null)
{
if (allOrgs[partner1].alive == true)
{
partnerIsAlive = true;
}
}
}
count++;
//System.out.println("Count 2: " + count);
partnerIsAlive = false;
//choose partner2
while (partnerIsAlive == false)
{
if (count+deathCount == (allOrgs.length))
{
unluckyDuck=true;
break;
}
partner2 = chooser.nextInt(allOrgs.length);
if (allOrgs[partner2] != null)
{
if (allOrgs[partner2].alive == true)
{
partnerIsAlive = true;
}
}
}
if (unluckyDuck == false)
count++;
//System.out.println("count 2: " + count);
if (unluckyDuck == false)
{
int numOfChildren = (chooser.nextInt(4)+1);
for (int d=0; d<numOfChildren; d++)
{
tempOrgs.add(new Organism(allOrgs[partner1].speed, allOrgs[partner2].speed, allOrgs[partner1].strength, allOrgs[partner2].strength ));
}
allOrgs[partner1] = null;
allOrgs[partner2] = null;
}
if (count+deathCount == (allOrgs.length))
{
Arrays.fill(allOrgs, null);
allOrgs = tempOrgs.toArray(new Organism[tempOrgs.size()-1]);
break;
}
//System.out.println(count);
}
}
}
主要方法:
public class Runner {
public static void main(String[] args) throws InterruptedException {
Simulator sim = new Simulator();
int lifeSpan = 20;
sim.start(lifeSpan);
sim.graphOrgs();
}
}
有机体类:
import java.util.Random;
public class Organism {
static Random traitGenerator = new Random();
int life;
int speed;
int strength;
boolean alive;
Organism()
{
speed = (traitGenerator.nextInt(49)+1);
strength = (50-speed);
life = 5;
alive = true;
}
Organism(int strength1, int strength2, int speed1, int speed2)
{
Random gen = new Random();
int speedMod = gen.nextInt(((int)Math.ceil((speed1+speed2)/10.0))+1);
int speedSign = gen.nextInt(2);
if (speedSign == 0)
speedSign--;
speedMod *= speedSign;
//System.out.println(speedMod);
int strengthMod = gen.nextInt(((int)Math.ceil((strength1+strength2)/10.0))+1);
int strengthSign = gen.nextInt(2);
if (strengthSign == 0)
strengthSign--;
strengthMod *= strengthSign;
//System.out.println(strengthMod);
strength = (((int)((strength1+strength2)/2.0))+ strengthMod);
speed = (((int)((speed1+speed2)/2.0))+ speedMod);
alive = true;
life = 5;
}
}
问题在于graphOrgs类,当我尝试打印以检查它是否正在准备绘制结果时。这是它返回错误的时候。当我尝试将打印代码放在Simulator类的其他位置时,会发生同样的事情,一个空指针错误。即使它刚好在已经建立元素的for循环之后也会发生这种情况。
答案 0 :(得分:1)
您的代码设置为allOrgs
数组中的null元素。
allOrgs[partner1] = null;
allOrgs[partner2] = null;
您的orgGenerations
列表多次包含相同的allOrgs
个实例。
因此,当您编写allOrgs[partner1] = null
时,partner1
元素在orgGenerations
的所有列表元素中都变为空,这就是打印方法失败的原因。
每次向列表中添加新一代时,都应创建数组的副本(可以使用Arrays.copy
)(如果需要,还可以考虑创建Organism
个实例的副本生成以记录Organism
的过去状态而不记录其最终状态。