CS 161 Homework 8 - Dancing Turtles

Due Fri Apr 19 at 5:00pm

Overview

In this assignment, you will be creating a graphical animation of a turtle dance party. There can be lots of different kinds of dancers at the party--but since they all share some characteristics (e.g., they are all dancing turtles), we can use inheritance to easily create the program and avoid code duplication.

A sample dance party is below: Notice all the different kinds of dancers. In the center are a large group of turtles dancing a pre-specified routine--specifically, the red turtle is dancing the routine and all of the orange turtles are copying him. The black and pink turtles are dancing back and forth across the floor, and the green turtle is just twirling in the corner. Your program will be able to support all of these turtles (and more!)

This assignment should be completed individually. You are welcome to ask for help (either from me or from your classmates), but remember the Gilligan's Island rule!

Objectives

Necessary Files

You will need to download and extract the BlueJ project from the Homework8.zip file. This project will supply you with the following classes:

Finally, the project contains a README.txt file that you will need to fill out. Remember that you can open this file in BlueJ by double-clicking on the white paper icon!

Details

First, read through all of the assignment carefully. As you do so, think about what kinds of methods you might need, what kinds of variables you may want, and what kinds of functionality you will need.

For this program you will be making many new classes: specifically ones representing specific kinds of dancers. Many of these classes will extend either DancingTurtle or each other. I will describe each class you need below:

  1. DanceTester

    The first thing you should do is make a tester class to test and run your program as you develop it. Your tester should instantiate a DanceFloor and then use the addDancer() method to add turtles you create to it. Call startAnimation() on the DanceFloor in order to start the animation.

  2. TwirlingTurtle

    Let's start by making a very basic dancer to get started: the TwirlingTurtle (the green one in the above animation). This class should extend DancingTurtle in order to use its methods. While you will need to create constructors for the new class, you will not need to declare the instance variables, because you inherit them from the parent! Note that although the parent is abstract, you can re-use code by calling the parent's constructor using super(<params go here>).

    You will need to implement the abstract step() method inherited from DancingTurtle in order to give the turtle instructions on how to dance (an "abstract" method means that it is listed as something that children need to support, but the details aren't given. We will talk about this more as we go). A TwirlingTurtle should just turn 90 degrees in place for each step.

  3. RoutineTurtle

    Now you should be getting a feel for how inheritence works, so let's make a more complicated turtle: the RoutineTurtle. This turtle is like the TwirlingTurtle (it should also extend DancingTurtle) dances/steps by following a specified routine.

    A routine should be specified as a list of steps (consider: would it be easier to use an array or an ArrayList?). You should specify this list and then pass it as a parameter to the RoutineTurtle's constructor.

    • But how to specify the list? One option would be to make it a list of Strings (e.g., ["forward", "back", "left", "right"]). However, a cleaner way to do this would be to use constants: for example, you might make a FORWARD constant that is an int with a value of 1, a BACKWARD constant that is an int with a value of 2, etc. This makes it fast and easy to check which step you're on: if the step in the list is equal to FORWARD, then you can moveForward(). Thus means you can write routines as [FORWARD, BACK, LEFT, RIGHT], without needing to compare Strings (note that String comparison is much slower than integer comparison).
      • Moving 25 pixels at a time ended up working well for me, but you can of course change that. Try using a constant or a variable to specify the distance you move, instead of hard-coding it!
    • You might even make a separate class (e.g., DanceStep) to contain these constants. Then everyone could talk about DanceStep.FORWARD instead of having to make sure that Strings match perfectly. This kind of "constants class" (where the class just has static constants) is a really helpful patten to use when writing larger programs!
    • Finally, if you're making a constants class, you might consider using enumerated constants so you don't even need to assign integer values to the constants! Enumerated constants are described in Chapter 5.7 (page 266). This is not required, but might be fun!

    Overall, your RoutineTurtle should take in a list of dance steps. Then in its step method, you should get the next step in the list and perform that. When you get to the end of the list, go back to the beginning!

    • Note that you will need to keep track of which step you're on in the list, and then increment this counter each time you take a step. Hint: the modulo operator is a good way to cycle around! Try using math like i = (i+1)%listSize.
    • Extra Hint: the rest of the program will be slightly easier if you increment the step you're on BEFORE you perform it. So get the next step, then do that step. This means that you'll need to initially start at the -1th step, so that you can start by incrementing to 0 and then do the 0th step.

    This turtle can be complicated, so be sure to test him thoroughly! Note that your routine will be specified in the tester and then passed to the turtle.

  4. Leader

    The next thing you'll want to do is enable some turtles to lead other turtles (to give the other turtles directions about what dance steps to do). But you'll want multiple different kinds of turtles to be able to lead. As such, you will need to make a Leader interface that other classes can implement.

    Remember that interfaces only have method signatures, not method definitions. And then any class that implements the interface must define those functions. You're specifying that all Leaders can perform certain functions (methods)---the interface describes what those functions are.

    Your interface will likely include the following methods:

    • public Point getLocation() //so the leader can report its position to its follower(s)
    • public Point getDirection() //so the leader can report its facing to its follower(s)
    • public void addFollower(DancingTurtle) //so the leader can add a follower (who it will give steps to).
    • public void removeFollower(DancingTurtle) //so the leader can remove a follower

    Note that these methods can be inherited, which counts as being defined (since the child does have that method--even if they just got it from the parent!).

    Again, each leader might implement these differently. So the RoutineLeaderTurtle might be able to add multiple followers so it can lead a whole troop, while the TravelingTurtle might only be able to add one special follower.

  5. FollowingTurtle

    In order to have a Leader effectively lead, it will need a follower. So you will need to make a FollowingTurtle class that is intended to follow a leader. This class (like the others) should extend DancingTurtle

    • You should include a constructor for this turtle that takes in a Leader as a parameter. The follower should then set its position and facing to be immediately opposite of the Leader (75 pixels away from the leader's position was a good number for me). The constructor could also call the Leader's addFollower() method to add this follower to the leader!
      • Note that you may want other constructors as well that do NOT put the follower immediately in front of the leader---such as for making the line dancing turtles shown in the animation.
    • This turtle will need to define the step() method (why?), but this method shouldn't do anything! FollowingTurtles only move when ordered to by their leader; they do not step on their own!

    Be sure and test that the follower shows up on the dance floor and doesn't do anything without a leader.

  6. RoutineLeaderTurtle

    Now that you have a follower, you should make a leader class to lead them! In particular, you might start with the RoutineLeaderTurtle who can lead multiple followers in a routine (you can also start with the TravelingTurtle described below). This class should extend RoutineTurtle (since it will also do a Routine), but will also implement the Leader interface.

    • Note that you will need to make new constructor(s) for the RoutineLeaderTurtle that call the parent's constructor(s) using super().
    • You will need to implement all of the methods in the Leader interface. In particular, the addFollower() and removeFollower() methods should add followers to a list of followers who are given orders, so you can lead a whole troop.
    • In the step() method, your RoutineLeaderTurtle should first do the routine exactly like its parent! You should do this by calling the parent's step() method. This will allow you to reuse the parent's method and functionality without needing to rewrite code--instead just extending that functionality.
      • After you have done a step (using the parent's method), you should go through your list of followers and tell each of them to take that same step. You may consider abstracting the "given a command, do a step" functionality into a separate helper method to avoid code duplication.

    You can test this turtle by making followers and checking that they all dance in sync!

  7. TravelingTurtle

    The TravelingTurtle is a turtle who leads its dance partner across the floor, turning around when they get to the far side (the black turtle in the above graphic). This turtle should extend DancingTurtle and implement the Leader interface.

    • Start by making the basic constructors and filling in the required methods (just like with the previous turtles); test that you can make your TravelingTurtle show up!
    • Once that works, fill in the step() method to have the turtle walk across the floor. When it hits the other side (which you'll know because the moveFoward() method will return false), have it start walking backwards!
    • The turtle will also need to give instructions to the follower. If you don't have a follower, you might just stand still (or travel on your own; either way!) In your TravelingTurtle's step() method, you will also need to tell your follower to move in a certain way by calling the appropriate methods on that object. For example, if you want your follower to step forward, you will call the moveForward() method on the follower. Note that you can't just call the step() method (why? not)
    • In order to get your very own Fred & Ginger to waltz across the floor, consider the following algorithm:
      if I'm walking forward
        tell the follower to step backwards
        if the partner cannot step backwards
          change movement direction
        otherwise
          step forward after the follower
      otherwise if I'm walking backward
        step backwards
        if I cannot step backwards
          change movement direction
        otherwise
          tell the follower to step forward after me
      You can also make further changes to this: can you avoid pausing at the edges of the wall? Can you get the pair to spin around as they walk (like a in a Viennese waltz?

Some final notes:

Timeline

This assignment is sizable, likely bigger and harder than the previous two. There are a lot of parts (though each part may be somewhat small). GET STARTED EARLY so you don't run out of time!

Time is going to be tighter on this assignment, so don't put it off!

Submitting

Check and double-check that your program works, that your code is commented, and that your name is in the class comment at the top of your program!

Be sure to complete the provided README.txt file with details about your program.

Upload the entire BlueJ project to the Hwk8 folder on the submission folder on hedwig. Make sure you upload your work to the correct folder!. This assignment is due at 5:00pm on Fri Apr 19.

Be sure to include a tester class that shows off all your dancers!

Extensions

As always, there are many extensions to this assignment. Completing them can earn you up to 5 points of extra credit.

Grading

This assignment will be graded on approximately the following criteria: