This site requires JavaScript, please enable it in your browser!
Greenfoot back
Minion1
Minion1 wrote ...

2012/12/2

Nullpointer exception to nothing?

Minion1 Minion1

2012/12/2

#
I'm trying out my first attempt at designing a world via a text file. It's not going so well. Most of my code is copied from a friend's code, I'm trying to reverse engineer it, but I'm getting a nullpointer exception in a place that I didn't expect. Here is the code: import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) import java.io.*; import java.util.Scanner; import java.util.List; /** * Write a description of class TEST here. * * @author (your name) * @version (a version number or a date) */ public class TEST extends World { private static final int TILE_WIDTH = 50; private static final int TILE_HEIGHT = 50; private int leftX = TILE_WIDTH / 2; private int topY = TILE_HEIGHT / 2; private static final int MAP_HEIGHT = 4; private static final int MAP_WIDTH = 9; private List<Actor> list; /** * Constructor for objects of class TEST. * */ public TEST() { // Create a new world with 600x400 cells with a cell size of 1x1 pixels. super(600, 400, 1, false); readMapFile(); } public void readMapFile() { InputStream istream = getClass().getResourceAsStream("a.txt"); String textmap = new String; Scanner s = new Scanner(new BufferedReader(new InputStreamReader(istream))); for(int i = 0; i < textmap.length; i++) { while(s.hasNextLine()) { textmap = s.nextLine(); } } s.close(); addTiles(textmap); } private void addTiles(String THEMAP) { for(int x = 0; x < THEMAP.length; x++) { addColumn(x, THEMAP); } } private void addColumn(int x, String THEMAP) { int tileX = leftX + TILE_WIDTH * x; String column = THEMAP; for(int y = 0; y < column.length(); y++) //the error is occuring right here. { int tileY = topY + TILE_HEIGHT * y; char type = column.charAt(y); if(type == 'T') { addObject(new Tile(1), tileX, tileY); } if(type == 'F') { addObject(new Tile(2), tileX, tileY); } if(type == 'R') { addObject(new Tile(3), tileX, tileY); } if(type == 'r') { addObject(new Tile(4), tileX, tileY); } } } } I'm stumped. I can't figure out what the compiler is having trouble finding. It makes a reference to one other class, here is the code for that class: public class Tile extends Actor { public void act() { } public Tile() { setImage("tile0.png"); } public Tile(int x) { setImage("tile" + x + ".png"); } } And lastly, there are just four images in the images folder. tile1.png through tile4.png. I just need to know what the compiler is having trouble finding. Thanks!
Minion1 Minion1

2012/12/2

#
Oh, sorry, here is the stack trace. java.lang.NullPointerException at TEST.addColumn(TEST.java:63) at TEST.addTiles(TEST.java:54) at TEST.readMapFile(TEST.java:47) at TEST.<init>(TEST.java:31) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:525) at greenfoot.core.Simulation.newInstance(Simulation.java:578) at greenfoot.platforms.ide.WorldHandlerDelegateIDE$3.run(WorldHandlerDelegateIDE.java:408) at greenfoot.core.Simulation.runQueuedTasks(Simulation.java:465) at greenfoot.core.Simulation.maybePause(Simulation.java:279) at greenfoot.core.Simulation.runContent(Simulation.java:210) at greenfoot.core.Simulation.run(Simulation.java:203)
danpost danpost

2012/12/2

#
Try enclosing your 'for' loop in the 'addColumn' method in 'if (column!=null) { for { ... } }'. NOTE: Unless you are absolutely sure that all positions in the THEMAP array is supposed to contain a non-null element, the above would be the proper fix (if you have already counted the non-null elements, you could use that value instead of column.length).
Minion1 Minion1

2012/12/2

#
Nope haven't counted any non-null elements. Really I just honestly thought it would be as easy as, "Put this here, put this there." I was wrong. Really wrong. I'll try this.
Minion1 Minion1

2012/12/2

#
OH! You did it. Thank you. So, can you tell me exactly what I was doing wrong? I copy enough code, you know? I'm really trying to learn this stuff!
Minion1 Minion1

2012/12/2

#
I'm guessing that the compiler was looking for an element in the array that was returning null?
danpost danpost

2012/12/2

#
I am not too sure about the code in the 'readMapFile' method. The 'while' inside the 'for' loop looks suspicious (like maybe the 'while' was supposted to be an 'if'; or, the 'for' was not supposed to be there, but a incrementation of i (i++) within the 'while'). If you experience strange results after the changing from the previous post, try experimenting with this.
danpost danpost

2012/12/2

#
Your stack-trace was telling you that the line in question was giving a 'null' value. The only thing in that line that could possibly return 'null' was 'column', so only executing the code only when 'column != null' was the thing to do. The fact that 'null' values are being registered here tells us that the array was originally saved only with regard to the length of the array (without regard to whether the array was full of non-null elements). I guess another possibility is that you are reading in less lines of data than are in your array, or somehow not filling that array; and that may be a result of what I called suspicious code above.
Minion1 Minion1

2012/12/2

#
Thanks. I wish I could say that I understand it, but honestly I'm frustrated. When I look at code I see gibberish. It takes me a great deal of time to break it down, and then it doesn't work. Thanks. I'll work with it.
danpost danpost

2012/12/2

#
All programming is, is giving step-by-step instructions to the computer to accomplish whatever purpose you intend. Instead of relying on code produced by others, try writing your own. First write down the exact steps you want to happen to produce the effect you want. Then, figure out the simplest way to put those steps in code using the Java language and the methods provided therein (as well as in the greenfoot package). By the way, it is for this reason that familiarization with the methods provided (what they do and for what purposes they can be used) is so helpful. Let us look at your 'addColumn' method above. BRIEF DESCRIPTION: With a given x (the element number in the array) and a list of elements THEMAP (the array itself), use the specified element in the array to create the actors for one column of the world. Each character in the string represents the actor to add at each consecutive position along that column. MORE CORRECTLY: Given an array and and element number to a possible string within that array, if the element is not null, then for each character in that string determine the actor to add to the world at its position in the column. Just from that description, we can visualize the following
private void addColumn(int x, String[] THEMAP)
{
    String column=THEMAP[x];
    if(column==null)return; // cannot process null string
    int tileX=leftX+TILE_WIDTH*x; // this would be realized later; when you are adding the tile into the world
    for(int i=0; i<column.length(); i++)
Now, let us describe the conversion of characters in the string to the actual Tile type to create. You specified the following: 'T' = Tile(1) 'F' = Tile(2) 'R' = Tile(3) 'r' = Tile(4) The only differences on the right is the int that determines the Tile type. The easiest way to convert the characters into the int for the type of Tile is with int tileType="TFRr".indexOf(theCharacter)+1 As long as all the characters within the string must be one of the four listed above than the 'for' loop would become:
for(int i=0; i<column.length(); i++)addObject(new Tile("TFRr".indexOf(column.charAt(i))+1), tileX, topY+TILE_HEIGHT*y);
Always look for ways to improve the code; your extensive 'for' loop above was reduced to a one-liner by a little play of the methods provided; employing no decision-making, just doing. This makes the code easier to understand when you are reading it also as it keeps things simple. READING: for each character in the 'column' string, add the appropriate type Tile object to the world at the appropriate place (you can look at how the appropriate type of Tile is determined by more detailed inspection; however, that takes nothing away from the main action of the statement).
actinium actinium

2012/12/2

#
Just a guess but should the line
 String column = THEMAP[x];
be
 String[] column = THEMAP[x];
No sorry, ignore the above. On the design side i noticed readMapFile returns void, it would be better to return type String array , the map from the file in effect. Then any method that wanted the Data file in any project could use the method and the last line in the method could be moved to the world constructor with the readMapFile() method as a parameter.
You need to login to post a reply.