Category: COSC 1P02

  • Java Programming Homework

    Since lab exams start the week after reading week (labs from the 22nd–28th), I wanted to provide some practice homework. Please attempt these questions before looking at the solutions. The solutions may include in-file documentation that explains the reasoning behind them.

    Homework 1 (functions, for loops)

    Empty Java File Link (Contains a semi-setup environment for you)

    Create functions to draw various polygons — Equilateral Triangle, Square, and Circle — at a position (x, y) with a given size. Include an option to fill the shape (hint: use a boolean parameter). Your square function should be easily adaptable for drawing rectangles. Please assume that (x, y) represents the center of the shape.

    Next, make a function to draw a line from (x1, y1) to (x2, y2). This is easier than you might think!

    Idea and hints

    The goal of this exercise is to create a set of functions that operate independently of the turtle’s current position. If you don’t do that, it’s fine—but turtle graphics involves a lot of “hidden state.” What does that mean?

    If you call yertle.forward(), the turtle moves from its current position and angle. If you don’t know what those values are, the result is essentially random, right?

    As you’ll learn, managing state is a key part of programming. So it’s a good idea to start practicing how to minimize unnecessary state. By assuming nothing about the current state, we can decouple each function from the rest of the program.

    Consider using:

    • yertle.moveTo(x, y)

    Validate your output

    Example outputs

    Triangle:

    Drawing at 50, 50 of size 100 non-filled plus drawing at -50, -50 with size 100 should create a similar image. If your triangles are inverted, that’s fine.

    Square

    Drawing at the same position with the same size should look similar to this:

    Note: It should be trivial to turn these into rectangles.

    Circle

    Circles are trivial because the turtle provides the function for you.

    Lines

    It’s just a line between (-100, -100) and (100,100).

    Solution Link

    Homework 2 (compound functions, for loops)

    Java File

    For this exercise, take the square function from the previous homework (or use mine). Then, create a function that draws alternating colors of squares. You can choose any colors you like — even multiple ones! Your function can draw either along the x-axis or the y-axis.

    Finally, make a function that draws stacked rows of alternating colors. The result should look like a checkerboard pattern.

    Example output

    Solution Link

    Homework 3

    Basic Environment File

    For this homework, we’ll be combining two images into one. How you choose to do that is up to you! I recommend picking one of the algorithms from the table below — the solution will include examples for each of them.

    Since I don’t want to accidentally use copyrighted images, I’ll stick to ones I know are safe — mostly photos I’ve taken myself. Conveniently, that means I get to plug my photography a little… and more importantly, my dog!

    List of pictures I will be using.

    Feel free to use your own pictures!

    These pictures are also on the github for this homework.

    List of potential combination methods

    The size of the strips, checkerboard cells, etc., should be user-controllable.
    The list below is roughly ordered by difficulty:

    • Completely Random
    • Stripes (Either vertical or horizontal)
    • Perlin Noise (Ordered Random)
    • Checkerboard
    • Rings
    • Spiral
    Sample Outputs

    Random Mixing (Using custom noise function)

    Vertical Lines

    Horizontal Lines

    Checkerboard

    Diamond Board

    Rings

    Spiral

    Sin + Cos Blending

    Tangent based function

    Hidden Pattern

    Rings2

    Solutions

    The solution I’ve written for this exercise uses one of Java’s more complex features. I chose this approach because I wanted to experiment with different functions without duplicating a bunch of code.

    Once you start learning more advanced programming concepts — and, more importantly, truly understand them — you’ll see how powerful they can be. The features I’ve used here combine aspects of functional programming with Java’s lambda expressions. Working on this reminded me how enjoyable these tools are to use; as you’ll see in the solution, they make the code elegant and easy to extend. (And honestly, this isn’t even the best way to do it — just the quick version I put together before bed.)

    Solutions Link

    Java Lambda explanation

    Since this is a complicated topic that falls well outside the scope of anything you will do in your first and second years, let us break the problem down into sections.

    I implore you to look at a piece of code, even if you don’t understand it, and ask yourself:

    • Does any of this resemble code I’m familiar with?
      • What patterns or structures do I recognize?
        • e.g., loops, function calls, conditionals
      • Can I identify inputs and outputs?
        • You can see in the picture display what the code outputs
      • Where is data being transformed or reused?
        • Are variables being updated, passed around, or returned?

    Once you’ve asked those questions about a piece of unfamiliar code, can you infer what it is doing?

    Starting at the beginning.

    Let’s start with a basic function that uses features you’re probably already familiar with mixRandom().
    This function uses Math.random() to select between the two images.

    But wait — what’s that weird-looking syntax?
    Those are called lambdas, also known as anonymous functions. They let you define a function directly inside an expression. You don’t have to give it a name or associate it with a class (hence the “anonymous” part).

    You’ll also notice that you aren’t required to define the type of the variable. This is one of the reasons lambdas are so convenient.

    Of course, you can explicitly define the type as usual if you want.

    Next, you may have noticed that there are no parentheses. For single-line expressions that return a single value, they aren’t required. You can include them if you like — but then you’ll also need to add a return statement.

    All of this is equivalent to using a normal function and passing it in as a parameter.

    That approach, however, introduces a bit more syntax — in this case, what’s known as a method reference. Method references are also quite useful, but let’s stay on topic for now. Hopefully, you’re starting to see that lambdas aren’t scary; in fact, they make a lot of sense!

    Now let’s look at the function definition itself.

    Whoa — what’s going on here?
    The while loop probably looks familiar, but what about that parameter? That’s a BiFunction, something provided by the Java standard library. It allows us to say:

    We want a function that takes two parameters and returns a value.

    We then specify the types of those parameters and the return value. Inside the angle brackets (< and >), we tell Java exactly what those types are — ordered from left to right. In this case, we want a function that takes two int values and returns a double. This kind of declaration lets us define what’s called a generic interface, meaning:

    We don’t care what the function does, only that it meets these requirements.

    Hopefully, that makes sense — but if not, let’s peel back another layer.

    How Is BiFunction Implemented?

    Surprisingly, it’s quite simple! It doesn’t even define what the function does.
    That’s because it’s an interface — essentially a contract (or API) between you, the programmer, and the Java runtime. Interfaces allow you to make behavior generic and reusable. If you’re feeling a bit lost, I highly recommend reading more about Java’s object model — it’ll make this concept much clearer. Maybe I’ll make a separate post on it later.

    Hardwork 4

    This one is going to be a bit special since it will require using knowledge outside the scope of the class. This topic was far too interesting for me to pass up, so I hope you learn something!

    Feel free to skip this one.

    For this exercise, I want you to hide information inside an image. For a start, we could hide a string of text inside the image. You may be thinking, how?? Well, the answer is surprisingly simple.

    A semi-technical description

    To hide a string inside an image, we must define some kind of encoding. Assume we have a string of information of length n. If we assume this to be a normal Java characmake the change as necessary.
    ter, we know it takes 2 bytes to store this.

    RGB is a 24-bit standard; each color channel receives 8 bits, equivalent to 1 byte. You might see what I am getting at. But wait, if we replace the R and G color channels with our information, we could, in theory, store it; however, wouldn’t that result in a completely different appearance from the original image? Yes! Yes, it would! The solution to this is to spread out bytes over a series of pixels.

    If this sounds really complicated and outside the scope of this class, yes, it is. That’s why I called it hard work. You can complete but it may require some individual research.

    The method I have described is a rather basic way of hiding information. If you think this field is neat, consider looking into steganography.

    Solution

    Comprehensive Solution

    Simple Solution

    Challenge 1

    Create a program that can draw an arbitrary string. Since font loading is well outside the scope of this course, make dedicated functions for drawing each character of the English alphabet. You can use either uppercase, lowercase, or both.

    As we haven’t covered all the required topics yet, I’ve provided an example program file with everything you’ll need.

    Link to pre-setup Java file

    There’s no solution provided for this challenge — you’ll know if it works when it does!

    Most letters can be constructed from combinations of straight lines and circles. It may be easier to start with capital letters. The letters don’t have to be precise — focus on structure and consistency.

    Challenge 2

    Given a set of distinct integer points P, draw the convex hull of P

    (Explanation, algorithm, examples, and solution coming soon)

  • Introduction to Java Programming

    Example 1

    Disclaimer: Although I am a TA at Brock, this website is in no way funded or associated with the university. It is something I do in my spare time for fun.

    Before we begin, I want to say that if you are serious about learning programming, now is the time to put on your critical thinking hat. You cannot expect someone to hold your hand through every programming problem, so it’s best to start learning how to think about programs now. If something here doesn’t make sense, stop and think it through. Programming is 90% debugging, which comes down to learning how to think critically, modify your code, and repeat the process. If you still don’t understand, feel free to leave a comment or send me an email.

    In addition to critical thinking, learning how to Google is an essential skill. You don’t have to be great at it – just like you don’t have to be great at programming right away. It’s okay to fail and struggle; the important part is putting in the effort to improve. I don’t avoid using proper terminology in this article, and if you come across a term you don’t recognize, there’s a glossary at the bottom of the page. If that still doesn’t help, it’s the perfect opportunity to practice your Google-Fu.

    Programming languages are highly structured. Like human languages, they follow a set of rules, or a grammar. Unlike English, however, a compiler enforces that grammar strictly. Why? Think about it this way: if you wrote a program to do heart surgery and the program hit a line of code it didn’t understand, would you rather it stop immediately or guess what you meant? Exactly.

    The main function

    In Java, all programs start with a main function. The main function always takes an array of Strings, which represent arguments passed to the program.

    If you’ve never used the command line and have no idea what that means, don’t worry—you can ignore it for now. Just know that all Java programs must have a function named exactly like this, with this exact signature, in order to run:

    Java
    // In java all classes start with a captial letter
    public class Example1 {
    	public static void main(String[] args){
    	
    	}
    }

    The version of Java we are using doesn’t allow free-standing functions (functions outside of classes), so we must create a class to house our main function.

    BlueJ abstracts away the main function, but I think this leads to a counterintuitive view of how the program actually runs. More on this later.

    Variables

    Before we can run, we must first learn how to walk.

    In Java, all variable declarations follow the same general syntax:

    Java
    // Variable declarataion, no value assigned
    Type identifer;
    // what value is stored by default? depends on the type (see table below)
    
    // Variable declaration, new object created.
    Type identifer = new Type(...); 
    
    // Variable declaration, with assignment to a primitive
    primitive_type identifer = 0;

    Nearly all variables in Java will follow one of these three styles. Notice that they all share the same underlying pattern: type followed by identifier.

    A variable identifier is nothing more than a name for a location in memory. For primitives, this is often stored on the stack. For objects, it’s stored on the heap. When you use a variable, Java doesn’t care about the variable’s name—it cares about the value stored there. For primitives, Java copies the value. For objects, it passes around what’s called a reference copy. More on that shortly.

    Java Primitives

    Type NameDefault Value*Size (bytes)
    booleanfalse1
    byte01
    char02
    short02
    int04
    long08
    float04
    double08
    (any object)nulldepends

    Some of you may have noticed that a boolean takes 1 byte, even though it could theoretically fit in a single bit. The reason is that computers are optimized to work with bytes, not individual bits. On most systems, the smallest addressable unit is 1 byte, so storing a boolean as a single bit would actually take more work.

    This also means you can store multiple booleans in a single int (up to 32). This is done using bitwise operators, which I may cover in a future post. If you’re curious, look up bitsets.

    References & Reference-Copies

    When I say “reference copies,” I mean that all objects in Java are passed by reference. However, reassigning the reference inside a method does not change the variable in the outer scope. On the other hand, modifying the object itself (e.g., by calling its methods) does change the underlying memory, and any reference to that object will see the update.

    In other words: the underlying object is the same, but the variables pointing to it are not.

    If that still doesn’t make sense, consider the following example.

    Java
    // This is a pattern you will see a lot in Java.
    // It is often useful to store similar data together
    // along with functions which modify or use that data. 
    class MyExampleObject {
    	private String myStr;
    	private int myVal = 0;
    	
    	public MyExampleObject(String myStr) {
    		this.myStr = myStr;
    	}	
    	
    	public void print(){
    		System.out.println("I have been changed " + myVal + " times.");
    		System.out.println("My string contains '" + myStr + "'");
    	}
    	
    	public void set(String replacementStr){
    		this.myStr = replacementStr;
    		myVal++;
    	}
    }
    
    class Example {
    	public static void setReference(MyExampleObject str){
    		str = new MyExampleObject("Goodbye World!");
    	}
    	
    	public static void setMethod(MyExampleObject str){
    		str.set("Goodbye World!");
    	}
    
    	public static void main(String[] args) {
    		MyExampleObject strObj = new MyExampleObject("Hello World!");
    		
    		// prints:
    		// I have been changed 0 times.
    		// My string contains 'Hello World!'
    		strObj.print();
    		
    		// What do you think this will print?
    		setReference(strObj);
    		strObj.print();
    		
    		// How about this?
    		setMethod(strObj);
    		strObj.print();
    		
    		// Answer at the bottom of this page.		
    	}
    }

    The new operator

    You may have noticed the new operator used in the previous example. The reason for this is that all objects in Java must be allocated using new. This tells Java that you are requesting an object of that type.

    When you write new, Java:

    1. Allocates memory for the object.
    2. Finds the constructor for the class.
    3. Calls the constructor with the parameters you provided.
    4. Returns a reference to the new object.

    You can think of new as a special keyword used to invoke the class constructor and hand you back a reference.

    Quiz

    Let’s connect this to Lab 1. Here’s the basic setup code we used to create a turtle canvas:

    Java
    import brock.*;
    
    class Example {
    	public static void main(String[] args) {
    		// What are these lines doing, exactly?
    		TurtleDisplayer display = new TurtleDisplayer();
    		Turtle yertle = new Turtle();
    		
    		// How about this line? What is it doing?
    		// What about the variable, what kind is it?
    		// Why would we want that?
    		display.placeTurtle(yertle);
    		display.waitForUser();
    	}
    }

    Answers are at the bottom of the page. Hint: even if you don’t know exactly what the function does, you can infer from its name and location.

    Scopes and For-loops

    I’ve noticed some people struggling with the concept of for loops. Since it’s hard to explain them well in plain English, I’ll walk through scope first and then connect it to for loops with examples.

    Scope

    In Java, every control-flow structure (loops, if statements, etc.) introduces its own scope, called a block-level scope. A scope is defined by curly braces { ... }. You can nest scopes inside each other, and the nesting creates a hierarchy of visibility.

    Java
    // File-level scope: everything here belongs to the file.
    // Usually, the file contains a single class named the same as the file.
    
    class Example {
    	// Class-level scope: everything declared here belongs to the class.
    	
    	public static void main(String[] args) {
    		// Function-level scope: everything here belongs to the main function.
    		
    		{
    			// Nested block-level scope.
    		}
    	}
    }

    A variable declared in an outer scope is accessible inside inner scopes, but not the other way around:

    Java
    public static void scopesAreFun(){
    	int i = 2;// outer scope
    	
    	{
    		// one indent more!
    		int j = 10; // inner scope
    	}
    	
    	// what happens here?
    	System.out.println(i + j);
    }

    This fails to compile because j only exists inside its inner block.

    • Outer → inner: allowed
    • Inner → outer: not allowed

    This lets you limit variable access and even reuse variable names safely outside that scope.

    Variables declared inside a function disappear once the function ends.

    Java
    public static void scope1(){
    	int j = 20;
    }
    
    public static void scope2(){
    	// compile failure: j is not accessible in this scope.
    	System.out.println(j);
    }

    Variables declared in a class belong to objects of that class. Functions inside the class can access them—but there’s a catch.

    Java
    class Example {
    	public int i = 10;
    	
    	void print(){
    		// perfectly fine.
    		System.out.println(i);
    	}
    	
    	public static void main(String[] args){
    		// Compile error: i does not exist in static scope
    		System.out.println(i);
    	}
    }

    Why the error? Because static methods belong to the class, not an instance of the class. To access i, you need an object:

    Java
    class Example {
    	public int i = 10;
    	
    	void print(){
    		System.out.println(i);
    	}
    	
    	public static void main(String[] args){
    		Example e = new Example();
    		System.out.println(e.i); // works
    		e.print();               // works
    	}
    }

    For loops

    Now, let’s connect scope to loops.

    A for loop is really just a common while loop pattern written in shorthand.

    Java
    class Example {
    	// the following two functions are equivalent.
    	public static void whileLoop(){
    		int i = 0;
    		while (i < 10){
    			System.out.println(i);
    			i++;
    		}
    	}
    	
    	public static void forLoop() {
    		for (int i = 0; i < 10; i++){
    			System.out.println(i);
    		}
    	}
    }
    • In the while loop, you write initialization, condition, and increment separately.
    • In the for loop, all three parts are bundled together at the top, but the meaning is the same.

    for loops also introduce their own scope. In the example above, the variable i only exists inside the loop. Once the loop ends, i goes out of scope and cannot be used.

    That’s all for now. I have to head to the lab. In the next post, I will talk about classes, nested for loops, and probably more!

    Glossary

    Function

    A function is a block of code with a well defined calling interface (signature), and can be called multiple times. They allow us to take a large complicated problem and break it down into smaller more manageable parts, often representing one task or aspect of a program.

    Signature

    A signature is the defined inputs and outputs to a function. In Java, the inputs to functions are called parameters and the output is called a return value. Java functions only allow one return value, thus if you want to return multiple objects you must package it into some kind of container class.

    Initializers

    An initlaizer sets a variable to a specific value. Specifically variable assignment is called variable initalization if it is set when the varaible is created.

    Java
    // Initalization
    int i = 10;
    
    // Assignment
    i = 20;

    Operator

    Answers

    Example MyExampleObject

    In the above paragraph, I asked the question of what each method would do to the object. Here are the answers.

    Java
    // ...
    	public static void main(String[] args) {
    		MyExampleObject strObj = new MyExampleObject("Hello World!");
    		
    		// prints:
    		// I have been changed 0 times.
    		// My string contains 'Hello World!'
    		strObj.print();
    		
    		// I have been changed 0 times.
    		// My string contains 'Hello World!'
    		setReference(strObj);
    		strObj.print();
    		
    		// I have been changed 1 times.
    		// My string contains 'Goodbye World!'
    		setMethod(strObj);
    		strObj.print();
    		
    	}
    // ...

    If you were thinking about what I said, then this answer doesn’t surprise you. I wanted to make it clear the distinction that, although the object represented by the variable is the same, the variables themselves are not the same.

    Example Turtle Canvas

    Java
    // What are these lines doing, exactly?
    TurtleDisplayer display = new TurtleDisplayer();
    Turtle yertle = new Turtle();
    // A:
    // Constructs a TurtleDisplayer class and keeps a local reference to it
    // Constructs a Turtle class and keeps a local reference to it
    // There are no arguements passed to either class.
    // Thus, we can infer that the object is in a valid state without any input from us.
    // In the case of TurtleDisplayer, it will create a graphical window on your computer.
    		
    // How about this line? What is it doing?
    // What about the variable, what kind is it?
    // Why would we want that?
    display.placeTurtle(yertle);
    display.waitForUser();
    
    // A:
    // We notice that it is a function called "placeTurtle" which takes a turtle object. Since we can call commands directly on a turtle and have it draw to our screen, we know that this function must link the two classes together somehow. 
    // Why would we want that? Well, by coupling state together we can simplify the interface to use it. Instead of passing the display every time we do turtle.forward(10); we can just call it like that.
    // This is a concept which you sould understand, as it will come up when you have to make your own functions and classes.