Complete Working Refrigerator

// COMPLETE WORKING PROCESSING PROGRAM,
// ILLUSTRATING:
// -- ARRAY OF OBJECTS
// -- MAINTAINING SORTED ORDER OF ARRAY OF OBJECTS
// -- SUBCOLLECTIONS
 
// Global instances of Refrigerator objects:
Refrigerator mainFridge;
Refrigerator miniFridge;
 
 
void setup(){
  size(450, 400);
 
  // Create the instance of the main Refrigerator object.
  // The mini Refrigerator is null for now.
  // Question for you: where does the miniFridge get created?
  mainFridge = new Refrigerator();
  miniFridge = null;
}
 
void draw(){
  background(180);
 
  // Request the main Refrigerator to draw itself.
  // I have modified the render() method to take location & size.
  mainFridge.render(50,50,150,300);
 
  // Since the mini Refrigerator does not exist at the start
  // of the program, only draw it once it has been created.
  if (miniFridge != null){
    miniFridge.render(250,180,150,170);
  }
 
}
 
int miniFridgeType = 0; // just a little hack
 
void keyPressed(){
  switch(key){
  case 'o':
    mainFridge.openDoor();
    break;
  case 'c':
    mainFridge.closeDoor();
    break;
  case '-':
    mainFridge.removeItem();
    break;
  case '+':
    mainFridge.addItem();
    break;
 
  case 'f':
    // When we press the 'f' key,
    // Create the mini-fridge.
    // For this fridge, we ONLY select those foods of a certain "type"
    // (triangle, circle, square).
    miniFridgeType++;
    miniFridgeType%=3;
    miniFridge = mainFridge.makeSubcollectionRefrigerator (miniFridgeType);
    break;
 
  case 'x':
    // When we press the 'x' key,
    // delete whichever item is mouse-selected (in the main fridge),
    // ans shift the remaining items down one position.
    int indexOfSelectedItem = mainFridge.getIndexOfSelectedItem();
    if (indexOfSelectedItem != -1){
      mainFridge.removeSpecificItem(indexOfSelectedItem);
    }
    break;
 
 
  case 'v':
    // when we press the 'v' key,
    // insert a new FoodItem into the main fridge.
    // This FoodItem is generated with a random tallness,
    // and it will have to be inserted in the correct position
    // in the array (maintaining sorted order!).
    // All inserted FoodItems are RED, so you can easily spot them.
    float tallness = 10 + random(35);
    color chroma = color(255,0,0);
    int   type = (int)random(0,3);
    FoodItem F = new FoodItem(tallness, chroma, type);
    mainFridge.insertAndSortNewFoodItem (F);
    break;
  }
}
 
//===============================================
class Refrigerator {
 
  // FIELDS
  int      nFoodItems;
  FoodItem foodItems[];
  boolean  bDoorOpen;
 
  //---------------------------
  // METHODS
 
  Refrigerator(){
    bDoorOpen = false;
    nFoodItems = 0;
 
    int initialFoodItemArraySize = 10;
    foodItems = new FoodItem[initialFoodItemArraySize];
    // ...individual food items will be created (new'd) when they're added.
    // that's one way to do it.
  }
 
  //---------------------------
  void render(int x, int y, int w, int h){
    // IF THE DOOR IS CLOSED, SHOW THE OUTSIDE OF THE FRIDGE.
    if (bDoorOpen == false){
      stroke(0);
      strokeWeight(1);
      fill(255,240,230);
      rect(x,y,w,h);
      fill(180,180,190);
      rect(x+5,y+h/2-40,5,60);
 
      // render silly kid's drawing
      pushMatrix();
      translate(50,50);
      rotate(radians(-15.0));
      translate(x,y);
      fill(255);
      rect(0,0,36,36);
      smooth();
      ellipse(18,18,27,27);
      arc(18,18,20,20, radians(45),radians(135));
      ellipse(12,14,6,6);
      ellipse(24,14,6,6);
      popMatrix();
 
    }
    else {
      // BUT IF THE DOOR IS OPEN, SHOW THE STUFF INSIDE.
      stroke(0);
      strokeWeight(1);
 
      // Draw the fridge enclosure
      fill(200,200,208);
      rect(x,y,w,h);
      fill(240,240,255);
      rect(x+5,y+5,w-10,h-10);
 
      // draw the food items at specified locations.
      // Compute some positions to cleverly position things.
      for (int i=0; i<nFoodItems; i++){
        float foodx = x + 25 + (i%6)*20;
        float foody = y + h - 10 - (60*(i/6));
        foodItems[i].draw(foodx,foody);
      }
    }
  }
 
  //---------------------------
  // ACCESSOR METHODS
  boolean isDoorOpen(){
    return bDoorOpen;
  }
 
  int getNFoodItems(){
    return nFoodItems;
  }
 
  // SIMPLE MUTATOR METHODS
  void closeDoor(){
    bDoorOpen = false;
  }
 
  void openDoor(){
    bDoorOpen = true;
  }
 
  //---------------------------
  Refrigerator makeSubcollectionRefrigerator (int subselectionFoodType){
    // Here, we ask this Refrigerator to create
    // a "subcollection" Refrigerator (such as a cooler or mini-fridge).
 
    // We know (from its signature) that this method *must*
    // return a Refrigerator. So declare and create this right away!
    // And don't forget to return it at the end of the method.
    Refrigerator outputFridge = new Refrigerator();
 
    // Open its door so we can add food to it (ha!)
    outputFridge.openDoor();
 
    // Search through my foodItems array for items which meet the criterion.
    // Add those items to the outputFridge.
    // (Note that "criterion" in this case means, subselectionFoodType.
    // But the criterion could be measuring a continuous property instead --
    // For example, find me all FoodItems taller than.... etc.)
    for (int i=0; i<nFoodItems; i++){
      if (foodItems[i].getType() == subselectionFoodType){
        outputFridge.addItem(foodItems[i]);
      }
    }
 
    // Return the outputFridge.
    return outputFridge;
  }
 
 
  //---------------------------
  // ADDITEM 1: pass in an actual FoodItem object.
  void addItem (FoodItem F){
    if (bDoorOpen){
      foodItems[nFoodItems] = F;
      nFoodItems++;
      if (nFoodItems >= foodItems.length){
        expandFoodItemArray();
      }
    }
    else {
      System.out.println("Door must be open to add an item.");
    }
  }
 
 
  //---------------------------
  // ADDITEM 2: pass in properties for a new FoodItem to be made from
  void addItem (float tallness, color chroma, int type){
    if (bDoorOpen){
      foodItems[nFoodItems] = new FoodItem(tallness, chroma, type);
      nFoodItems++;
      if (nFoodItems >= foodItems.length){
        expandFoodItemArray();
      }
    }
    else {
      System.out.println("Door must be open to add an item.");
    }
  }
 
  //---------------------------
  void addItem(){
    // ADDITEM 3: pass in nothing (no arguments);
    // Adds a randomly-generated item to the end of the array,
    // expanding the array if necessary (if it gets too full).
 
    if (bDoorOpen){
      // If the door is open,
      // generate the properties of a new FoodItem
 
      // This is code for adding a new fooditem to the end.
      // It makes sure that this new food item is 4 pixels taller than
      // what is currently the last item in the array.
      float tallness = 10;
      if (nFoodItems > 0){
        tallness = foodItems[nFoodItems-1].getTallness() + 4.0;
      }
 
      // generate a color and food type for
      // what will be the newly added FoodItem
      color chroma = color(random(100,255), random(128,255), random(0,100));
      int   type = (int)random(0,3);
 
      // .. create and add that FoodItem to the foodItems array.
      foodItems[nFoodItems] = new FoodItem(tallness, chroma, type);
      nFoodItems++;
 
      // Deal with what happens when the user fills up the array.
      // If the number of food items has exceeded the size of the array,
      // Expand the array!
      if (nFoodItems >= foodItems.length){
        expandFoodItemArray();
      }
    }
    else {
      System.out.println("Door must be open to add an item.");
    }
  }
 
  //---------------------------
  void insertAndSortNewFoodItem (FoodItem inputF){
    // Some FoodItem, inputF, is being "inserted" into the array.
    // We are asked to make sure that we maintain "sorted order",
    // in this case, of the "tallness" of the foodItems.
 
    if (bDoorOpen){
      // Only insert new food if the door is open, right?
      // Now fetch the tallness of the inputF FoodItem.
      // Note the use of the accessor method.
      float tallnessOfInputF = inputF.getTallness();
 
      // Search for the index at which to insert this foodItem,
      // to maintain the sorted order of the foodItem array.
      // This could also be accomplished with a while{} loop.
      int indexAtWhichToInsertInputF = 0;
      for (int i=0; i<nFoodItems; i++){
        if (foodItems[i].getTallness() < tallnessOfInputF){
          indexAtWhichToInsertInputF++;
        }
      }
 
      // It's possible we might need to enlarge the size of the array.
      if (nFoodItems >= foodItems.length){
        expandFoodItemArray();
      }
 
      // Shift all elements taller than inputF,
      // one position further down the array.
      for (int i=nFoodItems; i>indexAtWhichToInsertInputF; i--){
        foodItems[i] = foodItems[i-1];
      }
 
      // Insert the inputF. Note how simple this is.
      // Then, don't forget to increase the nFoodItems!
      foodItems[indexAtWhichToInsertInputF] = inputF;
      nFoodItems++;
 
    }
    else {
      System.out.println("Door must be open to insert an item.");
    }
  }
 
 
  //---------------------------
  void removeItem(){
    if (bDoorOpen){
      if (nFoodItems > 0){
        nFoodItems--;
      }
    }
    else {
      System.out.println("Door must be open to remove an item");
    }
  }
 
  //---------------------------
  void removeSpecificItem (int indexFromWhichToRemoveFoodItem){
    // To remove a specific item from the foodItems array,
    // copy all higher-numbered FoodItems down one position in the array.
    if ((indexFromWhichToRemoveFoodItem >= 0) &&
        (indexFromWhichToRemoveFoodItem < nFoodItems)){
      for (int i=indexFromWhichToRemoveFoodItem; i<nFoodItems; i++){
        foodItems[i] = foodItems[i+1];
      }
      nFoodItems--;
    }
  }
 
  //---------------------------
  int getIndexOfSelectedItem(){
    // Loop over all of my FoodItems,
    // and return the array-index of whichever one
    // reports that the mouse is hovering over it.
    int output = -1;
    for (int i=0; i<nFoodItems; i++){
      if (foodItems[i].isMouseHovering()){
        output = i;
      }
    }
    return output;
  }
 
  //---------------------------
  void expandFoodItemArray(){
    // Make a new array ("biggerArray") which
    // holds twice as much stuff as foodItems.
    FoodItem biggerArray[] = new FoodItem[ foodItems.length * 2];
 
    // Copy all of our FoodItems into that bigger array.
    for (int i=0; i<foodItems.length; i++){
      biggerArray[i] = foodItems[i];
    }
 
    // Re-assign foodItems to be that bigger array.
    foodItems = biggerArray;
  }
 
} // End of Refrigerator Class.
 
 
 
 
//=====================================================
//=====================================================
class FoodItem {
 
  float posx, posy;
  float tallness;
  color chroma;
  int   type;
 
  //-----------------------------------
  // Constructor for a FoodItem.
  // All necessary variables are passed in.
  FoodItem (float tallness, color chroma, int type){
    this.tallness = tallness;
    this.chroma   = chroma;
    this.type     = type;
  }
 
  //-----------------------------------
  // How a FoodItem should draw itself.
  // Note that a position is passed in.
  void draw (float x, float y){
    posx = x;
    posy = y;
 
    smooth();
    stroke(0);
    if (isMouseHovering()){
      strokeWeight(4);
    }
    else {
      strokeWeight(1);
    }
 
    fill(chroma);
    switch(type){
    case 0: // RECT
      rect(posx-6,posy-tallness, 12,tallness);
      break;
    case 1: // ELLIPSE
      ellipse(posx,posy-tallness/2, 12,tallness);
      break;
    case 2: // TRIANGLE
      triangle(posx-6,posy, posx+6,posy, posx,posy-tallness);
      break;
    }
    noSmooth();
  }
 
  //-----------------------------------
  // ACCESSOR METHODS.
 
  int getType(){
    return type;
  }
 
  float getTallness(){
    return tallness;
  }
 
  boolean isMouseHovering(){
    return (
    (  mouseX > posx-6) &&
      (mouseX < posx+6) &&
      (mouseY < posy) &&
      (mouseY > posy-tallness));
  }
 
} // End of FoodItem Class.

Important End-of-Semester Information

——————————————————-
FINAL EXAM date, time and location:

Monday, December 8
Room DH-2210 (Dougherty Hall)
8:30-11:30AM.

Arrive EARLY, like 8:15am!! Students arriving late will not be given extra time. Please arrive 15 minutes before the exam period begins to get to your assigned seat so you can hear the exam instructions completely.
Missing the exam will result in a failing grade for the exam. If you are ill or have a
family emergency during your exam time, you must have a valid documented excuse and
must speak with your instructor as soon as possible.
Bring 2 pencils, erasers, and your student ID card (or some other government-issued
photo ID) with you. Your ID will be checked at the exam. If you do not bring an ID, you
may be asked to leave the exam room.
You may not use electronic devices of any kind during the exam. This includes, but is
not limited to, cell phones, pagers, calculators, PDAs, computers, music players, etc. It is
better if you do not even bring these items to the exam room in the first place.
Please use the restroom before arriving at your exam room.

——————————————————-
WHAT TOPICS will be on the final exam? See these documents:
http://artscool.cfa.cmu.edu/~levin/courses/dmc/intro08/downloads/15100FinalInfoSheetF08.pdf
http://www.andrew.cmu.edu/course/15-100mooseNsquirrel/Exam3Overview.pdf

——————————————————-
FINAL EXPERIMENT PROJECTS and other HOMEWORK
– Final Experiments are due 3pm on Friday December 12. We will have a fun viewing-session/party in room CFA-303 at that time.
– All unfinished homework assignments should be uploaded by 3pm, Friday 12 December for grading. Missing assignments will not be accepted after that time.

——————————————————-
UNIVERSITY COURSE ASSESSMENTS:

The University Course Assessment (UCA) is open for your feedback, through Wednesday of this coming week. I really care about your feedback, and so does the school. I have received an automatic email informing me that 4 of you have still not filled this out — please take just a minute to fill out the form by going here: Link to the Carnegie Mellon portal at https://my.cmu.edu/site/main/page.academics and click on “University Course Assessment” under “Courses”.

Notes on INSERTION while maintaining sorted order

First, let’s handle the case for a simple array of INTEGERS:

// Insertion into an INTEGER ARRAY while maintaining SORTED ORDER,
// and NOT worrying about needing to expand the array size:
 
// Here's the setup:
int integerArray[] = new int[10];
int nData = 4; // we're consuming 4 ints out of 10.
integerArray[0] = 3;
integerArray[1] = 5;
integerArray[2] = 7;
integerArray[3] = 9;
//
int numberToInsert = 6; // the number to insert.
 
// First, compute the array index at which to insert the number.
// Assume the data in integerArray[] is already sorted!!
int index = 0;
while ((index < nData) && (numberToInsert > integerArray[index])) {
  index++;
}
 
// Now, shift the data above that index, further downstream.
for (int i=nData; i>index; i--){
  integerArray[i] = integerArray[i-1];
}
 
// Finally, insert the new number in the right place.
// And don't forget to increment nData.
integerArray[index] = numberToInsert;
nData++;
//
// NOTE: you *may* have to handle the case
// where nData suddenly exceeds the size of the array...

Now, here is the same problem, but dealing with inserting an Object into a sorted OBJECT ARRAY.
Note: the use of “setup()” is Processing-specific…

 
// Insertion into an OBJECT ARRAY while maintaining SORTED ORDER,
// and NOT worrying about needing to expand the array size:
 
// Here's the class we'll use for this example:
class Thing {
  int property;
  Thing (){
    property = 0; // initialized to zero
  }
  void setProperty(int p){
    property = p;
  }
  int getProperty(){
    return property;
  }
}
 
//-------------------------------------------
void setup(){
 
  // Here's the setup:
  Thing thingArray[] = new Thing[10];
  int nData = 4; // we're consuming 4 Things out of 10.
  for (int i=0; i<nData; i++){
    thingArray[i] = new Thing();
  }
  // Note the use of the accessor method!
  thingArray[0].setProperty(3);
  thingArray[1].setProperty(5);
  thingArray[2].setProperty(7);
  thingArray[3].setProperty(9);
 
  // The Thing to insert:
  Thing thingToInsert = new Thing();
  thingToInsert.setProperty(6);
 
 
  //--------------------------------
  // HERE'S THE INSERTION:
 
  // First, compute the array index at which to insert the number.
  // Assume the data in integerArray[] is already sorted.
  int index = 0;
  int propertyOfThingToInsert = thingToInsert.getProperty();
  while ((index < nData) &&
         (propertyOfThingToInsert > thingArray[index].getProperty())){
    index++;
  }
 
  // Now, shift the data above that index further downstream.
  for (int i=nData; i>index; i--){
    thingArray[i] = thingArray[i-1];
  }
 
  // Finally, insert the new number in the right place.
  // And don't forget to increment nData.
  thingArray[index] = thingToInsert;
  nData++;
}

Solutions to Moose Exam 2, Problem 5

Executing the code,

int dList[] = {3, 2, 2, 5, 1, 7, 4, 6, 0};
char charList[] = {'C',' ','O','G','U','D','K','L'};
 
for ( int i = 0; i < dList.length; i++){
  System.out.print( charList[ dList[ i ] ] );
}
System.out.println( );

we learn that the answer is:
GOOD LUKC
pretty mean!

Solutions to Moose Exam 2, Questions 3 & 4

Question 3.

public int search( char letter ){
  int indexOfSecondOccurrence = -1;
 
  int foundCount = 0;
  int nData = dList.length;
  for (int i=0; i<nData; i++){
    // Note use of getLetter() accessor method!!!:
    if (dList[i].getLetter() == letter){
      foundCount++;
      if (foundCount == 2){
        indexOfSecondOccurrence = i;
      }
    }
  }
 
  return indexOfSecondOccurrence;
}
 
  // Note that this function will return -1
  // for the "indexOfSecondOccurrence" when the input data
  // does not contain 2 occurrences. This is customary.
  // It's a reasonable answer, since this method *must*
  // return an integer.

QUESTION 4:

void insert (Data D){
  // assume the global variable "nData" stores the
  // number of valid references in the global dList array.
 
  // Special case if there are no elements already in the dList array,
  // since then we couldn't compare the incoming D with the 0th element!
  if (nData == 0){
    dList[0] = D;
    nData++;
  }
  else {
    int numberFieldOfZerothElement = dList[0].getNumber();
    if (D.getNumber() < numberFieldOfZerothElement){
      // copy elements higher than the 0th position, one position down.
      for (int i=nData; i>0; i--){
        dList[i] = dList[i-1];
      }
 
      // insert D at the 0th position
      dList[0] = D;
      nData++;
    }
    else {
      dList[nData] = D;
      nData++;
    }
  }
 
  // Now expand the array if it has become full on the
  // previous round of insertion. Needing to expand the array
  // is an annoying consequence of the way the problem is formulated,
  // since we (A) are told to deal with the case when the array is full,
  // and (B) are expressly told that we must never lose data.
  //
  if (nData >= dList.length){
    // a good guess for a new size is twice the previous size.
    int newMaximumSize = dList.length * 2;
    Data biggerDList[] = new Data[newMaximumSize];
    for (int i=0; i<nData; i++){
      biggerDList[i] = dList[i];
    }
    dList = biggerDList;
  }
}

Solutions to Moose Exam 2, Questions 1 & 2

Question 1.

public class Question1
{
  // fields
  int dList[];
 
  // constructor
  public Question1( ){
    dList = new int[7];
    for (int i=0; i<7; i++){
      dList[i] = (i+1);
    }
  }
}

OR

public class Question1
{
  // fields
  int dList[] = {1,2,3,4,5,6,7};
 
  // constructor
  public Question1( ){
  }
}

Question 2:

  void printGreaterThanSumOfBothNeighbors( int intList[]){
 
    int n = intList.length;
    if (n > 2){
      boolean bFoundOne = false;
 
      for (int i=1; i<(n-1); i++){
        int neighborLeft  = intList[i-1];
        int neighborRight = intList[i+1];
        int sumOfBothNeighbors = neighborLeft + neighborRight;
        if (intList[i] > sumOfBothNeighbors){
          bFoundOne = true;
          System.out.println("Value #" + i + ", " + intList[i] +
            ", is greater than the sum of its neighbors.");
        }
      }
 
      if (bFoundOne == false){
        System.out.println("Test failed, so nothing was printed.");
      }
    } else {
      System.out.println("Array too short to be tested.");
    }
  }

A basic template for a class definition

(This was a draft which I accidentally neglected to publish on November 3rd. I think the election distracted me!)
Generally speaking, a class definition will have:

  • Fields (data of various kinds, potentially including other objects)
  • Methods (functions):
    • Constructor methods
    • Accessor (getter) methods
    • Mutator (setter) methods

IceCreamCone yum;
 
void setup(){
  yum = new IceCreamCone(2, "Chocolate");
 
  yum.setNScoops(3);
  // The right way: Use a mutator!
 
  yum.nScoops = 3;
  // The less polite way: direct access to the object's field.
  // This "could" throw an error if nScoops had been declared "private";
  // Processing lets you do this for complex reasons...
 
}
 
 
//==================================
class IceCreamCone {
 
  // FIELDS
  int nScoops;
  String flavor;
 
  //-----------------------
  // METHODS
 
  // accessors
  int getNScoops(){
    return nScoops;
  }
 
  String getFlavor(){
    return flavor;
  }
 
  // mutators
  void setNScoops( int n){
    nScoops = n;
  }
 
  void addAnotherScoop(){
    nScoops++;
  }
 
  // constructors
  IceCreamCone (int n, String f){
    nScoops = n;
    flavor = f;
  }
 
  IceCreamCone (){
    nScoops = 0;
    flavor = "";
  }
 
}

Object & Class REVIEW

Here’s a definition block for a class of Objects called “Thing”.

class Thing {
  int property;
  Thing(){
    property = (int)random(100);
  }
}

Declaring, allocating memory for, and initializing a single Object:

Thing someThing;
someThing = new Thing();

Copying the data from one Object into a new Object, in order to make a duplicate.
This is the least elegant way of doing this, since you need to reach inside an Object from outside in order to copy all of its fields:

Thing T2 = new Thing();
T2.property = someThing.property;
// repeat for all properties of a Thing....

Another way to create a duplicate Object is to make a “copy constructor”. Here, a Thing called someThing is used to make a new Thing.

Thing T2 = new Thing (someThing);
 
class Thing {
  int property;
 
  Thing(){
    property = (int)random(100);
  }
 
  // COPY CONSTRUCTOR:
  // This constructor for class Thing
  // copies the data from another Thing
  Thing (Thing thingToCopyFrom){
    property = thingToCopyFrom.property;
    // OR: this.property = thingToCopyFrom.property;
  }
}

A third way to create a duplicate object is to make a “factory method”. In this example, class Thing is extended yet again, this time to contain a factory method for producing duplicate Things. When it’s employed correctly, you can ask a specific Thing to give you a copy of itself.

Thing T2 = someThing.getCopy();
 
class Thing {
  int property;
 
  Thing(){
    property = (int)random(100);
  }
 
  Thing (Thing thingToCopyFrom){
    property = thingToCopyFrom.property;
  }
 
  // FACTORY METHOD:
  Thing getCopy(){
    Thing T = new Thing();
    T.property = this.property;
    return T;
  }
}

Declaring, allocating memory for, and initializing an array of Objects

int nThings = 10; // a helpful variable
Thing thingArray[]; // declaration of an array
 
// allocation of memory for the array
// (but not the objects themselves)
// -- only their placeholder spots.
thingArray = new Thing[nThings];
 
for (int i=0; i<nThings; i++){
  thingArray[i] = new Thing(); // create each object
}

A common pattern: an array which is only partially used. Memory for all of the objects (maxNThings) has been allocated, but you’re only drawing a certain subset of them (nThings).

// A common pattern is to maintain 2 numbers:
// (1) The total size of the array -- all of the allocated memory;
// (2) The number of elements in the array you're actually using.
//
// It is assumed that you are "using" a contigouous block
// of the lowest-numbered elements in the array, e.g. 0 through 7, etc.
 
int nThings = 7; // a helpful variable
int maxNThings = 10; // a helpful variable
 
Thing thingArray[]; // declaration of an array
thingArray = new Thing[maxNThings];
for (int i=0; i<maxNThings; i++){
  thingArray[i] = new Thing(); // creating each object
}

Adding a new element to the end of an array, assuming the array has room allocated for it.

// Adding a new element to the end of an array,
// assuming the array has room allocated for it.
if (nThings < maxNThings){
  thingArray[nThings] = new Thing();
  nThings++;
}

How to insert a new Object into the MIDDLE of an array, moving the higher-numbered items further down the array.

  Thing thingToInsert = new Thing();
  int indexToInsertItAt = 4;
  if (indexToInsertItAt < maxNThings){
 
    // First, move the other elements further down the array.
    // note that this effectively loses/destroys the data
    // previously stored in the last element in the array.
    for (int i=(maxNThings-1); i>indexToInsertItAt; i--){
      thingArray[i] = thingArray[i-1];
    }
    // now, insert the new Thing.
    thingArray[indexToInsertItAt] = thingToInsert;
    // update the nThings.
    if (nThings < maxNThings){
      nThings++;
    }
  }
  int indexToRemoveThingFrom = 4;
  if (indexToRemoveThingFrom < nThings){
 
    // copy the higher-numbered items down into lower-numbered slots.
    // this has the effect of clobbering the Thing at indexToRemoveThingFrom.
    for (int i=indexToRemoveThingFrom; i<(nThings-1); i++){
       thingArray[i] = thingArray[i+1];
    }
  }
  if (nThings > 0){
    nThings--;
  }

Instead of re-numbering Objects in an array, moving around Objects in an array can also be achieved with a copy function (like the one I described above). There are some subtle differences in using this technique, which are less evident in Java and much more significant in C++; don’t worry about this for now.

University Course Assessments…

Dear Students,
The University Course Assessment (UCA) is now open for Fall courses. I really care about your feedback, and so does the school. Please take a few minutes to fill out the form by going here:

Link to the Carnegie Mellon portal at https://my.cmu.edu/site/main/page.academics
and click on University Course Assessment under Courses.
Regards,
Golan

Factory Methods!

 
void setup(){
  Thing T1 = new Thing(1);
  Thing T2 = T1.getBiggerThing();
  Thing T2prime = T2.getVerySimilarThing();
 
 
  Thing T1duplicate = new Thing(T1);
  println("The property of T1duplicate = " + T1duplicate.property);
}
 
 
class Thing {
  int property;
 
  //constructor
  Thing (int p){
    property = p;
  }
 
  //copy constructor
  Thing (Thing originalThing){
    this.property = originalThing.property;
  }
 
  // factory method
  Thing getVerySimilarThing(){
    return new Thing(property);
  }
 
  // factory method
  Thing getBiggerThing(){
    return new Thing(property+1);
  }
}