YCP Logo Assignment 3: Random Art

Due: Tues, Feb 16th by 11:59 PM

Acknowledgment: The idea for this assignment comes from Christopher Stone of Harvey Mudd College.

Getting Started

Download CS350_Assign3.zip. Import it into your Eclipse workspace (File->Import...->General->Existing projects into workspace->Archive File). You will see a project called CS350_Assign3 in the Package Explorer.

Do not use java.util

In this course, you are required to implement all data structures from scratch. Do not use any of the classes in the java.util package.

Exception: You may use java.util.StringTokenizer.

Do not copy code from textbook or other sources

Some assignments in this course may involve data structures which are implemented by source code in the textbook. And, of course, lots of code is available from web sites and other sources.

I expect you to implement all data structures and algorithms from scratch, using your knowledge of how they work. Do not copy code from any source, including the textbook.

Exception: You may use any code explicitly posted on the course web site.

Your Task

You have two tasks:

  1. Implement a tree data structure
  2. Use the tree to represent "random" functions of variables x and y

The random functions in step 2 are used to create "random art". Here's the idea

x and y values are restricted to the range -1 to 1.

The random functions are built from operations which are guaranteed to produce values in the range -1 to 1.

The random art is created by generating three random functions: one for red, one for blue, one for green. Each pixel in a square region of the GUI window corresponds to an x,y coordinate in the 2x2 region of the x/y plane centered at the origin. Each pixel's color is determined by evaluating the three functions for the pixel's x/y values, and mapping each result to the range 0..255. This produces three color component values, which together determine the overall color of the pixel.

Here is an example:


The following primitive operations can be composed to create functions which produce values in the range -1..1 (as long as x and y are in the same range):

  • x
  • y
  • sin(π * _)
  • cos(π * _)
  • average(_, _, ...)

In the above operations, the placeholder "_" is any expression built from the same operations. Thus, operations are nested recursively to represent arbitrary functions.

Representing Functions as Trees

The random functions are represented of trees consisting of ExprNode objects.

The ExprNode class is defined as follows:

package edu.ycp.cs350.randart;

public abstract class ExprNode {
        // TODO: fields

        public ExprNode() {
                // TODO: initialize fields

        // TODO: methods for adding and accessing child nodes

         * Evaluate the function represented by this node
         * for the given x and y values.
         * @param x the value of the variable x
         * @param y the value of the variable y
         * @return the result of evaluating the function
        public abstract double evaluate(double x, double y);

         * Generate a textual representation of the function
         * represented by this node.
        public abstract String exprAsString();


The evaluate method evaluates the expression for given values of x and y.

The exprAsString method returns a string containing a textual representation of the expression.

You will need to modify this class so that child nodes can be added and accessed. You can use either a linked list or an array to store the references to the child nodes.

Important: I strongly recommend writing JUnit tests to test your ExprNode classes. An example JUnit test class called ExprNodeTest is provided; you may use this as a starting point for your tests.

Note that ExprNode is an abstract class. You will need to implement concrete subclasses that represent the 5 fundamental operations described above. The node types representing the variables x and y will be the leaves of the overall expression tree. The node types representing sin(π * _) and cos(π * _) expressions will each have a single child. The node type representing average(_, _, ...) expressions will have 1 or more children.

Examples: here are how two expressions would be represented as trees:

cos(π*sin(π*avg(cos(π*cos(π*sin(π*avg(y, y, x)))), cos(π*x))))

Generating "Random" Expression Trees

The ExprBuilder class is used to generate "random" expression trees. It is defined as follows:

package edu.ycp.cs350.randart;

import java.util.Random;

public class ExprBuilder {
        public static final int MAX_LEVEL = 8;

        private Random rand;

        public ExprBuilder() {
                rand = new Random();

        public ExprNode build() {
                throw new UnsupportedOperationException("TODO - implement");

You will implement the build method.

The following rules should be used to build random expression trees.

(1) Trees must have no more than MAX_LEVEL levels. The leaves of the tree are nodes representing x and y expressions (with equal probability). All nodes added at level MAX_LEVEL of the tree must be x or y nodes.

(2) For nodes at levels of the tree less than MAX_LEVEL, the following probabilities should be used to determine what kind of node to create:

  • 10% chance of creating an x node
  • 10% chance of creating a y node
  • 20% chance of creating an average(_, _, ...) node with 2 or 3 randomly-generated child expressions
  • 30% chance of creating a sin(π * _) node with a single randomly-generated child expression
  • 30% chance of creating a cos(π * _) node with a single randomly-generated child expression


Run the ArtFrame class as a Java application. The Generate! button generates a new random image.

As mentioned above, you should add JUnit tests to the ExprNodeTest class.


You grade is determined as follows:

  • Implementation of ExprNode and tree operations (adding/accessing child nodes): 30%
  • Implementation of ExprNode subclasses to represent expressions (evaluation, formatting as text): 30%
  • Building random expression trees: 40%


Export your finished project to a zip file (right-click on the project, then Export...->Archive File). Upload the zip file to the marmoset server as project assign3. The server URL is


IMPORTANT: after uploading, you should download a copy of your submission and double-check it to make sure that it contains the correct files. You are responsible for making sure your submission is correct. You may receive a grade of 0 for an incorrectly submitted assignment.