CS300 P5: SWIMSIM (INHERITANCE) solved

$29.99

Original Work ?
Category: You will Instantly receive a download link for .ZIP solution file upon Payment

Description

5/5 - (1 vote)

This assignment involves reorganizing the code from your P4 Swim Sim (Exceptional) program to make use of inheritance, and then adding support for changing amounts of food. This food will be randomly added to the top of your simulation, and will then be removed from the simulation as it is eaten by fish. This is your final SwimSim-based assignment for this course, so be sure to keep it as clean and clear as possible.
Objectives and Grading Criteria
The goals of this assignment include refactoring existing code to make use of inheritance for code clarity and to reduce redundancy. You’ll make use of inherited fields and methods, explicitly calling constructors of a super class, and overriden methods. In addition to this refactoring, you’ll also be adding support for dynamic numbers of Food objects.
Grade Breakdown:
25 points
5 zyBooks Tests: automated grading test results are visible upon submission, and allow multiple opportunities to correct the organization and functionality of your code. Your highest scoring submission prior to the deadline will be recorded.
25 points
5 Hidden Tests: automated grading tests are run after the assignment’s deadline. They check for similar functionality and organizational correctness as the zyBooks Tests. But you will NOT be able to resubmit corrections for extra points, and should therefore consider and test your own code even more thoroughly.
LECTURE NOTES
GETTING STARTED
0. If it’s not already there, open the project containing your P4 code in Eclipse. Make a copy of this project and name this copy whatever you’d like, although P5SwimSim would be a descriptive choice.
REORGANIZING DATA AND CONSTRUCTORS
1. We are going to make use of inheritance to help make our code less redundant. Let’s start by creating a new base class called SimObject that our Fish, Food, and Hook classes can all be derived from. We’ll start by adding two protected int fields for the objects’ x and y positions to this base class. Remove the old x and y fields from the Fish, Food, and Hook classes to ensure that they are now using these inherited fields instead of the old ones. After this is working, remove the PImage and PApplet fields from our old classes, and use the protected fields inherited from our new SimObject class instead. 2. Since all of the SimObjects in our simulation (including all Fish, Food, and Hook objects) are all making use of the same PApplet reference, it seems wasteful to have some many copies of the same reference. Let’s consolidate these references by making the PApplet field in our SimObject class static. This single static “class field” is shared by any/all SimObjects. We used to pass this reference into every single new object upon construction. Let’s now change that by adding the following mutator method to our SimObject class:
This method should be called once, from the beginning of our SwimSimulation classes constructor. 3. Next we’ll create two SimObject constructors: the first takes only a string image path parameter, and the second takes this same string followed by additional int x and int y parameters (in that order). Notice that since the setProcessing() method takes care of initializing the PApplet reference for all objects, that we don’t need to worry about doing this on a per-object basis. We will however watch out for attempts to construct SimObjects without first calling setProcessing() to set this reference to a non-null value. At the beginning of each SimObject constructor, check whether the PApplet class field is null. When a null PApplet reference is found, your code should throw an IllegalStateException with the message: “SimObject.setProcessing() must be called before constructing any SimObjects.” When a non-null PApplet reference is found, the SimObject constructor should proceed to initialize its fields by 1) loading a PImage corresponding to the requested image path, and 2) initializing its position to the specified parameter values, or for the one-argument constructor: to a random position within the bound of the processing display.
1 2
// initialize the PApplet reference that is used by all SimObjects public public static static void void setProcessing(PApplet processing)
4. In order for your Fish, Food, and Hook classes to make use of these constructors, they’ll have to be called explicitly. While revising these constructors’ definitions, be sure to remove the PApplet processing fields from their parameter lists. After these constructors have been revised, make sure that they are being called properly from the SwimSimulation class. Your program should now be back in working order. If not, be sure to fix any existing problems before you proceed to the next step.
GROUPING COMMON FUNCTIONALITY
5. The distanceTo() methods in our Fish and Food classes are virtually identical, and this functionality seems like it could be useful from a variety of different SimObject type objects. So let’s move this definition from the Fish and Food classes into the SimObject class. 6. Although they are implemented in different ways, a common feature of our SimObjects is their ability to update themselves. To help us make use of this common ability, we’ll add an empty update method definition to the SimObject class, and have our Fish, Food, and Hook classes override this method’s implementation. 7. A common ability among our Fish and Hook classes (and possibly other SimObjects in the future) is to try to interact with another object. So let’s add the following empty method definition to our SimObject class:
Then we’ll refactor the tryToEat() and tryToCatch() methods in our Fish and Hook classes to instead override this new tryToInteract() method. Note that within this tryToInteract() method, we’ll need to check whether the SimObject that we are trying to interact with is of the correct type: Fish should only eat Food objects, and the Hook should only catch Fish. Updating your references in the SwimSimulation class from tryToEat() and tryToCatch() to tryToInteract() should bring your code back to working order.
Note that your SwimSimulation does not need to worry about the types of objects that it is attempting to help interact: it should call tryToInteract() on every SimObject (not just Fish and Hook) and with every SimObject as an argument of a different call (not just passing Food to Fishes or Fishes to the Hook). This simplifies the code in your SimObject, and also leaves us open to define additional kinds of interactions between objects within their respective classes in the futre.
USING SIMOBJECTS FROM SWIMSIMULATION
1 public public void void tryToInteract(SimObject other) { }
8. Instead of managing separate arrays of Fish and Food objects (not to method the Hook), let’s group all of these objects into a single ArrayList. Remove the Fish and Food array fields from your SwimSimulation class, and replace them with an ArrayList of SimObjects. If your file loading code relies on these arrays, your can either 1) refactor your file loading code to use the ArrayList field directly, or 2) pass local array references into any methods that need that access, and then later copy their contents into your ArrayList. You can either leave your hook reference in place to help handle mouse clicks, or you can iterate through the ArrayList to find the Hook object each time the mouse is clicked. DYNAMICALLY ADDING AND REMOVING FOOD
9. At the beginning of our SwimSimulation’s update method, let’s add a 1 in 20 chance (5% of updates) of creating a new Food object at a randomly chosen position along the top edge of our display. Notice how much easier this is to implement when we make use a dynamically resizing ArrayList. With the only Food[] organization, we’d need to create a new bigger array, copy reference from the old one into the new one, and then store the additional reference to the newly created Food object. 10. To help offset this influx of new Food objects, let’s start removing the Food objects that are getting eaten by Fish. But let’s implement this functionality in a general way that allows us to remove any kind of SimObject more easily in the future. Add a boolean protected instance field to the SimObject class to help track whether each object needs to be removed from the simulation. This field should be initialized to false (meaning that it does not need to be removed yet), and will then be set to true when an object needs to be removed. Also add a public accessor method to the SimObject class called shouldBeRemoved() that returns the value of this boolean field. We’ll have the SwimSimulation object take care of removing objects that should be removed in the next step. But before we get to that, go to your Food class’s getEaten() method and make sure that a result of calling any food object’s getEaten() method is that their shouldBeRemoved() method begins to return true instead of false. Removing the code from getEaten() that was moving eaten food objects to a random position along the top edge of the display, will help you see whether your solution to the next step is working or not. 11. Our final step is to remove all SimObjects that should be removed (according to their shouldBeRemoved() method) from our simulation at the end of the SwimSimulation’s update() method. Take some care in changing the contents of this ArrayList while iterating through it. The code snippet below demonstrates a common problem, that you’ll want to be sure to avoid in your solution. Trace through this code, and be certain that you understand how to avoid this problem before completing your P5 Swim Sim implementation.
1 2 3 4
// initialize list to contain the letters: h, i, p, p, o, p, o, t, a, m, u, s ArrayList list = new new ArrayList(); String String string string = “hippopotamus”; for for(int int i=0;i 12. Congratulations on finishing this final SwimSim-based CS300 assignment! After verifying that your work is correct, and written clearly in a style that is consistent with the course style guide, you should submit your work through zybooks. Note that if your classes contain extra fields beyond those described in this write-up, that may cause problems for some of our tests. If the automated tests detect defects in your code, you may fix those and re-submit for full credit, although you will need to wait an hour between submissions. The most recent of your highest scoring submissions prior to the deadline of 17:00 on Thursday, October 19th will be used as part of your score for this assignment. Additional grading tests will then be run against your highest scoring submission, to determine the rest of your assignment grade