简体   繁体   中英

Memory issue/error in Java

Below is a method I have in an adventure game I am making in Java:

public static void characterDisperse(){

    int wRand = (int)(Math.random())*wModifiers.length;
    Item[] inv = new Item[1];
    inv[0]=new Item(wModifiers[wRand] + " " + wNames[(int)(Math.random()*wNames.length)],(int)(Math.random()*wModifiers.length)*2,1);
    for(int a=0;a<10;a++){
        for(int b=0;b<10;b++){
            if(Math.random()>0.5){ //density of characters
                charTest[a][b] = new Character(names[(int)(Math.random()*names.length)],(int)(Math.random()*5),(int)(Math.random()*3),(int)(Math.random()*15+5)*10,2,inv); 

                map[a][b].chars[1] = charTest[a][b];
                System.out.println(map[a][b].chars[1]);

            }
            else{
                map[a][b].passable = false;
            }


        }
    }
    for(int d=0;d<10;d++){
        for(int e=0;e<10;e++){
            System.out.println(map[d][e].chars[1]);
        }
    }

}

The problem I am having is that in the first double "for" loop, each character printed is a different character with all sorts of different attributes. However, when the second double "for" loop runs and prints out all of the characters I just created, it prints out all the same character, see below:

NAME: Moriah    RACE: 4 ALIGNMENT: 0    HEALTH: 130 SKILL: 2    INVENTORY: 1
NAME: Marge RACE: 1 ALIGNMENT: 0    HEALTH: 160 SKILL: 2    INVENTORY: 1
NAME: Faith RACE: 0 ALIGNMENT: 1    HEALTH: 50  SKILL: 2    INVENTORY: 1
NAME: Morton    RACE: 3 ALIGNMENT: 2    HEALTH: 60  SKILL: 2    INVENTORY: 1
NAME: Sherwood  RACE: 1 ALIGNMENT: 2    HEALTH: 50  SKILL: 2    INVENTORY: 1
NAME: Ezequiel  RACE: 2 ALIGNMENT: 1    HEALTH: 150 SKILL: 2    INVENTORY: 1
NAME: Herschel  RACE: 2 ALIGNMENT: 2    HEALTH: 70  SKILL: 2    INVENTORY: 1
NAME: Lester    RACE: 3 ALIGNMENT: 2    HEALTH: 80  SKILL: 2    INVENTORY: 1
NAME: Corinna   RACE: 2 ALIGNMENT: 0    HEALTH: 190 SKILL: 2    INVENTORY: 1

FIRST FOR LOOP ENDS HERE
SECOND FOR LOOP BEGINS

NAME: Corinna   RACE: 2 ALIGNMENT: 0    HEALTH: 190 SKILL: 2    INVENTORY: 1
NAME: Corinna   RACE: 2 ALIGNMENT: 0    HEALTH: 190 SKILL: 2    INVENTORY: 1
NAME: Corinna   RACE: 2 ALIGNMENT: 0    HEALTH: 190 SKILL: 2    INVENTORY: 1
NAME: Corinna   RACE: 2 ALIGNMENT: 0    HEALTH: 190 SKILL: 2    INVENTORY: 1
NAME: Corinna   RACE: 2 ALIGNMENT: 0    HEALTH: 190 SKILL: 2    INVENTORY: 1
NAME: Corinna   RACE: 2 ALIGNMENT: 0    HEALTH: 190 SKILL: 2    INVENTORY: 1
NAME: Corinna   RACE: 2 ALIGNMENT: 0    HEALTH: 190 SKILL: 2    INVENTORY: 1
NAME: Corinna   RACE: 2 ALIGNMENT: 0    HEALTH: 190 SKILL: 2    INVENTORY: 1

I believe it is some sort of memory issue where I set the character at map[a][b] (a location object) to the character in charTest[a][b]. charTest has already been instantiated earlier in the code.

map[][] is a 10x10 array of Location objects, and charTest[][] is a 10x10 array of Character objects:

Location.java:

import java.awt.*;
public class Location{

Character[] chars;
Feature[] features;
boolean passable;

public Location(Character[] chars, Feature[] features, boolean passable){
    this.chars = chars;
    this.features = features;
    this.passable = passable;
}

public String toString(){
    return "test";
}

public boolean containsChars(Location l){
    if(l.chars.length>0){
        return true;
    }
    else{
        return false;
    }
}

}

Character.java:

public class Character{
String name;  
int race;
int alignment;

int health;

int skill;

Item[] inventory;

public Character(String name,int race,int alignment,int health,int skill,Item[] inventory){
    this.name = name;
    this.race = race;
    this.alignment = alignment;
    this.health = health;
    this.skill = skill;
    this.inventory = inventory;
}


public String toString(){
    String printOut = "NAME: " + name + "\tRACE: " + race + "\tALIGNMENT: " + alignment + "\tHEALTH: " + health + "\tSKILL: " + skill + "\tINVENTORY: " + "1";
    return printOut;
}
}

In this line, you have to change the inv at the end to new Item[1]

charTest[a][b] = new Character(names[(int)(Math.random()*names.length)],(int)(Math.random()*5),(int)(Math.random()*3),(int)(Math.random()*15+5)*10,2,inv); 

So this line would do the job :

charTest[a][b] = new Character(names[(int)(Math.random()*names.length)],(int)(Math.random()*5),(int)(Math.random()*3),(int)(Math.random()*15+5)*10,2,new Item[1]);

The reason is, when you create array with this Item[] inv = new Item[1]; , the reference to this array is assigned to variable inv . Then if you assing the value inv to another variable you copy the reference .

It means that in your case, all Character objects have the same object.


You obviously have the same problem in your

map[a][b].chars[1]

When you create map[a][b] , you assing the same chars array to all fields in map .

Then you every time create new Character , you place him into the same chars array, which replace the old and prints it. Thats why you see new characters while generating them and thats why the last one is same in all the map variable.


When you generating initial data for map, you have to create new arrays for each Location, something like this :

for(int a=0;a<10;a++){
        for(int b=0;b<10;b++){
            map[a][b] = new Location(new Character[5], new Feature[5], true);
        }
}

PS : I would strongly recommend to use ArrayLists, instead of arrays.

Maybe you should try to rewrite your code in a way that anybody, including yourself, can understand it? If your code looks like this, it is no wonder that you get lost in it.

  • Variablenames like wRand and inv don't tell what they do
  • Split the Code-Blob in small methods and give them a good name
  • The Character Constructor call is insane. Refactor it and maybe apply the factory pattern
  • Create single Functions that do one thing, like randomizing Race, Name, Health, etc.
  • Use Collections instead of Arrays if possible
  • Don't use magic numbers all over your code.
  • Try to avoid an indentation level of 3 and nested loops

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM