Help with for loop

edited February 2016 in Questions about Code

Hello - I have a nested for loop that I am having trouble with.

The purpose of the loop is to look at the distance between instances of a class as they move around.

The loop removes the two instances of the class if they get close.

I am trying to figure out how to make it create a new instance of the class at the collision location, after it has killed off the two instances that collided.

The problem is - creating a new instance of the class changes the creature count which then changes the for loops and puts them out of bounds.

If anyone has any solutions to this problem then that would be great!

void collideCreatures() {
  for (int i = 0; i < creatureCount; i++) {
    TweetAgent b = agents.get(i);
    for (int j = i+1; j < creatureCount; j++) {
      TweetAgent g = agents.get(j);
      float dx = b.location.dist(g.location); 
      if (dx < 5) {
        createAgent(new PVector(b.location.x, b.location.y)); 
        b.alive=false;
        g.alive=false;
      }
    }
  }
}

void createAgent(PVector _location) {
  agents.add(new TweetAgent(_location));
  creatureCount = creatureCount + 1;
}

Answers

  • in line 8 just store the positions in a separate arraylist and create them from here after the nested forloops

  • Things would be much easier if you postpone the add() once the double loop is over.
    Or at least create some temporary List for the new arrivals.
    Once loop is finished, addAll() them to the main List:
    http://docs.Oracle.com/javase/8/docs/api/java/util/List.html#addAll-java.util.Collection-

  • edited February 2016

    Hi - I had a go at the first suggestion but with no luck, maybe I have done something wrong:

    void collideCreatures() {
      for (int i = 0; i < creatureCount; i++) {
        TweetAgent b = agents.get(i);
        for (int j = i+1; j < creatureCount; j++) {
          TweetAgent g = agents.get(j);
          float dx = b.location.dist(g.location); 
          if (dx < 50) {
            b.alive=false;
            g.alive=false;
    
            collisionLocations.add(new PVector(b.location.x, b.location.y));
          }
        }
      }
    
      for (int i=0; i<collisionLocations.size(); i++) {
        PVector p = collisionLocations.get(i);
        createAgent(new PVector(p.x, p.y)); 
      }
    }
    
  • looks good so far

    do you have collisionLocations.clear() before line 2 ?

  • edited February 2016

    btw 1: you could maybe just keep b ? Depending on your class' constructor which we don't know

    btw 2: also, when you clear up agents (removing all with alive==false using agents.remove(i);) you need to loop backwards through agents

  • // forum.Processing.org/two/discussion/14834/help-with-for-loop
    // GoToLoop (2016-Feb-09)
    
    import java.util.List;
    final List<TweetAgent> agents = new ArrayList<TweetAgent>();
    
    void setup() {
      size(30, 20, FX2D);
      smooth(4);
    
      for (int i = 0; i++ < 10; agents.add(new TweetAgent
        (new PVector(random(width), random(height))))); 
    
      println(collision(agents)); 
      exit();
    }
    
    List<TweetAgent> collision(final List<TweetAgent> creatures) {
      final List<TweetAgent> newborns = new ArrayList<TweetAgent>(); 
      final int len = creatures.size(); 
      int j, i = 0; 
    
      while (i < len) {
        final TweetAgent a = creatures.get(i++); 
        j = i;
    
        while (j < len) {
          final TweetAgent b = creatures.get(j++); 
    
          if (b.isColliding(a)) {
            newborns.add(new TweetAgent(a.location)); 
            a.alive = b.alive = false; 
            break;
          }
        }
      }
    
      creatures.addAll(newborns); 
      return creatures;
    }
    
    class TweetAgent {
      static final int DIAM = 5, RAD = DIAM>>1; 
    
      final PVector location = new PVector(); 
      boolean alive = true; 
    
      TweetAgent(PVector vec) {
        location.set(vec);
      }
    
      boolean isColliding(TweetAgent o) {
        return location.dist(o.location) < DIAM;
      }
    
      @ Override String toString() {
        return "\nAlive: " + alive 
          + "\tPosition: " + location.toString();
      }
    }
    
  • edited February 2016
    • The sample above is just to demonstrate the use of addAll().
    • But its innards logic doesn't make any sense!
    • The PVector location in the List newborns got the same coordinates as the TweetAgent a.location!
    • Therefore rather than mark TweetAgent a.alive as false, just keep it! :>
    • Only TweetAgent b.alive needs to be false, the other stays true.
    • A better solution is throw away TweetAgent's alive and remove() it instead inside backwards loops.

    // forum.Processing.org/two/discussion/14834/help-with-for-loop
    // GoToLoop (2016-Feb-09)
    
    import java.util.List;
    final List<TweetAgent> agents = new ArrayList<TweetAgent>();
    
    void setup() {
      size(30, 20, FX2D);
      smooth(4);
    
      for (int i = 0; i++ < 10; agents.add(new TweetAgent
        (new PVector(random(width), random(height))))); 
    
      println(collision(agents)); 
      exit();
    }
    
    List<TweetAgent> collision(final List<TweetAgent> creatures) {
      //final List<TweetAgent> newborns = new ArrayList<TweetAgent>(); 
      final int len = creatures.size(); 
      int j, i = 0; 
    
      while (i < len) {
        final TweetAgent a = creatures.get(i++); 
        j = i;
    
        while (j < len) {
          final TweetAgent b = creatures.get(j++); 
    
          if (b.isColliding(a)) {
            //newborns.add(new TweetAgent(a.location)); 
            //a.alive = b.alive = false;
            b.alive = false;
            break;
          }
        }
      }
    
      //creatures.addAll(newborns); 
      return creatures;
    }
    
    class TweetAgent {
      static final int DIAM = 5, RAD = DIAM>>1; 
    
      final PVector location = new PVector(); 
      boolean alive = true; 
    
      TweetAgent(PVector vec) {
        location.set(vec);
      }
    
      boolean isColliding(TweetAgent o) {
        return location.dist(o.location) < DIAM;
      }
    
      @ Override String toString() {
        return "\nAlive: " + alive 
          + "\tPosition: " + location.toString();
      }
    }
    
  • Hi thanks for your replies - unfortunately the above code is beyond my current level so I don't understand it.

    Maybe if I add more of my code it will make more sense what is happening and why the first solution was unsuccessful:

    The first part is the main sketch (I have commented out all the parts that I think are irrelevant to the problem but have included the entire sketch so that it makes sense what I am doing ( I am aware the quality of this code could be improved but it serves its intended purpose at the moment).

    //import twitter4j.util.*;
    //import twitter4j.*;
    //import twitter4j.management.*;
    //import twitter4j.api.*;
    //import twitter4j.conf.*;
    //import twitter4j.json.*;
    //import twitter4j.auth.*;
    //import java.util.Map;
    //import controlP5.*;
    
    //ControlP5 cp5;
    //TwitterStream twitterStream;
    
    //String searchTerm; 
    //String tweet; // initial tweet when received
    
    //StringList allTweets; // stores all creature tweets text
    //String aTweet; // a tweet in the above stringlist
    
    //StringList allPredators; // stores all predator tweets text
    //String aPredator; // a tweet in the above string list
    
    //StringList keywordsCopy;
    
    ArrayList<TweetAgent> agents = new ArrayList<TweetAgent>(); //array list of tweet creature iterations
    //ArrayList<PredatorAgent> predatorAgents = new ArrayList<PredatorAgent>(); //array list of predator iterations
    
    
    void setup() {
     // fullScreen();
     // background(50);
      ///smooth();
      allTweets = new StringList(); //sets up stringlist containing all creature tweets
     // allPredators = new StringList(); //sets up stringlist containing all predator //tweets
      //openTwitterStream();
    }
    
    
    
    void draw() {
     // noStroke();
     // rectMode(CORNER);
     // colorMode(RGB);
     // fill(50, 255);
     // rect(0, 0, width, height);
     // strokeWeight(2);
     // stroke(255);
     // noFill();
     // ellipse(width/2, height/2, 600, 600);
     // fill(255, 255, 255);
    
      //Creature functions//Creature functions//Creature functions//Creature //functions//Creature functions//Creature functions//Creature functions
       for (int i = agents.size() -1; i>-1; i--) { //Does all the creature functions so they //can be seen
    
      for (int i = agents.size()-1; i>-1; i--) {
        aTweet = allTweets.get(i); // stores tweet text
        TweetAgent a = agents.get(i); // stores class iterations
        a.update();
        a.checkEdges();
        a.vowelCount();
        a.checkCreatureCollision();
        a.display();
        if (a.alive == false) {
          agents.remove(i); // if a is dead, remove that class iteration
          allTweets.remove(i); // and remove associated tweet text
        }
      }
      //Creature functions//Creature functions//Creature functions//Creature functions//Creature functions//Creature functions
    
    
      //Predator functions//Predator functions//Predator functions//Predator //functions//Predator functions//Predator functions
     // for (int i = predatorAgents.size ()-1; i >-1; i--) {
     //   PredatorAgent b = predatorAgents.get(i);
     //   aPredator = allPredators.get(i);
     //   b.update();
     //   b.checkEdges();
     //   b.display();
    
       // if (b.alive == false) {
       //   predatorAgents.remove(i);
       //   allPredators.remove(i);
       // }
     // }
      //Predator functions//Predator functions//Predator functions//Predator //functions//Predator functions//Predator functions
    //}
    
    
    void createAgent(PVector _location) {
      agents.add(new TweetAgent(_location));
    }
    
    //void createPredatorAgent(PVector _location) {
    //  predatorAgents.add(new PredatorAgent(_location));
    //}
    
    
    //void openTwitterStream() {  
    //  ConfigurationBuilder cb = new ConfigurationBuilder();  
    //  cb.setOAuthConsumerKey("XXXXXXXX");
    //  cb.setOAuthConsumerSecret("XXXXXXX");
    //  cb.setOAuthAccessToken("XXXXXXX");
    //  cb.setOAuthAccessTokenSecret("XXXXXXX"); 
     // TwitterStream twitterStream = new //TwitterStreamFactory(cb.build()).getInstance();
    //  FilterQuery filtered = new FilterQuery();
    
    //  String keywords[] = {
     //   "hello", "goodbye", //creatures, predators
     // };
    
     // keywordsCopy = new StringList();
    
      //for (int i =0; i<keywords.length; i++) {
      //  keywordsCopy.append(keywords[i]);
     // }
    
     // filtered.track(keywords);
     // twitterStream.addListener(listener);
    
     // if (keywords.length==0) {
     //   twitterStream.sample();
     // } else { 
      //  twitterStream.filter(filtered);
     // }
     // println("connected");
    //}
    
    //StatusListener listener = new StatusListener() {
    
      //do your stuff here..
      //@Override
      public void onStatus(Status status) {
        if (agents.size()<15) { // limits number of creatures
          tweet = status.getText();
          tweet = tweet.toLowerCase();
          tweet = tweet.replace('\n', ' ');
          booleanWords();
    
          if ( tweet.indexOf(keywordsCopy.get(0)) != -1 ) {
            allTweets.append(tweet);
            createAgent(new PVector(random((width/2)-200, (width/2)+200), random((height/2)-200, (height/2)+200)));
          }// else if ( tweet.indexOf(keywordsCopy.get(1)) != -1 && predatorAgents.size() //< 10  ) { // LIMIT PREDATORS LIMIT PREDATORS LIMIT PREDATORS
      //      allPredators.append(tweet);
       //     createPredatorAgent(new PVector(random((width/2)-200, (width/2)+200), //random((height/2)-200, (height/2)+200)));
    //      }
    //    }
     // }
    
    
    
      // Keep those methods here... this is it...
      //@Override
      ///public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {
       // System.out.println("Got a status deletion notice id:" + //statusDeletionNotice.getStatusId());
    //  }
    
      //@Override
      //public void onTrackLimitationNotice(int numberOfLimitedStatuses) {
     //   System.out.println("Got track limitation notice:" + numberOfLimitedStatuses);
     // }
    
      //@Override
     // public void onScrubGeo(long userId, long upToStatusId) {
     //   System.out.println("Got scrub_geo event userId:" + userId + " upToStatusId:" //+ upToStatusId);
     // }
    
      //@Override
    //  public void onStallWarning(StallWarning warning) {
     //   System.out.println("Got stall warning:" + warning);
     // }
    
      //@Override
     // public void onException(Exception ex) {
     //   ex.printStackTrace();
     // }
    //};
    

    This is the creature class (there is also a predator class but it isnt relevant to include it):

    //class TweetAgent {
    //  PVector location, velocity, acceleration;
    //  float limit, change;
     // int age, lifetime;
     // boolean alive = false;
     // float scaler;
     // int num = 50;
     // int vowelCount, punctCount;
    
     // TweetAgent(PVector _location) {
     //   location = _location.get();
      //  velocity = new PVector(0, 0);
      ////  acceleration = new PVector(random(-5, 5), random(-5, 5));
      //  change = random(0.001, 0.1);
      //  limit = random(1, 3);
      //  lifetime = 500;
      //  age = 0;
      //  alive = true;
     // }
    
      //void update() {
      //  if (random(1) < change) {
      //    acceleration = new PVector(random(-1, 1), random(-1, 1));
      //  }
      //  velocity.add(acceleration);
      //  velocity.limit(limit);
      //  location.add(velocity);
      //  age ++;
      //  if (age >= lifetime) {
      //    alive = false;
      //    noFill();
      //    stroke(0, 0255, 255);
      //    shapeMode(CENTER);
      //    ellipse(location.x, location.y, 60, 60);
      //  }
    //  }
    
    
      //void vowelCount() {
      //  vowelCount =0;
      //  for (int vCount = 0; vCount< aTweet.length(); vCount++) {
      //    if (aTweet.charAt(vCount) == 'a') {
      //      vowelCount = vowelCount + 1;
      //    }
      //    if (aTweet.charAt(vCount) == 'e') {
      //      vowelCount = vowelCount + 1;
      //    }
       //   if (aTweet.charAt(vCount) == 'i') {
       //     vowelCount = vowelCount + 1;
       //   }
       //   if (aTweet.charAt(vCount) == 'o') {
       //     vowelCount = vowelCount + 1;
        //  }
    
       //   if (aTweet.charAt(vCount) == 'u') {
        //    vowelCount = vowelCount + 1;
        //  } else {
        //    vowelCount = vowelCount + 0;
        //  }
       // }
     // }
    
    /*
      void punctCount() {
        punctCount =0;
        for (int vCount = 0; vCount< aTweet.length(); vCount++) {
    
          if (aTweet.charAt(vCount) != 'a') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'b') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'c') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'd') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'e') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'f') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'g') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'h') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'i') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'j') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'k') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'l') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'm') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'n') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'o') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'p') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'q') {
            punctCount = punctCount + 1;
          } 
          if (aTweet.charAt(vCount) != 'r') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != 's') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != 't') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != 'u') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != 'v') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != 'w') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != 'x') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != 'y') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != 'z') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != '0') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != '1') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != '2') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != '3') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != '4') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != '5') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != '6') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != '7') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != '8') {
            punctCount = punctCount + 1;
          } 
    
          if (aTweet.charAt(vCount) != '9') {
            punctCount = punctCount + 1;
          } else {
            punctCount = punctCount + 0;
          }
        }
      }
    
      void display() {
        int m = int(map(aTweet.length(), 0, 140, 0, 50));
        float n1 = map(aTweet.length(), 0, 140, -5000, 5000);
        float n2 = map(vowelCount, 0, 140, -5000, 5000);
        float n3 = map(punctCount, 0, 3, 0, 800);
        scaler = map(m*aTweet.length(), 0, 50*140, 30, 1);
    
        colorMode(HSB);
        strokeWeight(1);
        stroke(map(aTweet.length(), 0, 100, 0, 255), 75, 200);
        noFill();
        pushMatrix();
        //  ellipse(location.x, location.y, aTweet.length()/2, aTweet.length()/2);
        fill(map(aTweet.length(), 0, 100, 255, 0), map(vowelCount, 0, 50, 0, 255), 150);
        translate(location.x, location.y);
        rotate(velocity.heading() + (PI/2));
        float newscaler = scaler;
    
        beginShape();
        int s= 1;
        float mm = m + s;
        float nn1 = n2 + s ;
        float nn2 = n3 + s;
        float nn3 = n1 + s;
        newscaler = newscaler * .75;
        float sscaler = newscaler;
        PVector[] points = superformula(mm, nn1, nn2, nn3);
        curveVertex(points[points.length-1].x * sscaler, points[points.length-1].y * sscaler);
        for (int i = 0; i < points.length; i++) {
          curveVertex(points[i].x * sscaler, points[i].y * sscaler);
        }
        curveVertex(points[0].x * sscaler, points[0].y * sscaler);
        endShape();
        popMatrix();
      }
    
      PVector[] superformula(float m, float n1, float n2, float n3) {
        int numPoints = 360;
        float phi = TWO_PI / numPoints;
        PVector[] points = new PVector[numPoints+1];
        for (int i = 0; i <= numPoints; i++) {
          points[i] = superformulaPoint(m, n1, n2, n3, phi * i);
        }
        return points;
      }
    
      PVector superformulaPoint(float m, float n1, float n2, float n3, float phi) {
        float r;
        float t1, t2;
        float a=1, b=1;
        float x = 0;
        float y = 0;
    
        t1 = cos(m * phi / 4) / a;
        t1 = abs(t1);
        t1 = pow(t1, n2);
    
        t2 = sin(m * phi / 4) / b;
        t2 = abs(t2);
        t2 = pow(t2, n3);
    
        r = pow(t1+t2, 1/n1);
        if (abs(r) == 0) {
          x = 0;
          y = 0;
        } else {
          r = 1 / r;
          x = r * cos(phi);
          y = r * sin(phi);
        }
    
        return new PVector(x, y);
      }
    
      void checkEdges() {
        if (dist(location.x, location.y, width/2, height/2)>=(295-scaler)) {
          pushMatrix();
          location.x = -location.x;
          location.y= -location.y;
          rotate(velocity.heading()+PI);
          popMatrix();
        }
      }
    */
    
      void checkCreatureCollision() {
        for (int i =0; i<agents.size(); i++) {
          TweetAgent a = agents.get(i);
          for (int j = i+1; j<agents.size(); j++) {
            TweetAgent b = agents.get(j);
            float ab = a.location.dist(b.location);
            if (ab < 100) {
              line(a.location.x, a.location.y, b.location.x, b.location.y);
              b.alive=false;
    
              //save collision location (a.location.x, a.location.y) to an array list
    
            }
          }
        }
      }
    
    
    
    
    
    }
    
  • ... unfortunately the above code is beyond my current level so I don't understand it.

    My example wasn't that big, and I dunno how to simplify it any further. :|
    If you could pinpoint exactly what you don't get, I may be able to explain it better. :-/

    Maybe if I add more of my code it will make more sense...

    I guess I've got 2 old online examples which are very similar to your last example:

    1. http://studio.ProcessingTogether.com/sp/pad/export/ro.9s0026dE7B8v-
    2. http://studio.ProcessingTogether.com/sp/pad/export/ro.989GaZC5t7EkE
Sign In or Register to comment.