Starting from:
$30

$24

P04 Carrot Patch

This assignment involves the development of a graphic application from the scratch. This will give you practice with implementing interfaces, and de ning an hierarchy of classes including super classes, and subclasses. We’ll also work on improving the organization and clarity of your code. Having this programming assignment as reference, you will also be able to develop your own graphical application using the processing library, from the scratch. We no longer need to use the Utility class provided for you in the p2core.jar le in P2. The CarrotPatch graphic application de nes di erent graphic components which can be drawn to the display window. We distinguish:

    • Carrots which are non interactive images. They do not react to the mouse events or to key pressed by the user.

    • Interactive objects such as buttons and animals (rabbits and wolves). These graphic objects are GUI listeners objects which react to the mouse events or speci c key pressed. They de ne common properties and common behaviors. But they act di erently in the patch. Each animal/button has a speci c behavior indeed. We are going to de ne and implement these similarities and di erences in this assignment.

A screenshot of what the display window of this Carrot Patch application may look like after you have completed this assignment is shown in Fig.1. A demo of this application is provided soon in this video.


Learning Objectives

The goals of this assignment include:

    • Experience organizing code in an object oriented fashion that takes advantage of inheritance relationships between your classes.

    • Use of inheritance and interfaces to better organize your code in a more clear and concise manner. Students will also enjoy the power of polymorphism.

    • Learn how to use PApplet class de ned in the processing graphic library directly to develop a graphic application from the scratch, rather than through a provide .jar wrapper le.

    • Gain experience with writing tests to assess the correctness of your program. All developed test methods will be run with graphic mode disabled and would assert the correctness of speci c methods in your code.

©2021 Kacem & LeGault - University of Wisconsin - Madison.


































2


Additional Assignment Requirements and Notes

    • The only import statements that you may include in your project’s classes are:

import java.io.File;

import java.util.ArrayList; import java.util.Random; import processing.core.PApplet; import processing.core.PImage;

    • The automated grading tests in gradescope are NOT using the full processing library when grading your code. These tests only know about the following elds and methods (referenced directly from this assignment). If you are using any other elds, methods, or classes from the processing library, this will cause problems for the automated grading tests. Such references must be replaced with references to one or more of the following:

{ PImage: the two  elds int width, and int height.

{ PApplet: the three  elds int mouseX, int mouseY, and boolean mousePressed.

{ Five methods from PApplet: PImage loadImage(String), void image(PImage,int,int), void size(int,int), void getSurface().setTitle(String), and void main(String).

    • You are NOT allowed to add any constant or variable not de ned or provided in this write-up outside of any method.

    • You are NOT allowed to add any public method (static or instance) not de ned in this write-up.

    • Overriding a method does not mean adding a new public method not de ned in the write-up. Feel free to override any public behavior implemented in a superclass, if needed.

    • You CAN de ne local variables that you may need to implement the methods de ned in this program.

    • You CAN de ne private static methods to help implement the di erent public methods de ned in this write-up, if needed.

    • Do NOT submit the following source les to gradescope: ListenerGUI.java, Button.java, and Carrots.java.

    • You MUST adhere to the course’s Academic Conduct Expectations and Advice.

    • All implemented methods including the overridden methods MUST have their own javadoc-style method headers, with accordance to the CS300 Course Style Guide.





3


    • Getting Started

Start by creating a new Java Project in eclipse. You can call it P04 Carrot Patch for instance. You must ensure that your new project uses Java 11, by setting the \Use an execution environment JRE:" drop down setting to \JavaSE-11" within the new Java Project dialog box. Do NOT create a project-speci c package; use the default package.


Download the images and processing core.jar

Next, download this P4Distributables.zip le, and extract the contents of this archive le directly into your P4 project folder. This should add:

    • a core.jar le which is part of the processing graphical library. You are welcome (but not required) to read more about here. If this .jar le does not immediately appear in the Project Explorer, try right-clicking your project in the project folder and selecting \Refresh" to x that. To use of the code within this jar le, you’ll need to right-click on it within the Project Explorer and choose \Add to Build Path" from the \Build Path" menu.

    • a folder of images which contains the four following les: background.png, carrot.png, rabbit.png, and wolf.png. The core.jar le .

The result of this operation on the Package Explorer is illustrated in Fig.2.


























Figure 2: Eclipse Package Explorer



4



    • Create the CarrotPatch main class and download the supportive code

Create a new class called CarrotPatch which includes a main() method. Your CarrotPatch class MUST inherit from a class de ned the core.jar le called PApplet (You’ll need to import processing.core.PApplet for this to work). This makes your CarrotPatch class to BE of type PApplet. PApplet models the Processing window for a graphic application or program. It provides good ways to create a new window and draw graphics onto it. Note that in your whole graphic application, only ONE PApplet object must be used. It is an instance of this CarrotPatch class. All the visible and interactive objects including images which will be de ned in this application will be drawn in this CarrotPatch PApplet object.


2.1    CarrotPatch’s main() method

Now, de ne a main method to include only the following single statement.


PApplet.main("CarrotPatch"); // do not add any other statement to the main method

    • The PApplet.main() method takes a String input parameter which represents

    • the name of your PApplet class.


This should result in a program that opens a small window when it is run. We won’t be adding anything more to this main method for the rest of this assignment.


2.2    Download the supportive code

For this assignment, we give you a supporting code that you will start working on it and extend it. Download each of the following les and make sure they are included in the same project directly inside the default package in the src folder. If they do not immediately appear in the Project Explorer, try right-clicking your project in the project folder and selecting \Refresh" to x that.

    • interface GUIListener (GUIListener.java)

    • class Button (Button.java)

    • class Carrots (Carrots.java)


2.3    De ne the CarrotPatch data    elds

Your CarrotPatch class must contain the following instance data elds at the top of the CarrotPatch class outside of any method.




5



    • backgroundImage: private instance eld of type PImage. It represents the background image of this application. (You’ll need to import processing.core.PImage).

    • objects: protected instance eld of type ArrayList < GUIListener >. It stores all the interactive objects which will be de ned in this CarrotPatch graphic application.


Do NOT initialize any of the above data elds where they are de ned. They will be initialized in the setup() method.


2.4    De ne the CarrotPatch methods

Your CarrotPatch class must contain and override the instance methods de ned in the following text le. There are ve callback methods from the PApplet class to override: setup(), draw(), mousePressed, mouseReleased(), and keyPressed. Note these methods are used in a similar fashion to the setup (called once at the beginning of our program), draw (called repeatedly while the program runs) mousePressed (called each time the mouse is pressed), and keyPressed (called each time a key is pressed) methods from P2 Memory Game. Notice that with respect to P2 implemented using procedural programming, this CarrotPatch class which extends PApplet is implemented based on the Object-oriented programming paradigm. All the callback methods are instance methods (versus static methods in P2). Some other PApplet methods are new such as settings() and some graphic setting features implemented in the private method CarrotPatchSettings() called in the setup() method).

In addition to the callback methods, the CarrotPatch class de nes an instance method called removeAll which removes all carrots and animal objects already present in the patch. We are going to complete the implementation of the missing code (see TODO tags) as we go throughout this write-up.


2.5    Initialize the CarrotPatch instance    elds

To start, initialize the objects list to an empty ArrayList in the setup() method. Then, load the background image in the setup() method using PApplet.loadImage() method as follows.

backgroundImage = this.loadImage("images" + File.separator + "background.png");

Then, draw it to the center of the screen at the beginning of the draw method using the using the PApplet.image() method as follows.

this.image(backgroundImage, this.width / 2, this.height / 2);

Recall that the setup() method is a callback method called only one time when the graphic application starts. Now, running this program will now result in a window showing the background image as depicted in Fig.3. Next, let’s explore the other provided source les before we proceed.

6























Figure 3: Carrot Patch Background Screen

    • Explore the supportive code

3.1    GUIListener interface

Our P04 Carrot Patch program is a graphical application which interacts with the user via a Graphical User Interface (GUI). For instance, our program waits for a user input as one of the following events: press on the mouse button, release the mouse, drag an image, etc. Then, when such event is detected, a particular method is invoked.

Our application will contain di erent graphic objects (buttons and animals as shown above in Fig.1). These objects will be drawn repeatedly to the display window. They will listen to the mouse events and must react appropriately to them each time the mouse is pressed or released. To avoid redundancy and promote abstraction in our code, we de ned the interface GUIListener (GUI refers to Graphic User Interface). You can notice that this interface contains the signatures of the following methods ONLY without any implementation details.


public interface GUIListener {

public void draw(); // draws this interactive object to the display window public void mousePressed(); // called each time the mouse is Pressed public void mouseReleased(); // called each time the mouse is Pressed

public boolean isMouseOver(); // checks whether the mouse is over this GUIListener object

}


Recall that an interface cannot be constructed. We can de ne a reference of type GUIListener.

It can store the reference to any object instance of a class which implements this interface.




7



3.2    Button class

You can notice from the nal display window for our CarrotPatch application shown in Fig.1, that we are going to add four buttons \Plant Carrots", \Add Rabbit", \Add Wolf", and \Restart". All these buttons will de ne a similar state (data elds) and share similar functionalities. Therefore, we created the class Button to serve as the base class (aka super class) for each of the speci c Button classes that we will create later in this assignment. Each button will be drawn to display window, listen and react to the mouse events. Therefore, the class Button implements our GUIListener interface and overrides all its methods.

Note that the Button class contains the following    elds.


private static final int WIDTH = 85; // Width of this Button private static final int HEIGHT = 32; // Height of this Button

protected static CarrotPatch processing; // PApplet object where this button // will be displayed

private float[] position; // array storing x and y positions of this Button // with respect to the display window

protected String label; // text/label that represents the name of this button


Notice carefully that the Button class de nes one protected static eld named processing of type CarrotPatch. It represents the graphic display window of this application where all the buttons will be drawn and will operate. It is protected. So, it is directly visible to all the subclasses of the class Button.

This class implements two constructors, a static setter method to set the processing eld, and overrides the four methods de ned in the GUIListener interface. Make sure to read through the class de nition of the Button class and its implementation. To help you further understand the code for drawing a button, we note that we used the following processing methods de ned in the PApplet class.

    • rect(): This is the processing method for drawing a rectangle. It takes four parameters:

        1) the x-position of the upper left corner, 2) the y-position of the upper left corner,

        3) the x-position of the lower right corner, 4) the y-position of the lower right corner. These corner positions must be calculated so that the button appears centered around it’s position eld with the appropriate WIDTH and HEIGHT.

    • ll(): This method is used to set the drawing color. When the mouse is over a button, its lling color is set to dark gray by calling ll(100), and when the mouse is not over this button, its lling color is set to light gray ll(200)

    • text():  This processing method is used to draw a text to the display window.  The

PApplet.text() method takes three parameters: 1) the string of text to draw, 2) the x-position that this text should be centered around, and 3) the y-position that this text should be centered around.

Note that since our CarrotPatch class extends PApplet. All these public methods de ned in

8



the PApplet class must be directly accessible through the Button.processing data eld of type CarrotPatch.


3.3    Carrots class

The Carrots class models a list of the carrots planted in the carrot patch. This class will not be instantiable. It de nes static data elds and implements static methods ONLY. The carrots will be visible objects in this patch (meaning instances of processing.core.PImage class). They do not interact with the mouse events. They are NOT GUIListener objects.

Notice that the Carrots class de nes one static eld of type CarrotPatch which represents the PApplet object where the carrots will be drawn. The Carrots class also de nes a perfect size array of the potential positions of the carrots in the display window and a perfect-size array of the planted carrots. We invite you to read through the provided implementation of the class Carrots and its di erent methods. Do not hesitate to contact your instructor or any of our consultants or post a question on piazza if you have a question about any of the provided methods.


3.4    Set processing for the Carrots and Button classes

Now, let’s set the processing CarrotPatch display window for the Carrots and the Button classes.

In the CarrotPatch.setup() method, call the Carrots.settings() and the Button.setProcessing() methods and pass them a reference to the current CarrotPatch object (which is the reference this).



    • Create and add speci c buttons

Now Create the four following classes. They MUST extend the Button base class. This makes them all of type GUIListener since the Button class implements that interface.

    • PlantCarrotsButton extends Button

    • AddRabbitButton extends Button

    • AddWolfButton extends Button

    • RestartButton extends Button

All these classes must de ne the following instance methods. No speci c data elds are de ned in these classes.

    • One constructor which takes two oat variables as input parameters. The rst oat represents the x-position of the button. The second oat represents the y-position of the


9



button. Each of these constructors calls the constructor of the superclass Button(String, oat, oat). The String labels of the four speci c buttons are as follows:

{ \Plant Carrots" for the PlantCarrotsButton, { \Add Rabbit" for the AddRabbitButton,

{ \Add Wolf" for the AddWolfButton, { \Restart" for the RestartButton,

    • Only the public instance method mousePressed() must be overridden in each if the 4 speci c button classes. At this stage, you can add a speci c print statement which will be displayed to the console (not on the graphic display window) when the mouse is pressed and is over each speci c button. For instance, this can be an implementation of PlantCarrotsButton.mousePressed() method. We are going to change it later.

if (isMouseOver()) {

System.out.println("Plant Carrots Button Pressed");

}


Now, instantiate in your CarrotPatch.setup() method the following four buttons and add them to the objects ArrayList. Recall that the Button class implements the GUIListener.

    • an instance of PlantCarrotsButton at position (43, 16),

    • an instance of AddRabbitButton at position (129, 16),

    • an instance of AddWolfButton at position (215, 16),

    • an instance of RestartButton at position (301, 16); where position(x,y) represents the x-and y-coordinates where the related button will be placed in the screen display window.

Note that each reference of type Button or its subclasses can be safely cast to the type GUIListener and stored in the objects ArrayList.


4.1    Click on buttons

To use these buttons, we have to update rst the implementation of the CarrotPatch.draw(), CarrotPatch.mousePressed(), and CarrotPatch.mouseReleased() methods as follows.

    • In the CarrotPatch.draw() method, after drawing the background image, draw the planted carrots rst by calling Carrots.draw() method. Then, traverse the contents of the ArrayList objects and draw each of the interactive objects stored there.

    • In the CarrotPatch.mousePressed() method, traverse the ArrayList objects and call the mousePressed() method of the rst clicked element ONLY.

10



    • In the CarrotPatch.mouseReleased() method, traverse the ArrayList objects and call the mouseReleased() method of every element stored in the list.

Running the program will result in the display window comparable to the one provided in Fig.4 where the buttons have been clicked in this order: (1) \Plant Carrots", (2) \Add Rabbit",

    (3) \Add Wolf", and (4) \Restart". Notice that clicking on the di erent buttons will print the speci c behavior implemented in the mousePressed of each button. Notice the power of polymorphism. Even though the arraylist objects stores elements of type GUIListener, each element performs di erently with respect to the implementation of the mousePressed() method overridden in its most speci c type.




























Figure 4: CarrotPatch with 4 buttons



4.2    Update the implementation of PlantCarrotsButton.mousePressed()

Now, you can implement the speci c behavior of the PlantCarrotsButton when clicked. You can comment the print statement in the PlantCarrotsButton.mousePressed() method and instead call the Carrots.plant() method which is going to plant carrots in all the available spots within the Carrots.carrots array. Before checking whether this code will work or not, double check that the Carrots.draw() method call is added to the CarrotPatch.draw() method just before drawing the interactive objects stored in the objects arrayList.

This done, running your program and then clicking on the \Plant Carrots" button should result in a display window comparable to the one shown in Fig.5.


11






































Figure 5: Plant Carrots Button Clicked

    • Create Animal base class

Now create a new class called Animal. This class MUST implement the GUIListener interface. It plays the role of a base class of any speci c animal type such as Rabbit and Wolf which will be implemented in the next steps of this assignment. The class Animal de nes the following data elds.


private static Random randGen = new Random(); // Generator of random numbers

protected static CarrotPatch processing; // PApplet object representing the display window protected PImage image; // image of this

protected String label; // represents the name/identifier of this animal private int x; // x-position of this animal in the display window private int y; // y-position of this animal in the display window

private boolean isDragging; // indicates whether the animal is being dragged or not private int oldMouseX; // old mouse x-position private int oldMouseY; // old mouse-y position






12



It also de nes the two following constructors (available on this supportive source    le).


/**

    • Creates a new Animal object positioned at a given position of the display window

    • 
    • @param processing  PApplet object that represents the display window

    • @param xx-position of the image of this animal in the display window

    • @param yy-position of the image of this animal in the display window

    • @param imageFileName filename of the animal image

*/

public Animal(int x, int y, String imageFileName) {

// Set Animal drawing parameters

this.x = x; // sets the x-position of this animal this.y = y; // sets the y-position of this animal this.image = processing.loadImage(imageFileName); isDragging = false; // initially the animal is not dragging

}

/**

    • Creates a new Animal object positioned at a random position of the display window

    • 
    • @param processing  PApplet object that represents the display window

    • @param imageFileName filename of the animal image

*/

public Animal(String imageFileName) {

this(randGen.nextInt(processing.width), Math.max(randGen.nextInt(processing.height), 200), imageFileName);

}


In addition, we provide you with the implementation of the GUIListener.draw() method and a few setter and getter methods in this text le. Read carefully through the implementation of the method Animal.draw(). Try to understand how the behavior of dragging an animal such that it follows the mouse moves when clicked and dragged has been implemented.


Override GUIListener abstract methods

The class Animal MUST override all the abstract methods de ned in the GUIListener. Therefore, you MUST override on your own the following methods.


public boolean isMouseOver() {} // checks whether the mouse is over this animal

public void mousePressed() {} // starts dragging this animal by setting its isDragging

    • field to true if the mouse is pressed and is over this animal public void mouseReleased() {} // stops dragging this animal by setting its

        ◦ isDragging field to false




13



Animal class additional behaviors

Besides, the Animal class de nes the following behaviors. Implement the two versions of the overloaded method isClose() with respect to their speci cation provided in their javadoc style method headers comments. Notice that a method called distance to compute the euclidean distance between the current animal and a given (x,y) position was provided for you. DO NOT make any change to the action() method. A default animal does not perform any action in this CarrotPatch application. This method must be overridden by the derived classes. Note that

every animal has a continuous behavior. Therefore, call action() method from the Animal.draw() method.


/**

    • Checks whether this animal is within a distance range with respect to a

    • given (x,y) position. It returns TRUE if this animal is located within a

    • range distance [0 .. range] around the provided position and FALSE otherwise.

    • 
    • @param x a given x-position

    • @param y a given y-position

* @param range    radius of the neighborhood range from the given (x,y) position

    • @return true if otherAnimal is close to this animal with respect to range

*/

public boolean isClose(int x, int y, int range) { // TODO implement this method

}

/**

    • Checks whether this animal is within a distance range with respect to anotherAnimal.

    • It returns TRUE if otherAnimal is located within a range distance [0 .. range]

    • around the current animal and FALSE otherwise.

*

* @param otherAnimal an animal to check if it is close to this animal

* @param range    radius of the neighborhood range from the position of this Animal

    • @return true if otherAnimal is close to the current tiger

*/

public boolean isClose(Animal otherAnimal, int range) { // TODO implement this method

}

/**

    • Continuous behavior performed by this animal in the carrot patch

*/

public void action() {

// This method should be overridden by a subclasse

}




14



Set the processing    eld of the class Animal in the CarrotPatch.setup() method

Notice also that all the animal objects share the same static eld processing of type CarrotPatch which stores the reference to the PApplet display window of this application. Make sure to call the Animal.setProcessing() method in the CarrotPatch.setup() method to set the processing eld of all animals to the current CarrotPatch object this.


    • Create and implement Rabbit class

Now, let’s create the class Rabbit. This class represents the Rabbit animal. It MUST extend the Animal class. Rabbits can be added to randomly positions to the CarrotPatch application. They can move in the patch. They watch out for wolves and when they are clicked they make one hop towards a carrot. They also eat carrots. Every created Rabbit has their own label in the format R#. The rst created Rabbit is labelled R1, the second R2, the third R3, and so on.


6.1    De ne Rabbit’s data    elds, constructor, and getter methods

Here is a list of the data elds, and a provided implementation of the constructor of the class Rabbit. Note that the constructor of the class Rabbit creates a new Rabbit located at a Random position of the display window and initializes its instance elds.


private static final String RABBIT = "images"+ File.separator + "rabbit.png"; private static final String TYPE = "R"; // A String that represents the rabbit type

private static int hopStep = 70; // one hop step

private static int scanRange = 175; // scan range to watch out for threats private static int nextID = 1; // class variable that represents the identifier

// of the next rabbit to be created

private final int ID; // positive number that represents the order of this rabbit

/**

    • Creates a new rabbit object located at a random position of the display window

*/

public Rabbit() {

    • Set rabbit drawing parameters super(RABBIT);

    • Set rabbit identification fields ID = nextID;

this.label = TYPE + ID; // String that identifies the current rabbit nextID++;

}


15





    • getter of Rabbit.scanRange static field public static int getScanRange() {}

    • getter of Rabbit.hopStep static field public static int getHopStep() {}




6.2    Add new Rabbits to the carrot patch

Before implementing the speci c behaviors related to Rabbit objects, let’s try to add new Rabbits to our CarrotPatch. To do so,

    1. Update the AddRabbitButton.mousePressed() method such that a new instance of the Rabbit class is created and added to the CarrotPatch.objects arraylist each time the mouse is pressed and is over a AddRabbitButton object. Notice that the objects array list is a protected instance eld accessible directly using the Button.processing static eld visible to the AddRabbitButton class.

    2. Update the CarrotPatch.keyPressed() method such that a new Rabbit is added to the CarrotPatch’s objects array list each time the R-key is pressed.

Now, if you run your program, a new Rabbit will be added to the carrot patch graphic display window at random positions each time the R-key is pressed or the \Add Rabbit" button is clicked. The Fig.6 shows an example of this application run at this level.

Note also that even though you did not make any further change to the program, the added rabbit objects respond to the mouse events. These behaviors have been already implemented in the Animal class and Rabbit IS-An Animal. If the rabbits do not follow the mouse moves when they are dragged, review your implementation of the Animal.isMouseOver(), Animal.mousePressed(), and Animal.mouseReleased() methods.


    • Create and implement Wolf Class

Now create a new class called Wolf which extends the Animal class. This class models wolves objects in the CarrotPatch. Wolves are looking for rabbits in the patch to eat them.


7.1    De ne the Wolf’s data    elds

The class Wolf de nes the following data    elds.


// path to the wolf image file

private static final String WOLF = "images" + File.separator + "wolf.png";


16






































Figure 6: Rabbits in the Carrot Patch


private static int scanRange =
120; // scanning range to
look for a
rabbit


// in the neighborhood


private static int nextID =
1;
// identifier of the next
Wolf to be
created
private static final String
TYPE = "W"; // A String that
represents
the Wolf type
private final int ID; // positive number that represents
the order of this Wolf

private int rabbitEatenCount; // Number of rabbits that the current Wolf has eaten so far




7.2    Implement the constructor and getter methods of the Wolf class

Your Wolf class MUST de ne only one no-argument constructor which must create a new wolf and initialize its instance elds. Wolves are created at the same fashion of creating new rabbits. A new wolf is labelled W #. The rst created walf is named W1, the second is named W2, the third is named W3, and so on. Wolves will be created at random positions within the display window.



17




/**

    • Creates a new Wolf object at a random position of the display window

    • 
    • @param processing CarrotPatch object which represents the display window

*/

public Wolf() {}


In addition, implement the following getter methods.


public int getRabbitEatenCount(){} // gets rabbitEatenCount instance field public static int getScanRange(){} // gets the scanRange of a Wolf




7.3    Add new Wolves to the Carrot Patch

To add new wolves and display them to the CarrotPatch, update the CarrotPatch.keyPressed() and the AddWolfButton.mousePressed() methods as follows.

    1. Update the AddWolfButton.mousePressed() method to instantiate a new Wolf object and add it to the CarrotPatch.objects arraylist each time an AddWolfButton object is clicked.

    2. Update the CarrotPatch.keyPressed() method such that a new Wolf is created and added to the CarrotPatch’s objects array list each time the W-key is pressed.

Running the program and clicking on \Plant Carrots", \Add Rabbit", \Add Wolf" buttons, or pressing the R-key or W-key will result in an interactive interface comparable to the one shown in Fig.7. Notice that the animals (whether wolves or rabbits) drawn in the graphic display window can be dragged with response to the mouse moves. If two or more animals overlap, and the user tries to drag them, only the oldest animal added to the patch will be dragged.


7.4    Remove animals from the Carrot Patch

Now, implement removing an animal from the Carrot Patch when the mouse is over it and the "D-Key" is pressed. To do so, update the implementation of the CarrotPatch.keyPressed() method to implement this behavior. Traverse the objects list and remove the rst animal whose isMouseOver() returns true. Keep in mind that the objects list contains GUIListener references of di erent speci c types (buttons and animals). Make sure to consider only instances of the Animal class in your search.

After implementing this behavior appropriately, run your program and check whether a wolf or a rabbit is removed from the CarrotPatch each time the D-key is pressed while the mouse is over it.



18


































Figure 7: Rabbits and Wolves in the Carrot Patch

    • Implement RestartButton.mousePressed() behavior

Go to the CarrotPatch class and try to implement the CarrotPatch.removeAll() method with respect to its speci cation and the provided hints. Then, update the implementation of the RestartButton.mousePressed() behavior. When the mouse is pressed and is over the RestartButton button, all the planted carrots and all the animals must be removed from the CarrotPatch. Next, run your program and check whether this functionality works as expected.


    • Develop unit tests

Now that Rabbits and wolves can be added to the CarrotPatch, we can implement a few test methods to assess the correctness of the Animal.isClose() methods. Create a new class called CarrotPatchTester and add it to your project. This class MUST extend the CarrotPatch class and override its setup() method.

You can download the starter code for the CarrotPatchTester here. We provide you with an example showing how to de ne test scenarios for test1isCloseMethod(). You can make calls to your test methods in the overridden setup() method. Feel free to reuse the provided



19



implementation verbatim in your CarrotPatchTester class. You can also inspire by these examples and de ne your own scenarios for that test method. You MUST implement the test2isCloseMethod() and test3isCloseMethod() test methods.

In the next sections, we are going to implement the speci c actions performed by Rabbit and Wolf objects in the CarrotPatch.


10    Implement the Rabbit speci c behaviors in the CarrotPatch

In the Carrot Patch, our rabbit objects implement the following two behaviors.

    • Each time a rabbit is clicked, it will make ONE hop step towards the rst available carrot in the carrot patch. If it reaches the carrot, it will eat it.

    • Each rabbit is going to watch for wolves in their scan range neighborhood. If a rabbit detects at least one close wolf, it displays a warning message on the graphic display window.


10.1    Rabbit hops toward a carrot when clicked

To implement this behavior, add the following method to your Rabbit class.


/**

    • Gets the first carrot in the patch. If the carrot is in the Rabbit

    • hopStep range, the rabbit eats it. It sets its position to the (x,y)

    • position of the carrot and the carrot will be removed from the Carrot Patch.

    • Otherwise, the rabbit moves one hopStep towards that carrot. If no carrot

    • found (meaning Carrots.getFirstCarrot() returns false),

    • the rabbit does nothing.

*/

public void hopTowardsCarrot() {

// get the first carrot

int[] carrot = Carrots.getFirstCarrot();

if (carrot != null) {

// TODO complete the implementation of this method

}

}


To help you implement this method, we recommend that you review the Carrots.getFirstCarrot() and Carrots.remove(int) methods. Besides, we provide you in the following with a hint on how to calculate the new position (newX, newY) of an object located at (oldX, oldY) position when moving towards a destination located at (destinationX, destinationY) position with a moveDistance. We denote the euclidian distance between destination and object before moving


20



by d. In our case, if a rabbit is going to make one hop towards a carrot as destination, hopStep is the moveDistance, and newX, newY will be its new (x,y) position after performing the ONE hop.

newX = oldX +
moveDistance  (destinationX
oldX




d




newY = oldY +
moveDistance  (destinationY
oldY




d




d = (int)Math:sqrt(dx  dx + dy  dy)

where dx = destinationX  oldX and dy = destinationY   oldY



Override the mousePressed() method in the Rabbit class

Once your hopTowardsCarrot() is implemented, override the the mousePressed() method in the Rabbit class. This will be a partial overriding as follows.


@Override

public void mousePressed() {

    • TODO

    • call the mousePressed defined in the Animal super class

    • call hopTowardsCarrot() method

}


Now, run your program, plant carrots, add at least one rabbit, then try clicking on one rabbit and check whether it will make one hop towards the rst carrot after each mouse click. If the rabbit reaches the carrot, it will eat it. It takes its position, and the carrot is removed from the patch. If you keep clicking on the rabbit (simple clicks without dragging it), the rabbit will hop towards the next carrots, and eats them one by one.


10.2    Override the Rabbit.action() behavior

We de ne the following action of a rabbit in the carrot patch. A rabbit will continuously scan the area around it watching for a threat (i.e. if there is at least one wolf located nearby). If so, it will react by displaying an alert message "WOLF!". We provide you in the following with the implementation of the Rabbit.action() method. To enable it, you must implement the watchOutForWolf() behavior.








21




/**

    • This method watches out for wolves. Checks if there is a wolf

    • in the Rabbit.scanRange of this Rabbit.

*

    • @return true if the current rabbit is close to at least one wolf

*/

public boolean watchOutForWolf() {

    • TODO complete the implementation of this method

    • Traverse the processing.objects arraylist checking

    • whether there is a wolf which is close by Rabbit.scanRange

    • of this rabbit.

return false;

}

/**

    • Watches out for a wolf and display a Warning message "WOLF!"

    • if there is any wolf in its neighborhood.

*/

@Override

public void action() {

if (watchOutForWolf()) {

// this.setScaredImage();

processing.fill(0); // specify font color: black

processing.text("WOLF!", this.getX(), this.getY() - this.image.height / 2 - 6);

}

}


Note that you do not need to call Rabbit.action() method. It is already called in Animal.draw() method. Polymorphism is MAGICAL!

To help you assess the correctness of your Rabbit.watchOutForWolf() method, we provide you with the implementation of these test methods. You can use them verbatim in your CarrotPatchTester class and call them from the CarrotPatchTester.setup() method.


11    Implement the Wolf action in the CarrotPatch

In our carrot patch, we have HUNGRY wolves. Each wolf is looking for rabbits in its scan range to eat it. To implement this behavior, follow the following steps.







22



11.1    Implement eatRabbit() method

Add the following method eatRabbit() to the Wolf class and implement it.


/**

    • Moves to the position of the specified rabbit passed as input, and eats it.

    • The eaten rabbit will be removed from the patch and he number of eaten

    • rabbits by this wolf is incremented by one.

    • @param rabbit rabbit to eat by this wolf

*/

public void eatRabbit(Rabbit rabbit) {

    • if the mouse is over the current Wolf, release it so the Wolf can move

    • ahead to the position of rabbit and eat it.

if (isMouseOver())

this.mouseReleased();

    • TODO

    • 1. set the position of the current Wolf to the position of the rabbit

    • 2. remove the rabbit from the patch

    • 3. increment the number of eaten rabbits by one

}


To help you assess the correctness of your Wolf.eatRabbit() method, we provide you with the implementation of this test method. You can use it verbatim in your CarrotPatchTester class and call them from the CarrotPatchTester.setup() method. Feel also free to de ne further test scenarios.


11.2    Override action() method

Next, override the Wolf.action() method as follows.


/**

    • Defines the action of this wolf in the carrot patch. This wolf lookup for

    • rabbits in its neighborhood (Wolf.scanRange) and eats the first found rabbit

    • only. This method also displays the number of rabbit eaten by this wolf if any.

*/

@Override

public void action() {

// TODO

//Traverse processing.objects arraylist, search for the first rabbit which

    • is close to this wolf with respect to Wolf.scanRange, and eats it.

    • If no rabbit is found in the neighborhood, nothing will be done.

if (rabbitEatenCount > 0)

displayrabbitEatenCount(); // display rabbitEatenCount

}


23




/**

    • Displays the number of eaten rabbits if any on the top of the Wolf image

*/

public void displayrabbitEatenCount() { processing.fill(0); // specify font color: black

    • display rabbitEatenCount on the top of the Wolf’s image processing.text(rabbitEatenCount, this.getX(), this.getY() - this.image.height / 2 - 6);

}




12    Assignment Submission

Congratulations on nishing this CS300 assignment! After verifying that your work is correct, and written clearly in a style that is consistent with the CS300 Course Style Guide, you should submit your nal work through gradescope.com. The only NINE les that you must submit include: CarrotPatch.java, Animal.java, Rabbit.java, Wolf.java, PlantCarrotsButton.java, AddWolfButton.java, ResetButton.java, and CarrotPatchTester.java. Your score for this assignment will be based on your \active" submission made prior to the hard deadline. The second portion of your grade for this assignment will be determined by running

that same submission against additional o ine automated grading tests after the submission deadline. Finally, the third portion of your grade for your submission will be determined by humans looking for organization, clarity, commenting, and adherence to the CS300 Course Style Guide.



©Copyright: This write-up is a copyright programming assignment. It belongs to UW-Madison. This document should not be shared publicly beyond the CS300 instructors, CS300 Teaching Assistants, and CS300 Spring 2021 fellow students. Students are NOT also allowed to share the source code of their CS300 projects on any public site including github, bitbucket, etc.




Extra Challenges

Here are some suggestions for interesting ways to extend this CarrotPatch graphic application, after you have completed, backed up, and submitted the graded portion of this assignment. No extra credit will be awarded for implementing these features, but they should provide you with some valuable practice and experience. DO NOT submit such extensions via gradescope.

    1. Suggestion 1 { Try updating the way how a rabbit hops towards a carrot in the patch. Instead of moving forward the rst non null position in the Carrots.carrots array, the rabbit can move forward the closest carrot to its current position.


24



    2. Suggestion 2 { Try expanding the possible actions performed by a wolf or a rabbit in the carrot patch. Use your imagination!

    3. Suggestion 3 { Try creating new animal classes with di erent data elds and di erent behaviors. For instance, you can de ne birds which tweet and jump on the trees or y in the sky. Use your imagination!
























































25

More products