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

2014/6/5

Use var from method in act() in world class

1
2
3
mrunknown mrunknown

2014/6/5

#
Hi, i have a problem with my greenfoot simulation. In my world class ("plane") i'm using the method createSeats() to create the world. The variables/arrays (sitze, S, AReihen, sitzeArray, freieSitze, r) created in createSeats() are used in the method act() of the same class in which i want to spawning my actors when the simluation runs. When compiling it gives a "cannot find symbol" error due to the fact the variables can't be accessed from another method in the same class i guess. Putting act() into public Plane() wouldn't work too because then it would start itself i guess...
public Plane()
    {    
        super(3+3+1, 20, 32);
        setBackground("tile.png");
        createSeats(3, 20);
        ID = 0;
    }

public void createSeats(int S, int AReihen)
    {
        int ASitze = (S+S) * AReihen;
        sitze = new int[ASitze*3];
        int[] sitzeArray = new int[ASitze];
        int r;
        int freieSitze = ASitze;
        Random generator = new Random();
        for (int i=0;i<ASitze;i++) {
            sitzeArray[i]=i;
        }
        
        System.out.println("Seats (ID|y|x)");
        for (int cnt1 = 0; cnt1 < AReihen; cnt1++)
        { 
            for (int cnt2 = 0; cnt2 < S+S + 1 ; cnt2++)
            {
               if (cnt2 != S)
               {
                    int x = cnt2;
                    int y = cnt1;
                    Seat seat = new Seat();
                    addObject(seat, x, y);
             
                    sitze[ID*3]=ID; // Array Zugriff
                    sitze[ID*3+1]=y;
                    sitze[ID*3+2]=x;
                    System.out.println("id_" + sitze[ID*3] + " ( " + sitze[ID*3+1] + " | " + sitze[ID*3+2] + " )");
                    ID++;
               } 
            }  
        }
}
Thanks in advance!!
danpost danpost

2014/6/5

#
Please show the entire class code. It is almost impossible to help without seeing how the fields are being declared and used. Also, copy/paste the entire error message you are getting and indicate where any highlights may be due to the error. It would be best if you re-compile, create the error then copy/paste the message and the code into your post.
mrunknown mrunknown

2014/6/6

#
Ok, sorry, here it comes:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.ArrayList;
import java.util.Random;

public class Plane extends World
{       
   private int ID;
   private int[] sitze;


    public Plane()
    {    
        super(3+3+1, 20, 32); // 3+3 and 20 will later be replaced with input variables
        setBackground("tile.png");
        createSeats(3, 20); // same here, s.a.
        ID = 0;
    }
    

    public void createSeats(int S, int AReihen)
    {
        int ASitze = (S + S) * AReihen;
        sitze = new int[ASitze*3];
        int[] sitzeArray = new int[ASitze];
        int r;
        int freieSitze = ASitze;
        Random generator = new Random();        
              
        for (int i=0;i<ASitze;i++) {
            sitzeArray[i]=i;
        }
        
        System.out.println("Seats (ID|y|x)");
        for (int cnt1 = 0; cnt1 < AReihen; cnt1++)
        { 
            for (int cnt2 = 0; cnt2 < S+S + 1 ; cnt2++)
            {
               if (cnt2 != S)
               {
                    int x = cnt2;
                    int y = cnt1;
                    Seat seat = new Seat();
                    addObject(seat, x, y);
             
                    sitze[ID*3]=ID; // Array Zugriff
                    sitze[ID*3+1]=y;
                    sitze[ID*3+2]=x;
                    System.out.println("id_" + sitze[ID*3] + " ( " + sitze[ID*3+1] + " | " + sitze[ID*3+2] + " )");
                    ID++;
               } 
            }  
        }
    }
    
 
    public void act()
    {
        int ASitze = (S + S) * AReihen;
        sitze = new int[ASitze*3];
        int[] sitzeArray = new int[ASitze];
        int r;
        int freieSitze = ASitze;
        Random generator = new Random();
        
        //spawn passengers
        for (int cnt1 = 0; cnt1 < AReihen; cnt1++)
        { 
            for (int cnt2 = 0; cnt2 < S+S + 1; cnt2++)
            {
               if (cnt2 != S)
               {

                   r = generator.nextInt(freieSitze);
       
                   for (int j = r; j < freieSitze-1; j++)
                   {  
                      sitzeArray[j]=sitzeArray[j+1];
                   }
                 
                   freieSitze--;
                                            
                   if (cnt1 < 2)
                   {
                       System.out.println("[");
                       for (int kkkk = 0; kkkk < ASitze; kkkk++)
                       {
                           System.out.print(sitzeArray[kkkk]+"|");
                       }
                       System.out.println("");
                   }
                                     
                   Passenger passenger = new Passenger(sitze[sitzeArray[r]*3+2], sitze[sitzeArray[r]*3+1]); //get x and y
                   addObject(passenger,S,0); // spawn passenger into aisle
               
               }
            }  
        }
    }
}
Error message:
cannot find symbol - variable S
You are using a symbol here that has not been declared [...]
The whole code in act() was placed in createSeats() in the first place. But then i decided to put it in act() because i dont want that all Passenger-Objects appear from the start on. They're supposed to wait until the previous Passenger is more than x Fields away on the map.
danpost danpost

2014/6/6

#
You should probably have fields for the number of rows and seats per row on a side (S and Areihen). As these will not change for any Plane object (world), they can be 'static final int' fields. Use the field names in the 'super' constructor call. The method 'createSeats' will not need those values passed to it. The 'act' method will have access to those fields. It would be better, instead of having an array for 'ID/x/y' values to just have each Seat object hold its ID value by way of an instance field in its class; the Seat objects will know where they are located in the world by way of its hidden x and y fields supplied by the Actor class. The Seat class could also have an instance boolean field to indicate whether it is assigned to a passenger or not.
mrunknown mrunknown

2014/6/6

#
Great, thank you! Works fine :)
public class Plane extends World
{  
   // ....
   private static final int S = 3;
   private static final int AReihen = 20;
   // ...
   public Plane()
    {    
        super(S + S + 1, AReihen, 32);
        setBackground("tile.png");
        createSeats();
        ID = 0;
    }
But is there any way of making an input for Plane where I can set S and AReihen manually? Or is it impossible because they have to be "static final int" fields? I also wonder how i can access the instance fields of the Seat class (ID/is_assigned/x/y) from the Plane object to connect the Passenger objects to the Seat objects and let the passengers walk to their seats. In my mind i first have to find a way to differ the Seats by their ID but i don't really have found a solution yet.
danpost danpost

2014/6/6

#
You can add another constructor to the Plane class (in addition to the one that is already there):
// add this constructor
public Plane(int run, int rows)
{
    super(2*run+1, rows, 32);
    S = run;
    AReihen = rows;
    setBackground("tile.png");
    createSeats();
    ID = 0;
}
// you can change your other constructor to this as well
public Plane()
{
    this(S, AReihen, 32);
}
This avoids duplicate coding. You will need to remove 'final' from the 'S' and 'Areihen' field declarations. What does your seat class look like?
danpost danpost

2014/6/6

#
Will you ever have co-existing Plane worlds? and is the Plane class your initial world class?
mrunknown mrunknown

2014/6/6

#
After adding the second Plance constructor it says "no suitable constructor found for Plane(int,int,int)" and marks "this" in the code. My code looks exactly like yours above and i removed the "final" from the static fields. My seat class looks like this:
public class Seat extends Actor
{
    private int seatId;
    private boolean is_occupied;
   
    public Seat(int seat_id, boolean occup)
    {
        seatId = seat_id;
        occup = is_occupied;
    }
    
    public void act()
    {
        if(is_occupied == true)
        {
            System.out.println("OCCUPIED"); // just for testing
        }
    }
    
    public int getSeatId()
    {
        return seatId;
    }

    public void occupied()
    {
        is_occupied = true;
    }
}
danpost danpost

2014/6/6

#
Sorry. my line 14 (above) should be
this(S, AReihen);
As far as the Seat class: -Each seat will have a distinct location in the world. That can be its identifying factor. -Each seat will be placed in the world empty. These two things means that no information will need to be passed to the Seat constructor to create a seat. Your 'occupied' method is ok; but not versatile (you may want to un-occupy a seat later). I would use:
public void setOccupied(boolean occup)
{
    is_occupied = occup;
}
You may also want a 'get' method for the 'is_occupied' field value.
danpost danpost

2014/6/6

#
Just a thought. If you want to have more information available to the Seat object, instead of the 'is_occupied' boolean, you could have an 'occupant' (Passenger) object reference and a 'setOccupant' method. If the field is null, the seat is not occupied, otherwise the passenger occupying the seat is referenced (as like a passenger log).
mrunknown mrunknown

2014/6/6

#
Thanks very much! No, i won't have co-existing Plane worlds and it is my only and inital world class. My Seat looks like this now:
public class Seat extends Actor
{
    private int seatId;
    private int occupant;
   
    public Seat(int seat_id)
    {
        seatId = seat_id;
    }

    public int getSeatInfo() // first problem
    {
        return seatId;
        //return this.getX(); => doesn't work
        //return this.getY(); => same
    }
    
    // Occupy methods
    public void setOccupant(int occup_id, boolean occup)
    {
        if(occup == true)
        {
            occupant = occup_id;
        }
        else
        {
            //occupant = null; => don't now how to delete the integer value so that it returns null
        }
    }

    public int getOccupant()
    {
        return occupant;
    }
}
First problem is that i dont know how to call the methods getSeatInfo, setOccupant and getOccupant from another class (mostly my world-class Plane). Second problem is that i don't know how to un-connect the passenger from a seat if integer 'occupant' is set with a number (see code above, line 25). Basically i want to call the method "getSeatInfo" in world Plane when i am spawning my Passenger so that the passenger knows the X and Y coordinates of the seat with ID=xxx and can set the seat occupied (with the ID of the passenger so that seat and passenger are connected, IDs could be similar to simplify it). I know i can put all of this probably in one method but in the first place i have to find out how i can call the seat's methods (and coordinates) from another world "Plane". By now I'm using this in my Passenger class:
    public void getSeat()
    {
        int value = ((Seat) getWorld().getObjects(Seat.class).get(0)).getSeatInfo();
        System.out.println("Test "+value);
    }
But this only works in passenger class (not in world) and only adresses the first object 'Seat' with ID=0 and can't print out the coordinates, only the ID of the seat. I know this is a lot of stuff so i totally appreciate that you're helping me!
danpost danpost

2014/6/7

#
Instead of 'private int occupant', better would be 'private Passenger occupant'. Then:
public void setOccupant(Passenger passenger)
{
    occupant = passenger;
}
would solve the one problem. You can use 'setOccupant(null);' to remove the passenger from the seat. It would also be good to have the passenger assigned a seat before being added to the world using 'private Seat seat' in the Passenger class and creating a passenger using 'new Passenger(seat)', where seat is a randomly chosen unoccupied seat. This takes a little work to weed out the occupied seats from a list of all seats:
List<Seat> seats = new ArrayList<Seat>(getObjects(Seat.class));
List<Seat> available = new ArrayList<Seat>(seats);
for (Seat seat : seats) if (seat.isOccupied()) available.remove(seat);
Seat seat = available.get(Greenfoot.getRandomNumber(available.size()));
Passenger passenger = new Passenger(seat);
seat.setOccupant(passenger);
Line 1 gets a list of all seats. Line 2 copies the list of all seats. Line 3 removes all occupied seats from the second list. Line 4 chooses a random seat from the list of available seats. Line 5 creates a passenger, assigning it the randomly chosen available seat. Line 6 cross-links the seat to the passenger. The method 'isOccupied' in the Seat class would be:
public boolean isOccupied()
{
    return occupant != null;
}
Once the passenger is created with a seat assignment using 'private Seat seat', the passenger can use 'seat.getX()', 'seat.getY()' and 'seat.getId()'. Make sure that the seat is not 'null' before using those methods if it is possible the seat assignment is taken away from the passenger.
mrunknown mrunknown

2014/6/7

#
Works fine, thanks! But when i'm trying to create the passengers automatically rather than manually i get this error:
java.lang.IllegalArgumentException: n must be positive
	at java.util.Random.nextInt(Random.java:294)
	at greenfoot.Greenfoot.getRandomNumber(Greenfoot.java:145)
	at Plane.setPassenger(Plane.java:146) // <=
	at Plane.act(Plane.java:218) // <=
	at greenfoot.core.Simulation.actWorld(Simulation.java:574)
	at greenfoot.core.Simulation.runOneLoop(Simulation.java:509)
	at greenfoot.core.Simulation.runContent(Simulation.java:215)
	at greenfoot.core.Simulation.run(Simulation.java:205)
Line 140 is the second list in my 'setPassenger' method:
    public void setPassenger(int num)
    {
        List<Seat> seats = new ArrayList<Seat>(getObjects(Seat.class));
        List<Seat> available = new ArrayList<Seat>(seats); // <= this is line 140
        for(Seat seat : seats) 
        {
            if(seat.isOccupied()) 
            {
                available.remove(seat);
            }
        }
        Seat seat = available.get(Greenfoot.getRandomNumber(available.size()));
        Passenger passenger = new Passenger(seat, num);
        seat.setOccupant(passenger);
        addObject(passenger, S, 0);
    }
And line 218 is in my 'act' method where i'm creating my passengers:
    public void act()
    {
        if(z != 10) // <= this is line 218
        {
            for(z = 0; z < 10; z++)
            {
                setPassenger(z);
            }
        }
        else
        {
            // nothing
        }
I think it must be something with the List but i don't know where the error exactly is. When i print the numbers created in 'act' (from 0 to 10) everything is how it should be so that can't be the reson.
danpost danpost

2014/6/7

#
This is probably happening after all seats have been assigned. Do not run the 'setPassenger' method if all the number of passengers in the world equals the number of seats.
mrunknown mrunknown

2014/6/7

#
The error is gone now, although i haven't changed anything... awkward. I haven't found out yet how i can make an input that gives me the opportunity to change the number of rows/seats per row after compiling. Somewhere above you said it should work with this (this is how it looks in my 'Plane' class):
   private static int S = 3;
   private static int AReihen = 20;

    public Plane(int run, int rows)
    {    
        super(2*run + 1, rows, 32);
        S = run;
        AReihen = rows;
        setBackground("tile.png");
        createSeats();
        ID = 0;
    }
    
    public Plane()
    {
        this(S, AReihen);
    }
But although 'int run, int rows' is placed in the Plance constructor there is no input window after compiling. When i change
private static int S = 3;
private static int AReihen = 20;
to
private static int S;
private static int AReihen;
There's just a small empty world with no seats at all.
There are more replies on the next page.
1
2
3