Week 7 -- Recursion, 2D Arrays
back to syllabusRecursive Functions
We've know that a function/method can call another function/method. We do this all the time when we write our function calls from the "main" or "setup" method. But can a function call itself?Functions that call themselves are called "recursive" and are appropriate for solving different types of problems. This occurs often in mathematical calculations; the most common example of this is with "factorial." If we remember, the factorial of any number
n! = 1 x 2 x 3 x 4 x . . .x n
0! = 1
We might write a function to do this in processing like:
int fact(int n) { int f = 1; for (int i = 0; i < n; i++) { f = f * (i+1); } return f; }but we can also define factorial as:
n! = n x (n-1)!
0! = 0
This is where the "recursion" or "self-reference" happens. N factorial is defined as N times N - 1 factorial. We can then write a function that does exactly this:
int fact(int n) { if (n == 0) { return 1; } else { return n * fact(n-1); } }The same principle can be applied to a drawing application. In the following example, the function "drawCircle" draws an ellipse based on a set of parameters, then calls itself with adjusted parameters. The result is a sequence of circles being drawn inside circles. The same result could have been achieved with simple iteratrion. . . Nevertheless, using recursion is an elegant solution.
// Recursion // by REASHere's another example of recursion. Here a "tree-like" structure is simulated. The functions draws a branch (i.e. a line) then calls itself to draw more branches from its endpoint (and so on and so forth. . .)// simplified DS int MAXLEVELS = 6; int x = 100; int y = 100; int level = MAXLEVELS; int radius = 100; void setup() { size(200, 200); background(0); colorMode(RGB, 255); ellipseMode(CENTER_RADIUS); drawCircle(x, radius, level); } void loop() { } void drawCircle(int x, int radius, int level) { noFill(); stroke(200); ellipse(x, y, radius, radius); if(level > 1) { level = level - 1; drawCircle(x - radius/2, radius/2, level); drawCircle(x + radius/2, radius/2, level); } }
// Recursion // DS int MAXLEVELS = 6; int x,y; int level = MAXLEVELS; void setup() { size(300, 300); colorMode(RGB, 255); background(0); x = width/2; y = height; } void loop() { framerate(1); background(0); //make call to recursive function once per loop drawBranch(x,y,level); } void drawBranch(int x, int y, int level) { //set color of branch stroke(200); //get random values for offsetting new branch int factor = 15; int x1 = int(random(-level*factor, level*factor)); int y1 = int(random(level*factor)); //draw branch (line) line(x,y,x-x1,y-y1); //set number of branches int no_branches = int(random(8)); //if we're not at the end recursively call this function to draw new branches if(level > 1) { level = level - 1; for (int i = 0; i < no_branches; i++) { drawBranch(x - x1, y - y1,level); } } }And here it is with bezier curves this time instead of simple lines. (only the recursive function is shown, the rest of the code is the same)
void drawBranch(int x, int y, int level) { //set color of branch stroke(200); //get random values for offsetting new branch int factor = 15; int x1 = int(random(-level*factor, level*factor)); int y1 = int(random(level*factor)); //get random values for offsetting bezier points int b1 = int(random(-level*factor, level*factor)); int b2 = int(random(-level*factor, level*factor)); int b3 = int(random(-level*factor, level*factor)); int b4 = int(random(-level*factor, level*factor)); //draw bezier curve bezier(x,y,x+b1,y+b2,x+b3,y+b4,x-x1,y-y1); //set number of branches int no_branches = int(random(8)); //if we're not at the end recursively call this function to draw new branches if(level > 1) { level = level - 1; for (int i = 0; i < no_branches; i++) { drawBranch(x - x1, y - y1,level); } } }CONTINUE ON TO 2. . .
back to syllabus