Processing - Array index out of bounds error - java

I'm trying to use an array of objects to have barrels fall from the top of the screen to the bottom. (Like that old donkey kong game.) However, I can't seem to find a way to create more instances of the object than whatever the initial length of the array was. Anyone know a way to do this?
Here's the code:
Man Man;
Man background;
Man ladders;
PFont font1;
int time;
boolean run;
boolean newBarrel;
int barrelTotal;
Barrel[] barrel = new Barrel[100];
void setup() {
newBarrel = false;
run = true;
barrelTotal = 1;
time = millis();
size(800, 800);
Man = new Man();
background = new Man();
ladders = new Man();
for (int i = 0; i < barrel.length; i++) {
barrel[i] = new Barrel();
}
}
void draw() {
if (run == true) {
for (int i = 0; i < barrel.length; i++) {
if ((Man.bottom-10 >= barrel[i].top)&&(Man.bottom-10 <= barrel[i].bottom)&&(Man.Ladder == barrel[i].randomLadder)) {
print("GAME OVER!");
run = false;
}
if ((Man.top >= barrel[i].top)&&(Man.top <= barrel[i].bottom)&&(Man.Ladder == barrel[i].randomLadder)) {
print("GAME OVER!");
run = false;
}
}
}
if (run == true) {
background.createBackground();
Man.ladders();
Man.movement();
Man.createMan();
//spawns a barrel every second
if (millis()> time + 10) {
newBarrel = false;
print(" " + barrelTotal + " ");
time = time + 10;
barrelTotal = barrelTotal+1;
newBarrel = true;
}
for (int i = 0; i < barrelTotal; i++) {
if (newBarrel == true) {
}
barrel[i].gravity();
barrel[i].createBarrel();
}
//if(barrelTotal == 100){
//for (int i = 0; i < 50; i++){
// barrel[i] = "???";
//}
//}
}
}

Use an ArrayList instead of a native array. ArrayList will expand capacity as needed, whereas an array is fixed size and cannot be changed (you'd need to create a new larger array each time, which under the covers is what an ArrayList handles for you).

You can use ArrayList for this. You will change
// from
Barrel[] barrel = new Barrel[100]; // i suggest naming it to barrels instead of barrel
// to
ArrayList<Barrel> barrel = new ArrayList<>();
// or better
List<Barrel> barrel = new ArrayList<>();
// from
for (int i = 0; i < barrel.length; i++) {
barrel[i] = new Barrel();
}
// to
for (int i = 0; i < barrel.length; i++) {
barrel.add(new Barrel());
}
// from
barrel[i].<some-method()/attribute>
// to
barrel.get(i).<some-method()/attribute>
// etc
I highly recommend this for getting started with lists
https://docs.oracle.com/javase/tutorial/collections/interfaces/list.html

Related

I need help making prims algorithm the way my instructor wants

So i have checked through the previously posted prims algorithm posts. and i cant find one that satisfies my teachers requirements. I worked on this code with him, and have it mostly working. however for somereason when it gets to a certian point, it breaks and goes to the wrong edge.
'''public int prims(T startVertex) {
int tempWeight = 0;
int championWeight = 0;
int totalWeight = 0;
int i = 0;
boolean firstOne = false;
T championVertex = null;
T currentVertex = null;
T checkVertex = null;
T championMarked = null;
UnboundedQueueInterface<T> vertexQueue = new LinkedUnbndQueue<T>();
clearMarks();
markVertex(startVertex);
currentVertex = startVertex;
do {
for (int y = 0; y < numVertices; y++) {
currentVertex = vertices[y];
if (isMarked(currentVertex)) {
championWeight = 0;
championVertex = null;
checkVertex = null;
firstOne = true;
vertexQueue = getToVertices(currentVertex);
while (!vertexQueue.isEmpty()) {
checkVertex = vertexQueue.dequeue();
if ((!(isMarked(checkVertex)))) {
tempWeight = weightIs(currentVertex, checkVertex);
if (championWeight > tempWeight || firstOne == true) {
championWeight = tempWeight;
championVertex = checkVertex;
championMarked = currentVertex;
firstOne = false;
}
}
}
}
}
System.out.println((String) championMarked + (String) championVertex + championWeight);
markVertex(championVertex);
totalWeight += championWeight;
} while (!(getUnmarked() == null));
System.out.println("Total cost is " + totalWeight);
return totalWeight; '''
when i run it i get the following output
Graph 1
AD1
DF4
FC3
FE12
FZ17
Enull0
the output is correct for the graph until the line FE12. it should be CE4. when i run debug, i watch the code find the answer, but then jumps up to the for loop and looses the right answer. I know there is an error in my logic, but I cant quite figure it out. Your input is appreciated. thanks
So i have figured out my issue, I needed to put the resets for the code, after the code outputs the solution, otherwise where they were, if there were any vertices left to check that were not used already, the code would loose the current values.
they needed to go here
'''System.out.println((String) championMarked + (String) championVertex +
championWeight);
markVertex(championVertex);
totalWeight += championWeight;
championWeight = 0;
championVertex = null;
checkVertex = null;
firstOne = true;
} while (!(getUnmarked() == null));'''

Android - An algorithm to check recursively if a map is solvable

I am making an android Hashikawekero puzzle game, I have implemented a algorithm to spawn nodes (Islands) at random positions using a 2-d array this works fine it creates the node at random position but most of the times the map cant be solved. The map nodes spawn at random.
BoardCreation.java Class - this generates the map.
package Island_and_Bridges.Hashi;
import android.annotation.TargetApi;
import android.os.Build;
import android.util.Log;
import java.util.Random;
import static junit.framework.Assert.*;
//This class Creates the map by random using a 2d array
public class BoardCreation {
// This class member is used for random initialization purposes.
static private final Random random = new Random();
// The difficulty levels.
private static final int EASY = 0;
static public final int MEDIUM = 1;
static public final int HARD = 2;
static public final int EMPTY = 0;
private static int ConnectionFingerprint(BoardElement start, BoardElement end) {
int x = start.row * 100 + start.col;
int y = end.row * 100 + end.col;
// Swap to get always the same fingerprint independent whether we are called
// start-end or end-start
if (x > y ) {
int temp = x;
x = y;
y = temp;
}
Log.d("", String.format("%d %d" , x ,y));
return x ^ y;
}
public class State {
// The elements of the board are stored in this array.
// A value defined by "EMPTY" means that its not set yet.
public BoardElement [][] board_elements = null;
public int [][] cell_occupied = null;
// The width of the board. We only assume squared boards.
public int board_width=0;
public State(int width) {
board_width = width;
board_elements = new BoardElement[width][width];
cell_occupied = new int[width][width];
}
public State CloneWithoutConnections() {
State newstate = new State(board_width);
if (board_elements != null) {
newstate.board_elements = new BoardElement[board_elements.length][board_elements.length];
for (int i = 0; i < board_elements.length; ++i) {
for (int j = 0; j < board_elements.length; ++j) {
if (board_elements[i][j] == null)
continue;
newstate.board_elements[i][j] = board_elements[i][j].clone();
}
}
}
if (cell_occupied != null) {
assert board_elements != null;
newstate.cell_occupied = new int[board_elements.length][board_elements.length];
for (int i = 0; i < board_elements.length; ++i) {
System.arraycopy(cell_occupied[i], 0, newstate.cell_occupied[i], 0, board_elements.length);
}
}
return newstate;
}
public void AddToBridgeCache(BoardElement first, BoardElement second) {
if (first == null || second == null) { return; }
final int fingerprint = ConnectionFingerprint(first, second);
Log.d(getClass().getName(),
String.format("Fingerprint of this bridge %d", fingerprint));
// mark the end points as occupied.
cell_occupied[first.row][first.col] = fingerprint;
cell_occupied[second.row][second.col] = fingerprint;
int dcol = second.col - first.col;
int drow = second.row - first.row;
if (first.row == second.row) {
for (int i = (int) (first.col + Math.signum(dcol)); i != second.col; i += Math.signum(dcol)) {
cell_occupied[first.row][i] = fingerprint;
String.format("deleting bridge");
}
} else {
assert first.col == second.col;
for (int i = (int) (first.row + Math.signum(drow)); i != second.row; i+= Math.signum(drow)) {
cell_occupied[i][first.col] = fingerprint;
}
}
}
} // end of state
private State current_state, old_state;
static private final int WIDTH_EASY = 7;
private void NewGame(int hardness) {
switch(hardness) {
case EASY:
Log.d(getClass().getName(), "Initializing new easy game");
InitializeEasy();
old_state = getCurrentState().CloneWithoutConnections();
break;
}
}
public void ResetGame() {
if (old_state != null) {
Log.d(getClass().getName(), "Setting board_elements to old_elements");
setCurrentState(old_state.CloneWithoutConnections());
} else {
Log.d(getClass().getName(), "old_lements are zero");
}
}
public BoardCreation(int hardness) {
NewGame(hardness);
}
public boolean TryAddNewBridge(BoardElement start, BoardElement end, int count) {
assertEquals(count, 1);
assert (start != null);
assert (end != null);
final int fingerprint = ConnectionFingerprint(start, end);
Log.d(getClass().getName(),
String.format("considering (%d,%d) and (%d,%d)", start.row,start.col, end.row,end.col));
if (start.row == end.row && start.col == end.col) {
Log.d(getClass().getName(), "Same nodes selected!");
return false;
}
assert count > 0;
int dcol = end.col - start.col;
int drow = end.row - start.row;
// It must be a vertical or horizontal bridge:
if (Math.abs(dcol) > 0 && Math.abs(drow) > 0) {
Log.d(getClass().getName(), "not a horizontal or vertical bridge.");
return false;
}
// First we check whether start and end elements can take the specified bridge counts.
int count_start = start.GetCurrentCount();
int count_end = end.GetCurrentCount();
if (count_start + count > start.max_connecting_bridges ||
count_end + count > end.max_connecting_bridges) {
Log.d(getClass().getName(), "This Bridge is not allowed");
return false;
}
Log.d(getClass().getName(),
String.format("Sums:%d # (%d,%d) and %d # (%d,%d)",
count_start, start.row, start.col,
count_end, end.row, end.col));
Connection start_connection = null;
Connection end_connection = null;
// Next we check whether we are crossing any lines.
if (start.row == end.row) {
for (int i = (int) (start.col + Math.signum(dcol)); i != end.col; i += Math.signum(dcol)) {
if (getCurrentState().cell_occupied[start.row][i] > 0 &&
getCurrentState().cell_occupied[start.row][i] != fingerprint) {
Log.d(getClass().getName(), "Crossing an occupied cell.");
return false;
}
}
assert start.col != end.col;
if (start.col > end.col) {
start.connecting_east = GetOrCreateConnection(end, start.connecting_east);
end.connecting_west = GetOrCreateConnection(start, end.connecting_west);
start_connection = start.connecting_east;
end_connection = end.connecting_west;
} else {
start.connecting_west = GetOrCreateConnection(end, start.connecting_west);
end.connecting_east = GetOrCreateConnection(start, end.connecting_east);
start_connection = start.connecting_west;
end_connection = end.connecting_east;
}
} else {
assert start.col == end.col;
for (int i = (int) (start.row + Math.signum(drow)); i != end.row ; i += Math.signum(drow)) {
if (getCurrentState().cell_occupied[i][start.col] > 0 &&
getCurrentState().cell_occupied[i][start.col] != fingerprint) {
Log.d(getClass().getName(), "Crossing an occupied cell.");
return false;
}
}
if (start.row > end.row ) {
start.connecting_north = GetOrCreateConnection(end, start.connecting_north);
end.connecting_south = GetOrCreateConnection(start, end.connecting_south);
start_connection = start.connecting_north;
end_connection = end.connecting_south;
} else {
start.connecting_south= GetOrCreateConnection(end, start.connecting_south);
end.connecting_north = GetOrCreateConnection(start, end.connecting_north);
start_connection = start.connecting_south;
end_connection = end.connecting_north;
}
}
start_connection.destination = end;
end_connection.destination = start;
start_connection.second += count;
end_connection.second += count;
getCurrentState().AddToBridgeCache(start, end);
Log.d(getClass().getName(),
String.format("New bridge added. Sums:%d # (%d,%d) and %d # (%d,%d)",
count_start, start.row,start.col,
count_end, end.row,end.col));
return true;
}
private Connection GetOrCreateConnection(
BoardElement end,
Connection connection) {
if (connection!= null) { return connection; }
return new Connection();
}
#TargetApi(Build.VERSION_CODES.N)
private void InitializeEasy() {
Random rand = new Random();
String[][] debug_board_state = new String[7][7];
setCurrentState(new State(WIDTH_EASY));
for (int row = 0; row < debug_board_state.length; row++) {
for (int column = 0; column < debug_board_state[row].length; column++) {
debug_board_state[row][column] = String.valueOf(rand.nextInt(5));
}
}
for (int row = 0; row < debug_board_state.length; row++) {
for (int column = 0; column < debug_board_state[row].length; column++) {
System.out.print(debug_board_state[row][column] + " ");
}
System.out.println();
}
for (int row = 0; row < WIDTH_EASY; ++row) {
for (int column = 0; column < WIDTH_EASY; ++column) {
getCurrentState().board_elements[row][column] = new BoardElement();
getCurrentState().board_elements[row][column].max_connecting_bridges = Integer.parseInt(debug_board_state[row][column]);
getCurrentState().board_elements[row][column].row = row;
getCurrentState().board_elements[row][column].col = column;
if (getCurrentState().board_elements[row][column].max_connecting_bridges > 0) {
getCurrentState().board_elements[row][column].is_island = true;
}
}
}
}
private void setCurrentState(State new_state) {
this.current_state = new_state;
}
public State getCurrentState() {
return current_state;
}
}
What algorithm could I use to make sure the Map can be Solved (Islands Connected with Bridges) before spawning the nodes.
This is what the map looks like (don't mind the design)
One thing to consider would be to start with a blank board. Place an island. Then place another island that can be connected to the first one (i.e. on one of the four cardinal directions). Connect the two with a bridge, and increment each island's count.
Now, pick one of the two islands and place another island that it can connect. Add the bridge and increment.
Continue in this way until you've placed the number of islands that you want to place.
The beauty here is that you start with an empty board, and during construction the board is always valid.
You'll have to ensure that you're not crossing bridges when you place new islands, but that's pretty easy to do, since you know where the existing bridges are.

Memory game does not call compare function correctly

I have coded a simple memory game. Card values are added to two arrays and after that, a compare function is called. But there is a problem with the logic of the compare function.
The specific problem seems related to the fact that the compare function is called on the third button click. So on first click it adds first value to first array , on second click second value to second array. But I must click for yet a third time to call the compare function to compare the match of two arrays.
The main problem is that after all cards are inverted (10 matches in 5x4 memory game), it does not show the result.
I have uploaded full code here : http://uloz.to/xcsJkYUK/memory-game-rar .
public class PEXESO5x4 extends JFrame implements ActionListener {
private JButton[] aHracieTlactika = new JButton[20];
private ArrayList<Integer> aHodnoty = new ArrayList<Integer>();
private int aPocitadlo = 1;
private int[] aTlacitkoIden = new int[2];
private int[] aHodnotaTlac = new int[2];
private JButton aTlacitkoExit;
private JButton aTlacitkoReplay;
private JButton[] aHracieTlacitko = new JButton[20];
private int aPocetTahov = 0;
public void vkladanieHodnot() {
for (int i = 0; i < 2; i++) {
for (int j = 1; j < (this.aHracieTlactika.length / 2) + 1; j++) {
this.aHodnoty.add(j);
}
}
Collections.shuffle(this.aHodnoty);
}
public boolean zhoda() {
if (this.aHodnotaTlac[0] == this.aHodnotaTlac[1]) {
return true;
}
return false;
}
public void zapisCislaDoSuboru() {
try(PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("Semestralka.txt", true)))) {
out.println("haha");
//more code
out.println("hahahahha");
//more code
}catch (IOException e) {
//exception handling left as an exercise for the reader
}
}
public void actionPerformed(ActionEvent e) {
int match = 0;
if (this.aTlacitkoExit == e.getSource()) {
System.exit(0);
}
if (this.aTlacitkoReplay == e.getSource()) {
}
for (int i = 0; i < this.aHracieTlactika.length; i++) {
if (this.aHracieTlactika[i] == e.getSource()) {
this.aHracieTlactika[i].setText("" + this.aHodnoty.get(i));
this.aHracieTlactika[i].setEnabled(false);
this.aPocitadlo++;
this.aPocetTahov += 1;
if (this.aPocitadlo == 3) {
if (this.zhoda()) {
match+=1;
if (match==10)
{
System.out.println("You win");
}
this.aHracieTlactika[this.aTlacitkoIden[0]].setEnabled(false);
this.aHracieTlactika[this.aTlacitkoIden[1]].setEnabled(false);
} else {
this.aHracieTlactika[this.aTlacitkoIden[0]].setEnabled(true);
this.aHracieTlactika[this.aTlacitkoIden[0]].setText("");
this.aHracieTlactika[this.aTlacitkoIden[1]].setEnabled(true);
this.aHracieTlactika[this.aTlacitkoIden[1]].setText("");
}
this.aPocitadlo = 1;
}
if (this.aPocitadlo == 1) {
this.aTlacitkoIden[0] = i;
this.aHodnotaTlac[0] = this.aHodnoty.get(i);
}
if (this.aPocitadlo == 2) {
this.aTlacitkoIden[1] = i;
this.aHodnotaTlac[1] = this.aHodnoty.get(i);
}
}
}
}
}

Why do object arrays in my ArrayList fail to retain their values?

I am creating a program in Java to simulate evolution. The way I have it set up, each generation is composed of an array of Organism objects. Each of these arrays is an element in the ArrayList orgGenerations. Each generation, of which there could be any amount before all animals die, can have any amount of Organism objects.
For some reason, in my main loop when the generations are going by, I can have this code without errors, where allOrgs is the Organism array of the current generation and generationNumber is the number generations since the first.
orgGenerations.add(allOrgs);
printOrgs(orgGenerations.get(generationNumber));
printOrgs is a method to display an Organism array, where speed and strength are Organism Field variables:
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 + ".");
}
}
Later on, after this loop, when I am trying to retrieve the data to display, I call this very similar code:
printOrgs(orgGenerations.get(0));
This, and every other array in orgGenerations, return a null pointer exception on the print line of the for loop. Why are the Organism objects loosing their values?
Alright, here is all of the code from my main Simulation class. I admit, it might be sort of a mess. The parts that matter are the start and simulator methods. The battle ones are not really applicable to this problem. I think.
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);
}
}
}
Main method:
public class Runner {
public static void main(String[] args) throws InterruptedException {
Simulator sim = new Simulator();
int lifeSpan = 20;
sim.start(lifeSpan);
sim.graphOrgs();
}
}
Organism class:
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;
}
}
The problem lies in the graphOrgs class when I try to print to check if it is working in preparation for graphing the results. This is when it returns the error. When I try placing the print code in other places in the Simulator class the same thing occurs, a null pointer error. This happens even if it is just after the for loop where the element has been established.
You have code that sets to null elements in your allOrgs array.
allOrgs[partner1] = null;
allOrgs[partner2] = null;
Your orgGenerations list contains the same allOrgs instance multiple times.
Therefore, when you write allOrgs[partner1] = null, the partner1'th element becomes null in all the list elements of orgGenerations, which is why the print method fails.
You should create a copy of the array (you can use Arrays.copy) each time you add a new generation to the list (and consider also creating copies of the Organism instances, if you want each generation to record the past state of the Organisms and not their final state).

Why is this Array getting modified? [duplicate]

This question already has answers here:
How to clone a multidimensional array in java? [duplicate]
(2 answers)
Closed 8 years ago.
I have an array called maze which in, theory, should get modified only in the updateMaze() method. This is because that is the final result I want to output to the console. The problem is when tempMaze gets modified maze is modified as well. This is not supposed to happen. My first thought was that they are pointing to same reference in memory however I checked and that is false. I do have to mention I used clone() at initialization to make their contents similar, and I am not sure if this could be a issue or not. (Even though I think I understand what clone() does I am not familiar enough to know if it is the problem or not.) My code:
public class ThreadTheMaze {
ArrayList<Cell> result = new ArrayList<Cell>();
private String[][] maze;
private String[][] tempMaze;
private int initRowPosition;
private int initColPosition;
private int amtOfRows;
private int amtOfCols;
public ThreadTheMaze(int initRow, int initCol){
initRowPosition = initRow;
initColPosition = initCol;
result.add(new Cell(initRowPosition, initColPosition));
}
public void loadMaze(){
try{
Scanner in = new Scanner(new File("mazeData.txt"));
while (in.hasNextLine()){
amtOfCols = in.nextLine().length();
amtOfRows++;
}
in.close();
maze = new String[amtOfRows][amtOfCols];
in = new Scanner(new File("mazeData.txt"));
for (int r = 0; r < amtOfRows; r++){
String line = in.nextLine();
for (int c = 0; c < amtOfCols; c++){
maze[r][c] = line.substring(0,1);
line = line.substring(1);
}
}
tempMaze = maze.clone();
}catch (FileNotFoundException e){
System.err.print(e);
}
}
public void printMaze(){
for (int r = 0; r < amtOfRows; r++){
for (int c = 0; c < amtOfCols; c++){
System.out.print(maze[r][c]);
}
System.out.println();
}
}
public void updateMaze(){
for (int i = 0; i < result.size(); i++){
maze[result.get(i).getRow()][result.get(i).getColumn()] = "!";
}
}
/**
#return ArrayList of objects 'Cell' that are the solution to the maze. (Note: if no solution then returns empty ArrayList)
*/
public void solve(Cell cell){
tempMaze[cell.getRow()][cell.getColumn()] = "!";
ArrayList<Cell> neighbors = getNeighbors(cell);
if ((cell.getRow() == 0 || cell.getRow() == tempMaze.length-1) || (cell.getColumn() == 0 || cell.getColumn() == tempMaze[0].length-1)){
return;
}
if ((cell.getColumn() == initColPosition && cell.getRow() == initRowPosition) && neighbors.size() < 1){
return;
}
// If not in init position and has no neighbors then backtrack
if ((cell.getColumn() != initColPosition || cell.getRow() != initRowPosition) && neighbors.size() < 1){
result.remove(result.size()-1);
solve(result.get(result.size()-1));
}else if (neighbors.size() >= 1){ // If has neighbors then choose one and call the method again
result.add(neighbors.get(0));
solve(neighbors.get(0));
}
}
/**
#return ArrayList of objects 'Cell' that are empty and available to move to.
*/
private ArrayList<Cell> getNeighbors(Cell cell){
ArrayList<Cell> neighbors = new ArrayList<Cell>();
int row = cell.getRow();
int column = cell.getColumn();
int[][] moveLocs = {{row-1, column}, {row+1, column}, {row, column+1}, {row, column-1}};
for (int r = 0; r < moveLocs.length; r++){
int tRow = moveLocs[r][0];
int tCol = moveLocs[r][1];
if (isValid(tRow, tCol)){
Cell neighbor = new Cell(tRow, tCol);
neighbors.add(neighbor);
}
}
return neighbors;
}
public boolean isValid(int row, int col){
if(row < 0 || row >= amtOfRows){
return false;
}
if (col < 0 || col >= amtOfCols){
return false;
}
if (!tempMaze[row][col].equals(" ")){
return false;
}
return true;
}
}
The class Cell is a simple class with some simple get and set method.
I know this isn't the most concise way to present you my question, but really I can't spot a place were the problem could exist. Thanks.
clone() is shallow. This means that the following:
tempMaze = maze.clone();
only clones the first level of the 2D array. In other words, you get a new array containing the same String[] references as the original array.
For suggestions on how to fix this, see How do I do a deep copy of a 2d array in Java?

Categories