Introduction to Computer Science CSC 2011 Laboratory Manual Mark A. Boshart © 2006 Mark Boshart Contents CSC 2011 Syllabi Lab 01: Getting Started Lab 02: Console I/O and Calculations Lab 03: Static Methods and Primitive Data Conversion Lab 04: Using Objects Lab 05: Conditionals Lab 06: Loops Lab 07: Writing Classes Lab 08: Overloading Methods Lab 09: Interfaces and Interface Type Lab 10: Object Arrays, ArrayList, 2D Primitive Arrays Lab 11: Inheritance Hierarchies Lab 12: Collection Polymorphism Lab 13: Exception Handling and File I/O Lab 14: Graphics and GUIs CSC 2011 Lab: Introduction to Computer Science My office hours: MW 10:00 – 12:00 c. Prerequisite: CSC 2001 Corequisite: CSC 2010 Download the doc for the 2010/2011 syllabi, lab assignments. Section 1: Lab TA: Michael Baldwin (Bruner 405) Email: mkbaldwin21@tntech.edu Office Hours: M W: 12:30-2:30 T: 1:30-3:30 R: 9:00-11:00 Section 2: Lab TA: Emily Sherrill (Bruner 405) Email: emsherill21@tntech.edu Office Hours: M: 11:00-12:00 1:00 - 3:00 T: 8:00-12:00 1:00 - 3:00 W: 11:00-12:00 2:00 - 3:00 R: 8:00-9:00 11:00-12:00 1:00 - 3:00 F: 8:00-10:00 11:00 - 12:00 You will demonstrate your in-class labs (as a team) to TA assigned to your class and you will demonstrate your post-labs (individually) to TA assigned to your class. Sheikh K. Ghafoor Email: sghafoor@tntech.edu Lab Guidelines You are expected to have read the entire lab before coming to the lab and to have reviewed the material described in the pre-lab. You will also want to read the detailed instructions within the starting code for each lab as important points are made there as well. Lab time will be allocated as follows: Five minutes for lab setup. This will involve taking roll, downloading starting source code, and assignment of a partner for the lab. You will be assigned a different partner for each lab. Ten minutes for a discussion of background material and possible ways to tackle the solution. I expect everyone to participate by asking questions and by suggesting ways to tackle the solution that I did not cover. Ninety-five minutes to implement and to test your solution. When you are ready, I will verify that your solutions are correct. Total time: 110 minutes for each lab. Grading Policy Missed labs can only be made up (on your own time and by yourself) with proper documentation of exceptional circumstances (i.e. a doctor's note or other authorized absence). In order to pass, you must attend 13 out of 14 the labs and make a decent attempt at the in-class lab exercises. You must also participate in class discussions on a regular basis. In order to make a "C", you must satisfy all the requirements for passing and successfully complete 12 out of 14 of the in-class lab exercises. You must complete labs 11, 12, and 13. You may only turn in an in-class lab if you are present for the entire lab during the scheduled lab time, unless your team successfully demonstrated the in-class lab exercises before the end of the lab, or you have documentation of exceptional circumstances. Roll will be taken at the beginning and the ending of lab. If you are late to the point that partners have already been rearranged due to your tardiness, you will not be allowed to participate in the lab and will be marked as absent for the lab. If you cannot complete the in-class lab exercises during the scheduled class time, you may continue to work on the exercises outside of class (see below). Your team has until: Monday at 2:30 PM to complete the in-class lab and the individual post-labs (if you choose to do the post-labs). In order to make a "B", you must satisfy all the requirements for a "C", and you must successfully complete 9 of the post-lab exercises individually. Post-labs are due according to the same schedule (above) used for in-class labs and must be based on a lab with an in-class portion that you have completed. In order to make an "A", you must satisfy all the requirements for a "B", and you must successfully complete 13 of the post-lab exercises individually. Handing In Your Lab I am always willing to help with any lab or post-lab questions that you may have. To officially turn in your work, please follow the guidelines below. The Lab TAs (and/or myself) will be keeping track of which in-class labs and post-labs that you have completed. The in-class portion of the lab should be shown (or emailed) to the Lab TA in charge of your lab section. Simply demonstrate that your lab is working. If the lab has multiple parts, you will need to demonstrate each part as you complete them. You will also be asked about your observations concerning specific lab sections as noted in the lab instructions. After all parts have been demonstrated, your team will be checked off as having completed the in-class portion of the lab. Depending on the specific post-lab, there may be some additional programming, a short paper, or both to hand in. If a post-lab has a programming component, you will need to demonstrate it (or email it) to the TA (there is no need to print out your source code). Post-labs are done individually, so everyone handing in a post-lab will need to demonstrate their work. If the post-lab has a paper component, you will need to print this out and give it to me as well. I recommend that you demonstrate your in-class labs and post-labs. This way, specific problems that are encountered can be discussed in person. If you choose to email your in-class labs and post-labs, you will only be given a brief description of any problems (if there are any) with your work. If you email your work, zip all of your files up and use your name, the lab number, and in-class or post-lab to create the title for the zip file. Labs 1) Getting Started Compiling Running Identifiers Comments o Multi-line o End of line 2) Console I/O and Calculations Console I/O o Keyboard class o Repeating input o Reporting output o String concatenation Calculations o o o Syntax Runtime Logical 3) Static Methods and Primitive Data Conversion Static Methods o Parameters o Return Types o Nesting Method Calls Primitive Data Conversion o Widening Assignment Arithmetic o Narrowing Casting Code Reuse 5) Conditionals If - Else If - Else o Checking User Input o Nested Conditionals o Complex Boolean Expressions Switch 7) Writing Classes State variables o integers o booleans o Strings Visibility modifiers o private state variables o public get/set methods o private helper methods toString to report state Controlling state changes with set methods Driver class Object parameters UML 9) Interfaces and Interface Type Interfaces Separate Implementations of a Common Interface o Parametric Line o Slope - Intercept Line Hiding Implementation (Abstraction) o Interface Type o Factories Still More UML 11) Inheritance Hierarchies o o o Errors Inheritance o extends o super Primitive data types Arithmetic operators Math class 4) Using Objects String Class o Pig Latin Translator Random Class o Abstraction o Code Reuse DecimalFormat Class o Using Formatting Patterns o Currency Pattern 6) Loops While Loop o "Hiding" Nested Loops o Do-While Loop For Loop 8) Overloading Methods Reinforce o Constructors o Get/Set o Encapsulation Aggregation (HAS-A) equals this Method Overloading Static Methods and Variables More UML 10) Object Arrays, ArrayList, 2D Primitive Arrays Reinforce o Constructors o Loops Randomizing Object Arrays For-each statement Object Arrays as Parameters/Return Values ArrayList Primitive Arrays o 1D o 2D 12) Collection Polymorphism Polymorphism o Inheritance Polymorphism o Interface Polymorphism protected abstract classes and/or methods overriding and overloading equals constructors o implements o indirect Reinforce o Comparable Interface o Get Methods o o o 13) Exception Handling and File I/O Exceptions o Custom Checked Exceptions Throwing Exceptions Error Messages Additional Information o Handling Exceptions File I/O o Text Files o Serializing Objects Reinforce o Comparable Interface o ArrayList o for-each o Set Methods Testing 14) Graphics and GUIs Reinforce o Has-a Relationship o Is-a Relationship o Object Arrays o Interfaces Basic Graphics o Shape Hierarchy o Visual Interface o Graphics class Basic GUIs o Mouse Events o Timer o repaint I reserve the right to modify the contents of the labs. Honesty Students are encouraged to obtain limited help and/or ideas from one another. However, copying assignments or allowing assignments to be copied will not be tolerated. The penalty for cheating in the class is an "F" for a final course grade. Attendance Policy You are expected to attend every lab. You are responsible for all assignments and material covered and all issues discussed during all lab meetings whether you are present or not. Makeup labs will not be accepted without proper documentation for an excused absence. Disabilities Students with a disability requiring accommodations should contact the Office of Disability Services (ODS). An Accommodation Request (AR) should be completed as soon as possible, preferably by the end of the first week of the course. The ODS is located in the Roaden University Center, Room 112; phone 372-6119. Contact Email: sghafoor@tntech.edu Laboratory 1: Getting Started Java API Pre-lab: Be comfortable with Windows Explorer. A keyboard short cut to launching Windows Explorer is to press the Windows key and E at the same time. Compilers and Interpreters General Procedure: Initially, you use an editor as you type a program into a computer and store it in a file. After editing and saving your program, you attempt to translate it from "high-level", English-like code into a form that can be executed by the computer which requires 1’s and 0’s. The steps are outlined on my web site here. That translation may result in errors, in which case you return to the editor to make changes to the code to fix the problems. Such errors are called syntax errors. Once the translation occurs successfully, you can execute the program and evaluate the results. If the results are not what you want (logical errors) or your program can't complete (run-time errors), you again return to the editor to make changes. A compiled language has a compile step. (C/C++) The translation of source code into machine language for a particular type of computer architecture can occur in a variety of ways. A compiler is a program that translates code in one language to equivalent code in another language. The original code is called source code, and the language into which it is translated is called the target language. For many traditional compilers, the source code is translated directly into a particular machine language. The translation process occurs once for a given version of the program. The program can then be directly executed whenever needed. However, this will only work for one particular system architecture without recompiling (i.e. PC vs. Mac). Each type of computer has its own set of requirements. Thus, the same program will have to be compiled multiple times in order to be run on different computer architectures. An interpreted language does not have a compile step. An interpreter is similar to a compiler but has some important differences. An interpreter interweaves that translation and execution activities. A small part of the source code, such as one statement, is translated and executed. Then the next statement is translated and executed, and so forth. The program generally runs slower as the translation process occurs during each execution. Java combines the compilation and translation processes. The Java compiler translates Java source code into Java bytecode, which is a representation of the program in a low-level form similar to machine language code. This translation is performed during the javac step (see later) that checks for syntax errors. The Java interpreter then reads Java bytecode and executes it on a specific machine (the java step). Java bytecode has the advantage that it is not tied to a particular processor type like traditional compilers which compile to the machine code for a particular computer architecture. Java is, architecture neutral, and is easily portable from one machine to another. The only restriction is that there must a Java interpreter installed on the computer on which the Java bytecode is to be executed. Each type of computer architecture has its own version of the Java interpreter which converts the bytecode the rest of the way to machine code for the computer on which the program is being run. As the interpreters are installed ahead of time, a particular Java program can be run on different computer architectures without repeating the translation step. Thus, Java is faster than traditional interpreters as the Java interpreter only needs to translate from bytecode to machine code. However, Java is still slower than traditional compilers as some interweaving of translation and execution is still performed. Also, there is no need to recompile to bytecode when running a Java program on multiple computer architectures. Simply install the Java interpreter on each machine on which you wish to run your Java bytecode. Lab: Compiling Running Identifiers Comments o Multi-line o End of line Errors o Syntax o Runtime o Logical Part I: Compiling and Running a Program First, you will need to open a text editor. You can use any text editor that you want, but these lab instructions assume Notepad. Launch Windows Explorer. Navigate to the folder where you want to store your work. Right click the folder and select Launch Command Prompt. Type notepad in the command prompt window. Type in the following text exactly as it appears below into notepad. Note that the name of our class is FirstProgram. You can identify the name of the class because it occurs after the keyword class. You will need to use this class name when saving your file later. Now you need to save the file. Go to the File menu and select Save As. Navigate to the folder where you are working. This should be the same folder where your opened a command prompt earlier. Set the file name to FirstProgram.java. As noted earlier, all Java files require that the file name match the class name. Also, make sure that the file type is set to All Files. Otherwise, your file name will have a .txt extension added automatically. In order to compile a program, the Java compiler requires a .java extension, not a .txt extension. Click Save. Compile the file by typing javac FirstProgram.java in the command window. You should have gotten a message in the command window that states that the symbol string was not found. This is because Java is case sensitive, and you need to use the symbol String. This type of error is called a syntax error. The Java compiler could not figure out what was meant by "string". There can be no ambiguity in our code or the compiler will complain. Fix this error by replacing string with String, and repeat steps 3 and 4 (if you received other errors, fix those as well). Note that when saving your file now, you can select Save rather than Save As, as the file to write to has already been specified, and your old work will be overwritten with your changes. Type dir in the command prompt. Note that there is a file called FirstProgram.class. This is the Java bytecode file, and was created when our program compiled with no syntax errors. The Java interpreter needs this file to execute your program. Type java FirstProgram in the command prompt. Note that no extension is needed. The interpreter knows that it is going to use the .class file. Hopefully, your program executed and printed two lines of text to the screen. Part II: Identifiers There are three types of identifiers in a program. Reserved words of the Java language Names chosen by another programmer Names chosen by us In FirstProgram, class is an example of a reserved word. It has a specific meaning to Java. There are specific locations where Java expects reserved words to be used. They should not be used anywhere else. Change class to cls, and repeat the steps for compiling and running. What happened? Change this back. Other keywords include public, static, and void. You will know what these reserved words are for later in the course. An example of the second type of identifier is String. This name was chosen by another programmer. You are telling Java that you want to make use of someone else's code, a very important idea in computer science. You can save a tremendous amount of time coding and testing if you make use of existing code. In order for you to make use of the code that someone else wrote, you must use the name they selected (remember, Java is case sensitive) to refer to their work. You have already experimented with changing this type of an identifier in Part I. If the incorrect identifier is used, the Java compiler cannot find the code that you want, and will issue an error message. In our program, args is an example of an identifier chosen by us. Thus, you are free to change it, as long as you change it everywhere it occurs (there is only one occurrence for args in our example). However, you must follow the rules for identifiers. An identifier may contain letters, digits, the underscore character, and the $ character. The only other restriction is that an identifier cannot start with a digit. Try changing args to 1args and compiling. What happened? Next change args to _1args and repeat the steps for compiling and running. What happened? Change back to args. Finally, change the text inside the double quotes to something else and repeat the steps to compile and run. What happened? The text in the double quotes are not specific instructions for running the program (this is called a String literal). This is the text that is going to be written to the screen when the program runs, exactly as it appears in your file. It is not an identifier, so it can be changed to anything. Part III: Comments There are two ways to insert comments into a program. /*...*/ (multi-line) // (end of line) Multi-line comment example: /* Here is an example of a multi-line comment. */ Everything between the /* and the */ is ignored by the compiler. End of line comment example: System.out.println("Some text"); //Here is an example of an end-of-line comment. Everything after the // to the end of that line is ignored by the compiler. Using the multi-line comment, document the top of the program (class) to describe the purpose of the program (class). Make sure that your comment spans multiple lines. Repeat the steps to compile and run. The text in the comment should have been ignored by the compiler. Using the multi-line comment, document your main method. Describe the purpose of the main method and what the method does in general. Using the end of line comment, put some text after the first System.out.println indicating that the two lines of text are going to be printed to the screen. Repeat the steps to compile and run. Again, your comments should be ignored. Part IV: Errors As noted earlier, there are three types of errors. Syntax (already discussed) Runtime Logical Insert the following line of code at the end of your main method: System.out.println(3/0); In this line, you are dividing 3 by 0 and printing the result to the screen. Compile and run this modified program. There are no syntax errors, so the program compiles. That is, it is clear to the compiler that you want to divide one number by another. There is no ambiguity in this instruction. However, there is still a problem with this line of code. Division by 0 is not defined. This problem is not checked for by the compiler, and will only be detected when the interpreter runs the line with the problem. An error that is encountered during the running of the program is a runtime error. Take this line out before proceeding. Insert the following lines of code at the end of your main method exactly as it appears below (you are not expected to understand all of the symbols below): System.out.println("3 times 2 = " + (3 * 3)); Compile and run your program. Although fixing this particular "error" is simple, in a program with many complex calculations, it can be very difficult to find and correct such errors. This is because there are no error messages, but the answer that the program gives is simply incorrect. Such errors are called logical errors. Fix this error (hopefully, how to fix this is self-evident). Post-lab: About You Write a program to print your name, your birthday, your hobbies, your favorite books, and your favorite tv show. Call it ComplexText.java. Use only one System.out.println statement. Use quotes in your output where appropriate, and place each item about you on a separate line. That is, write your single System.out.println statement over several lines, rather than one very long line. Make sure that word wrap in notepad is turned off. Do not declare any String variables. You will need to read about escape characters on page 67 and about String concatenation on page 64 of your textbook. Laboratory 2: Console I/O and Calculations Java API Keyboard Documentation Pre-lab: Make sure that you are comfortable with the primitive data types and the primary arithmetic operators. Review compiling and running a Java program from Lab 1. Keep your work for this lab as you will be using it in the next lab. Download the Keyboard class and place it in the directory where you will be working for this lab. Take a look at the documentation for the Keyboard class. You will use the Keyboard class to obtain input from the user. Remember that to call a static method (the only kind that we have seen so far), you use the name of the class followed by a dot and the name of the method. You will also need to make use of the Math class in this lab. The methods are selfexplanatory. The Math class is automatically available to you, so you don't need to download anything. Call methods using the class name just like for the Keyboard class. Lab: Console I/O o Keyboard class o Repeating input o Reporting output o String concatenation Calculations o Primitive data types o Arithmetic operators o Math class Part I: Obtaining and Confirming User Input Start a new class called Points. Remember to work in the same directory where you saved the Keyboard class. Obtain 4 pieces of information that will define two points from the user as indicated below: (x0, y0) and (x1, y1) Indicate with an informative prompt exactly what you expect to obtain from the user. Make sure to allow numbers with fractional parts to be inputted. After the input has been obtained, print back to the screen exactly what you obtained from the user. Display the inputted values in (x, y) format. Indicate the first point and the second point. You will need to use string concatenation. Refer to the figure later in the lab. Part II: Performing Calculations Next compute the distance between the two points using the distance formula: √(x1 - x0)2 + (y1 - y0)2 (everything is under the radical) Use the information that you have retrieved from the user to compute the distance between the two points. Do not use the Math class to compute the squares, but you may use the Math class to compute the square root. Print out the results to the screen using a complete sentence. Refer to the figure. Part III: Slope and Intercept Enhance your program to compute the slope and y-intercept of the line joining the two points. Compute the slope first using both points obtained from the user. Next, compute b. To do this, you will use the slope just computed and one of the two points (you choose) obtained from the user. Use the following formulas (m is the slope and b is the y-intercept): m = (y1 - y0) / (x1 - x0) y = m*x + b Print out the equation of the line (y = m*x + b) with your computed slope and yintercept. Use a complete sentence. Part IV: Documentation Document your class, main method, and important individual lines using both multi-line comments and end of line comments as you did in Lab 1. Part V: Approximation Errors The trigonometric functions sine and cosine can be approximated as follows: sine(x) = x - x3/3 + x5/120 - ... cosine(x) = 1 - x2/2 + x4/24 - ... where x is in radians and radians = degrees * pi / 180 The tangent is defined as sine/cosine. Write a program (Trig.java) to request an angle from the user in degrees. Convert degrees to radians. (use Math.PI for pi, a constant defined in the Math class). Use a Math class method to obtain xy (search for the method to use in the Java API). Report the sine, cosine, and tangent using the approximations above. You only need to use the terms explicitly shown above in your computation. State that they are approximate values. Find and use an appropriate method in the Math class to obtain an "exact" value (really just a much better approximate value) for the sine, cosine, and tangent given an angle in radians. Compute the percentage error in your approximate calculation for the sine, cosine, and tangent. % error = 100 * (approximate value - exact value) / (exact value) Report the percentage error obtained for sine, cosine, and tangent. Post-lab: Floating Point Accuracy As discussed in class, a float uses 32 bits to store a value (a bit is a one or a zero). Thus, there is a limit to how accurate your computations can be in a program. The first bit stores the sign (0 for a positive number, 1 for a negative number). The next 8 bits store the exponent. The last 23 bits store the mantissa. For example, 7.5f is represented in binary as: 01000000111100000000000000000000 OR 0 10000001 11100000000000000000000 (broken into the three regions, sign, exponent, and mantissa) The first bit, a zero, indicates that the sign is positive. The next 8 bits give the exponent, but in a form called excess 127. This means that the exponent that we compute from the 8 bits for the exponent is 127 larger than the actual exponent. Since computers operate on bits, everything is in binary, so we need to convert the exponent from binary to decimal. The exponent in base 10 is computed as 1x27 + 0x26 + 0x25 + 0x24 + 0x23 + 0x22 + 0x21 + 1x20 = 129. Thus, the exponent is 129 in base 10 (or decimal), so the actual exponent is 2 (129 - 127 = 2). Note that 2 is raised to the given exponent and this result is multiplied by the mantissa (see next). The last 23 bits represent the mantissa, or the fractional part of the number. It is evaluated as follows: 1 x 2-1 + 1 x 2-2 + 1 x 2-3 + 0 x 2-4 + ... the remaining bits are all zeroes. This is 0.5 + 0.25 + 0.125 = 0.875. Finally, add 1 to the mantissa. So we have: + 1.875 x 22 = 7.5f, which is a floating point number that can be represented exactly in Java. Assume that 12.36f is represented as 01000001010001011100001010001111. This bit pattern is not exactly 12.36, but it is very close. As a float can only hold 32 bits, many numbers cannot be represented exactly, and this can introduce errors in calculations. Using the rules described above, write a program to compute the decimal number that the bit pattern for 12.36f actually corresponds to. It will not be exactly 12.36, but very close. Your program does not have to be interactive. It only needs to be able to compute the decimal number for the above bit pattern. Since you are computing the error contained in floats, should you use floats or doubles to perform your calculation? Print out your result. Next, compute the percentage error of the value just computed from the actual value. As your computed value represents the "approximate" value, should you use doubles or floats to represent the actual value, which you need in order to compute the percentage error? Print the percentage error. Over the course of the semester, you may encounter strange output that is related to the fact that many numbers cannot be represented exactly. To see what this strange output might look like, add a few more statements to your program. Declare a float and give it the value 12.36f. Print the result. Now add 100.2f and then immediately subtract 100.2f. Print the result. Write a paragraph describing your strange output and speculate as to why you get what you get. Laboratory 3: Static Methods and Primitive Data Conversion Java API Keyboard Documentation Pre-lab: Make sure that you are comfortable with static methods and primitive data conversion. Remember, there are several types of primitive data conversion: 1. 2. 3. 4. 5. (A) assignment (B) arithmetic (C) casting (D) parameter (E) return Download the Keyboard class and place it in the directory where you will be working for this lab. Lab: Static Methods o Parameters o Return Types o Nesting Method Calls Primitive Data Conversion o Widening Assignment Arithmetic o Narrowing Casting Code Reuse Part I: Static Methods Modify your Lab 2 work to include and use the following methods: 1. public static double getInput(String prompt) //obtains input from the user given the specified prompt (use Keyboard.readDouble) //you can only return one value from a method at a time //you will call this method 4 times 2. public static String printPoint(double x, double y) //returns a String representing one xy-pair "(x, y)" 3. public static double distance(??) //returns the distance between two points 4. public static double slope(??) //returns the slope of the line determined by two points 5. public static double intercept(??) //returns the y-intercept of the line determined by two points 6. public static String printLine(??) //returns a String representing the equation of one line "y = m*x + b" All System.out.printlns should be placed in the main method and not the new methods that you will be writing. Part II: Documentation Document your class, main method, other methods, and individual lines using both multi-line comments and end of line comments. Part III: Primitive Data Conversion Copy and paste all of your code and comments from Part I into a file called Points2.java. Change the declaration of y0 and y1 in your main method only to int rather than double. Without changing any of the methods or any other variable declarations, make the changes that are necessary to get your program to compile and run. Initially, you may have some compile errors due to narrowing conversions. Run your program. What happened? Write a slope2 method that accepts the x-coordinates as ints and returns an int. Use this new slope method in your computation. Without changing any of the other methods or any other variable declarations, make the changes that are necessary to get your program to compile and run. Initially, you may have some compile errors due to narrowing conversions. Explain what happens during the division. Does using the slope2 method increase or decrease accuracy of the computation from that of using the original slope method? Why? Write a slope3 method that accepts all coordinates as ints and returns a double. Make sure that you do not perform integer division. Use this new slope method in your computation. Without changing any of the other methods or any other variable declarations, make the changes that are necessary to get your program to compile and run. Initially, you may have some compile errors due to narrowing conversions. Explain what happens during the division. Does using the slope3 method increase or decrease accuracy of the computation from that of using the slope2 method? Why? Print out your source code for Points2.java. Label all data conversions as assignment (A), arithmetic (B), casting (C), parameter (D), or return (E) for the slope methods, the distance method, the intercept method, and the main method. Also, label your conversions as (W) widening or (N) narrowing. Hand your print out in (don't forget to put your names on your work). Part IV: Perimeter of a Triangle Start a new class called Triangle.java. Obtain 3 points from the user. Write a method (getPerimeter) to compute the perimeter of the triangle formed by those three points. Call methods in the Points class as needed. Return the result to main and print out the result in a complete sentence. Post-lab: Rounding Examine the round method available in the Math class. Note that it will only round to integer values. Suppose you needed to round a number off to a specified number of decimal places. You need something more sophisticated than the round method available in the Math class. Write a Round class with a static method that accepts a double (call it val) and an int (call it places) and rounds val off to the specified number of decimal places. The rounded value (a double) is returned. If the specified number of decimal places is 0, your method should behave the same as the Math.round method. That is, the double will be rounded off to the nearest integer. To get the extra functionality of specifying an arbitrary number of decimal places, you could perform some initial computations (see the Math class) and then use the Math.round method. However, it is possible (and better) to use a cast to an int to achieve your goal rather than calling the Math.round method. Do this, remembering that a cast to an int truncates the fractional part, so you might have to think a little bit about how to make this work so that you get rounding rather than truncation. Add a main method to your Round class to thoroughly test your program. What happens if the number of places is negative? Again, your round method will NOT use Math.round (or Math.floor, or Math.ceiling). Use your Round method to round off the computed perimeter of your triangle to 2 decimal places. Laboratory 4: Using Objects Java API Keyboard Documentation Pre-lab: Download the Keyboard class and place it in the directory where you will be working for this lab. Be comfortable with the methods available in the String class, the DecimalFormat class, and the Random class. Know how to create objects of these classes and know how to call their methods. Since most of the methods in these classes are not static, you need to invoke their methods through a reference variable. Lab: String Class o Pig Latin Translator Random Class o Abstraction o Code Reuse DecimalFormat Class o Using Formatting Patterns o Currency Pattern Part I: Pig Latin Write a program that accepts a word from the user. Assume that the word begins with a single consonant. Transform the word into its pig latin equivalent. That is, move the initial consonant to the end and then append "ay". For example, birthday transforms to irthdaybay. Invert the transformed word to get the original word back (don't simply use the original word). Include the following static methods in your solution: 1. 2. 3. 4. 5. public public public public public static static static static static String getMessage(String prompt) String translate(String word) //translate to pig latin String inverse(String word) //translate back boolean standardEquals(String str1, String str2) boolean aliasEquals(String str1, String str2) Compare the original word obtained from the user to the word transformed to pig latin and back in two ways: 1. compare them using the equals method (performed by standardEquals) 2. compare them using == (performed by aliasEquals) Explain your results. Part II: Random Numbers import java.util.Random; What if you want a random integer between 3 and 7, inclusive of both? There are no methods in the Random class that will allow you to specify an arbitrary lower limit and an upper limit. However, with a little extra work, the methods in the Random class can be used to achieve a random integer between arbitrary limits. If you need arbitrary limits often enough, the extra work required to obtain them using the methods in the Random class can become very tedious. You will now write some static methods in a new class (RandomNumbers.java) to do this extra work. You will perform a simple calculation in each of your methods to ensure the proper limits. Do not use any if statements or loops. From now on, when you need arbitrary limits, simply use the methods that you are going to write in this lab. You never need to concern yourself with the details required to achieve arbitrary limits ever again. By doing this, you are abstracting, or hiding, the tedious details required to include arbitrary limits from the Random class methods. This promotes code reuse as you will use and reuse methods as you need them throughout your computer science career. Abstraction and code reuse are very important concepts in computer science which you will revisit in most, if not all, of your computer science classes. Include the following static methods in RandomNumbers.java: 1. public static double randomDouble(Random rand, int low, int high) (random double between the given limits, low and high) 2. public static int randomInt(Random rand, int low, int high) (random integer inclusive of the given limits, low and high) Document this class in the usual way as it will come in handy later. Part III: Formatting Numbers import java.text.DecimalFormat; Start a new class called RandomDriver and write the main method as follows. Obtain a lower and an upper limit from the user. Using your work in Part II, obtain a randomly generated integer and a randomly generated double using the specified lower and upper limits. Display the randomly generated numbers using complete sentences. Format and display the integer to include commas if necessary. Format and display the double to show exactly two decimal places (and no commas). Display the formatted numbers using complete sentences. Make sure that inputting the lower and upper limits as the same value works correctly. What happens if low is greater than high? You will address this in the post-lab. Write a class (Currency.java) that contains the method shown below: public static String formatCurrency(double val) This method accepts a double and returns a String formatted for currency. That is, the double is formatted to use a dollar sign, commas if necessary, and exactly two decimal places. This is also an example of abstraction. Go back to RandomDriver and add some code to the end of your main method to display your randomly generated double using your new formatCurrency method. Post-lab: More Random and DecimalFormat Fix up RandomNumbers so that a Random object does not need to be passed in to the methods. To do this, look at the example on page 292 of your text concerning static variables. You will create a Random object that can be used in any method in the RandomNumbers class so it doesn't need to be passed in to those methods. Simply create and declare a (static) Random object outside the methods in the RandomNumbers class. This object can now be used in the two methods that you wrote, so you don't need to pass them in any longer. Also, check that low is less than or equal to high in your two RandomNumbers methods. If low is larger than high, set low to be equal to high (use if statements). Do the same procedure for Currency.java so that the DecimalFormat object is not instantiated inside the method. Write an application (PhoneNumbers.java) that creates and prints a random phone number of the form XXX-XXX-XXXX. Include the dashes in the output. Do not let any of the first three digits contain an 8 or a 9, and make sure that the second set of three digits (taken together) is not greater than 742. Use your RandomNumbers class. Don't copy code from RandomNumbers to PhoneNumbers. To get the phone numbers to display properly, you will need two different formatters. You may do all of your work in the main method of PhoneNumbers. Hint: each digit does not have to be obtained separately. Laboratory 5: Conditionals Java API Keyboard Documentation Pre-lab: Review boolean expressions, including expressions that make use of AND (&&) and OR (||). Note that a boolean (the primitive data type) alone can be used represent a boolean expression. Review conditionals, including the switch statement and nested conditionals. In particular, note how conditionals have been used in class to check input obtained from the user. You will also need to refer to various String methods. Download the Keyboard class and place it in the directory where you will be working for this lab. You will also need your work from the previous lab. Lab: If - Else If - Else o Checking User Input o Nested Conditionals o Complex Boolean Expressions Switch Part I: If - Else If - Else Modify your PigLatin program from the previous lab. Check user input to make sure that the word contains at least 3 characters. If it doesn't, inform the user and quit. In addition to handling words that begin with a single consonant, you will now allow words to start with a vowel or two consonants. Thus, your program should work for words that start with 0, 1, or 2 consonants. If the word begins with a vowel, simply append "yay" to the end of the word (nothing is moved from the front to the back in this case). If the word begins with two consonants, move both consonants to the end and append "ay" as you did for a single consonant. Write and use the following method to determine if the first or second letter of the inputted word is a vowel. Use the result of this method to control your conditionals. public static boolean checkVowel(char theChar) Your program should also allow an inverse translation for the case that the word begins with a vowel or a single consonant. If the word did not begin with a vowel, assume that it began with a single consonant. You may also assume that the original word did not start with a "y". Note any problems that are encountered when attempting to write an inverse translation for the case with two constants. Use one translate and one inverse method, the same methods that you wrote in the last lab, but add conditionals to them. Part II: Nested Conditionals &&/|| Complex Boolean Expressions Write a program (BlackJack.java) to simulate a simple version of Black Jack. Generate two random numbers (using RandomNumbers.java) in the range 1 to 13. Let a 1 represent an Ace and a 13 represent a King. Generate an if - else if - else statement with no nesting and only using && to separately test for all possible combinations of Black Jack. Limit the number of tests in each conditional to two (to avoid extremely long boolean tests). Black Jack occurs when a player is dealt an Ace with a 10, Jack, Queen, or King. Print out the numeric values of the cards drawn along with the text "Black Jack!" or "No Black Jack." as appropriate. What is the maximum number of tests that will ever be required in this format? Test your work. Why is it better to use if else if - else in this case rather than several separate if statements? Rework your if statements to allow nesting and the use of ||. Reduce the number of tests required as much as possible. Again, limit the number of tests in each conditional to two (or less). Test your work. Why is this version more efficient? Part III: Switch Write a menu program (Menu.java) that allows users to select a salad, an entree, and a dessert. Use the following choices and prices. If an invalid selection is made, make the first choice the default choice. Format your menu selections using the escape sequence for carriage returns to make your menu easy to read. Salad 1. house salad $2.99 2. caesar salad $3.99 3. greek salad $3.24 Entree 1. chicken $4.99 2. steak $7.99 3. fish $5.79 Dessert 1. cake $2.99 2. ice cream $1.47 3. pie $2.64 Download Menu.java for the starting code for this part. Complete the following methods : 1. 2. 3. 4. public static String getSaladString() //create the menu text for the salad public static String getEntreeString() public static String getDessertString() public static int getChoice(String prompt) //accepts a number between 1 and 3 for a selection (if an invalid integer is inputted, set the choice to 1) 5. public static double getCost(int choiceSalad, int choiceEntree, int choiceDessert) //uses a switch statement and all selections to compute the cost After all the selections have been made, use the formatCurrency method in the Currency class from the previous lab to display the total cost of the selections. Also display the total cost without formatting. Find a combination of items that will not add correctly to get the total cost, but contains a small error due to the fact that Java cannot represent all floating point numbers exactly. Post-lab: Roulette Write a program to play Roulette. Roulette is a wheel with 36 slots. A ball is spun in the wheel and eventually stops in one of the slots. The slots are numbered 1 through 36. Each number also has a color, red or black. Assume that even numbers are red and odd numbers are black. Allow the following bets to be selected from: 1. red or black (user enters "r" or "b") 2. first 12 (1 - 12), second 12 (13 - 24), or third 12 (25 - 36) (user enters "first", "second", or "third") 3. a single number from 1 to 36 After selecting the desired type of bet by entering an integer in the range 1 to 3, the user enters the specific bet as text rather than an integer, so use the readString method even when an int is required from the user (as usual, check user input). You will need the parseInt method of the Integer class. If an invalid entry is selected, inform the user and quit. If a valid entry is selected, generate a random number using the RandomNumbers class and inform the user of a win or a loss (display the number generated, its color, and whether it is in the first 12, the second 12, or the third 12). If the user wins, compute the odds that they should be paid on their bet and inform them of their winnings (you may assume that all bets are $1). For example, if the user matches a single number, they should be paid 35:1 (a real casino will pay less than this to ensure a profit), so they will win $35 if they bet $1. That is, there are 35 ways to lose, and 1 way to win for this particular bet. Compute the odds that should be paid for the other bets and pay the player the appropriate amount when they win. Write methods as necessary to perform the various tasks. Make up post-lab: To make up a missed post lab (1-4), add some features to your Roulette program. Allow the user to specify a starting bankroll. Let the user to continue playing until they want to quit, keeping track of the bankroll balance. This involves computing the correct payout for the bet when the user wins. Of course, you cannot bet more than you have (or a negative amount). If the bankroll reaches zero, inform the user and quit. Laboratory 6: Loops Java API Keyboard Documentation Pre-lab: Review while loops and for loops. Read about the do-while loop on page 242 in your text. Download the Keyboard class and place it in the directory where you will be working for this lab. You will also need RandomNumbers from Lab 4. You may also need to refer to various String methods. Lab: While Loop o "Hiding" Nested Loops o Do-While Loop For Loop Part I: While Loops Write a program (Guessing.java) to play a simple guessing game. Select a secret number between 1 and a constant MAX (set MAX in the first line of your program-- 100 is a good choice). Allow the user to pick a number in the range 1 to MAX. Inform the user if they are too high or too low, and let them try again. If they guess the number, inform them and tell them how many guesses it took to get the number correct. Ask the user if they want to play again. If they do, select another secret number and start all over. When they finally indicate that they do not want to play again, inform them of the total number of games played, the total number of guesses for all games played, and the average number of guesses per game. Write the following methods (in addition to main): 1. public static int getGuess(final int MAX) //the user makes a guess with their guess checked for the range 1 to MAX and return the guess (reprompt if not in the valid range) 2. public static int playGuess(int secret, final int MAX) //user makes guesses and the result is processed (higher or lower) until the guess is correct and the number of guesses for this game is returned In this way, the nested loops are "hidden" inside method calls. This makes the program much easier to read and debug than it would be if all of your loops were done in the main method. Test your work. Part II: For Loops Write a program (Palindrome.java) to test a word inputted by the user to see if it is a palindrome or not. A palindrome is a word that is the same forwards and backwards. Make sure that a single character and the empty string register as valid palindromes, but don't write separate if statements to check for this. Use a for loop to reverse the word, storing the reversed word. Write another for loop to check for palindrome status by comparing the original String to the stored String character by character. Use a boolean to store the result of the palindrome test. Report the result (palindrome or not) using a conditional that branches based on the value of the boolean. Don't use the .equals method in the String class. Part III: Do-While Rewrite your palindrome tester using do-while loops instead of for loops. Note any problems that may occur and any assumptions that you need to make in order to use this type of loop for this application. Post-lab: Grades You will need to make use of a GradeBook object. Refer to the documentation for the GradeBook class. Write a program (Grades.java) to read in (from the keyboard) a list of final grades for a class. Allow the user to keep inputting grades until the user inputs a sentinel value (i.e. -1). You may assume the inputted grades are integer percentages from 0 to 100. You may also assume that at least two grades will be entered. Compute and report the average and the standard deviation with appropriate formatting applied. Using the class average (c.a.) and the standard deviation (s.d.), report the number of A's, B's, C's, D's and F's assigned to the class. Compute the standard deviation as follows (Σ means summation, in this case, the summation over all single final grades inputted): 1. sum = Σ(single final grade - c.a.)*(single final grade - c.a.) 2. s.d. = √ (sum / (n - 1)) where n is the total number of students Once you have the class average and the standard deviation, compute the assigned letter grade as follows: 1. 2. 3. 4. 5. 'A' final grade >= (c.a. + 1.5 * s.d.) 'B' final grade >= (c.a. + 0.5 * s.d.) 'C' final grade >= (c.a. - 0.5 * s.d.) 'D' final grade >= (c.a. - 1.5 * s.d.) 'F' final grade < (c.a. - 1.5 * s.d.) Write the following methods: 1. 2. 3. 4. public static GradeBook getGrades() //enter the grades into the GradeBook public static double getAverage(GradeBook grades) public static double getSD(GradeBook grades, double ca) public static void countGrades(GradeBook grades, double ca, double sd) //count the As, Bs, etc., and print the results to the screen Laboratory 7: Writing Classes Java API Pre-lab: Review visibility modifiers, get/set methods, constructors, object parameters, and driver classes. Remember that System.out.printlns should be placed in the driver class. Download the Keyboard class and place it in the directory where you will be working for this lab. You will also need your Currency.java file from an earlier lab. Lab: State variables o integers o booleans o Strings Visibility modifiers o private state variables o public get/set methods o private helper methods toString to report state Controlling state changes with set methods Driver class Object parameters UML Part I: Ice Cream Write an IceCream class (IceCream.java). Include instance/state variables for the flavor, the number of scoops, whether a cone or a cup is desired, and a topping, if one is desired. Write a default constructor to set reasonable default values of the state variables. Write a toString method to report the current state of an ice cream object, including the price of the entire order. Also include the following methods: 1. public static String listFlavors() //list all the available flavors, at least five (why static?) 2. public boolean setFlavor(String flav) //only certain flavors are available 3. public boolean setScoops(int scoop) //only 1, 2, or 3 scoops is allowed 4. public void setCone(boolean choice) //choices are cone or cup 5. public void setTopping(String top) //the topping can be anything 6. public double getPrice() //get the price of the ice cream cone 7. private boolean validFlavor(String testFlavor) //check that the flavor passed to the setFlavor method matches one of the available flavors An order of ice cream has a base price of $1.99. For each scoop (larger than 1), add $.75. If a cone is requested, add $.59. Use currency formatting (remember the principle of code reuse). The price of the order will be part of the reported state when the toString method is called. Note that some of your set methods will return a boolean to indicate whether the set was successful or not. This is an excellent way to indicate to your driver class whether the input from the user was valid or not. If it was not valid, your driver class needs to get the requested input again. Also, your set methods will check to make sure that a null is not passed to the method. Normally, you may assume that null is not passed to a method. Part II: Ice Cream Driver As usual, your driver class interacts with the user, making changes to objects through set methods as requested. Allow the user to order as many ice cream cones as they wish. Write the following static methods which may need "hidden" loops to wait for valid input from the user: 1. 2. 3. 4. public public public public static static static static void void void void getConeChoice(IceCream ice) getToppingChoice(IceCream ice) getScoopsChoice(IceCream ice) getFlavorChoice(IceCream ice) After all selections have been made, report the state of the current ice cream order (which includes the price, as noted earlier). Ask the user if they would like to order another ice cream. Repeat the process until they don't want to order any more ice creams. Report the number of ice creams purchased and the total price of the order. Post-lab: Enumerated Types Investigate using an enumerated type to list the available flavors and to check that a flavor was selected from the available flavors. See pages 135 and 316 for a discussion of enumerated types. You will also need use a for each statement (see page 249-- we will cover this in class in a few chapters). This is a form of the for loop which you can use to automatically loop over all the flavors in your enumeration without a counter at all. Example: enum RB {red, black}; creates an enumeration called RB with valid values red and black. Note that red and black are not Strings. Your enumeration should be an instance variable in your IceCream class. for (RB rb : RB.values()) loops over all of the values in the enumeration, storing each one in turn in the variable rb. Note that rb refers to an object of type RB, so you can call the toString() method to obtain the String representation of the enumeration. Thus, rb.toString() will either be "red", or "black". For more information, try here. Laboratory 8: Overloading Methods Java API Keyboard Documentation Pre-lab: Review the concepts covered in the previous lab, as you will need many of them for this lab as well. Review how to correctly compare floats. Review class level (static) methods and variables. Download the Keyboard class and place it in the directory where you will be working for this lab. Lab: Reinforce o Constructors o Get/Set o Encapsulation Aggregation (HAS-A) equals this Method Overloading Static Methods and Variables UML Part I: Slope-Intercept Line Download the Point class and place it in the directory where you will be working for this lab. Download the Line class and place it in the directory where you will be working for this lab. Complete the Line class. A Line is defined by two different Points. This means that two Points need to be stored in the Line class. This represents an aggregate (HAS-A) relationship. Write a constructor that accepts two Points as parameters. Be careful not to violate encapsulation. If the Points are the same, set them to reasonable default Points instead. Allow the constructor to compute and store the slope and intercept of the Line as well. Overload the constructor to write a default constructor. Have the default constructor call the constructor that takes two Points. Again, choose reasonable default Points for the no argument constructor. Write an equals method to compare two Lines within some tolerance. You will need to think about how to do this. Write get methods for your instance variables. Make sure that you do not violate encapsulation. Remember how objects and primitives differ when they are method parameters or return values. Write a class level (shared by all Line objects) intersection method to compute the intersection of two Lines. The Point of intersection is returned by this method. Overload this intersection method to compute the intersection between this and another Line passed in as a parameter. Call the first intersection method within the second, overloaded intersection method. To obtain the intersection of two Lines, you need to set their equations (y = m*x + b) equal to one another and solve for x. Use the equation (y = m*x + b) for either Line to obtain y once you have x. Identify a local variable in the toString() method that can be made a class variable (shared by all objects of the Line class), and make it one. Part II: Parametric Line A line can also be described by two Points in another, better way, called the parametric equation of a Line. Use the following equation to obtain any Point on the Line, using the two Points that define the Line and a parameter (α): P(α) = (1 - α)*P1 + α*P2, where α is the parameter. If α = 0, we obtain P1, one of the Points that describes the Line. If α = 1, we obtain P2. If α is between 0 and 1, we obtain a Point in between P1 and P2 (a Point on the line segment joining the two Points). Other values of α yield the rest of the Points on the Line. Write an evaluateParametric method that takes a value for the parameter and returns the associated Point on the Line (use the above formula). Write an intersectionParametric method to compute the intersection of this and another Line passed in as a parameter and return the Point of intersection. A lot of algebra is involved in obtaining the formula for the parameter of intersection, so the computation of the parameter of intersection has been done for you. Call the evaluateParametric method within the intersectionParametric method as necessary. Overload intersectionParametric to accept two Points as parameters. Call the first intersectionParametric method from within your overloaded method to compute the intersection of this and the Line defined by the two Points passed in as parameters. Part III: Intersection Download the Intersection (driver) class and place it in the directory where you will be working for this lab. Complete Intersection.java. Display the inputted Points. Create two Lines from the four Points, and display the equations of the two Lines. Compute and display the intersection of the two Lines using both intersection techniques, calling all four intersection methods (two overloaded intersection methods and two overloaded intersectionParametric methods). Make sure that your results in all four cases are the same. Part IV: UML Draw the UML diagram for Point, Line, and Intersection. Hand this in. For this and all UML diagrams in later labs, you only need to show the class level relationships. You may omit the method and instance variable sections of your UML diagram. Post-lab: Equal, Parallel, and Vertical Lines Add the following methods to your Line class: 1. public boolean isParallel(Line other) 2. public boolean isVertical() The basic equation of a Line, y = mx + b, has a major drawback. This equation cannot handle vertical Lines as the slope of a vertical Line is infinity. If the Line is vertical, set the slope and intercept to infinity. You will need to refer to the Double class to do this. Modify your intersection method to return null if either Line is vertical, if the two Lines are parallel, or if the two Lines are actually the same Line. The parametric version of the line can handle vertical lines. Modify intersectionParametric to return null only if the two Lines are parallel or are the same Line. Verify that the parametric version will compute the correct intersection even if one of the Lines is vertical. Modify the toString method to report the equation of the line as x = constant if the Line is vertical. Note that you will fill in the constant with an actual value. Laboratory 9: Interfaces and Interface Type Java API Pre-lab: You will be building on the work that you did in the previous lab. If you did the postlab, you should comment that work out. In this lab, you may assume that two Lines are not vertical, parallel, or the same line. Your work on the Line class in the previous lab actually handled two different ways to view a Line simultaneously. The first view is the parametric view which relied on the two Point instance variables. The second view is the slope-intercept view which relied on the slope and intercept instance variables. Both have advantages and disadvantages. The parametric view handles vertical lines automatically. The slope-intercept view is more familiar to most people. Thus, it makes sense to have both available. However, typically one form of a Line or the other will be used by an individual class. Having a class handle both simultaneously is clumsy, as evidenced by the clumsy method names that you had to use in the previous lab. You will create two implementations of a Line. In many cases, the user is not interested in the implementation details. That is, they do not care if the parametric view or the slope-intercept view is being used to create the Line. They just need to know how to use the Line. An interface allows you to provide multiple implementations, but to hide the implementation details. Thus, we encounter the principle of abstraction once again. All the user needs to know about is the methods that they need to call to get their work done. However, in those cases that the exact implementation is important (for example, cases where vertical lines must be easily handled), the actual implementation exists and can be specifically requested. Lab: Interfaces Separate Implementations of a Common Interface o Parametric Line o Slope - Intercept Line Hiding Implementation (Abstraction) o Interface Type o Factories More UML Part I: Multiple Line Implementations Using a Common Interface Write an interface (LineInterface.java) that contains the following method signatures: 1. public Point intersection(LineInterface other) 2. public Point evaluate(double x) //x is either the parameter or the x-coordinate Note that an interface type is passed as a parameter. This has very important consequences. In particular, you will be able to compute the intersection of two Lines even if one is implemented with the parametric view and the other is implemented with the slope-intercept view. Just use the methods provided in the interface to accomplish your task. In fact, even if you wanted to, you could not easily access methods not present in the interface because you don't know from what class the object is created. You only know that it implements LineInterface. Break your work on the Line class from the previous lab into two new classes: 1. LineParametric 2. LineSlopeIntercept LineParametric will only contain the two Point instance variables. The two Points will be passed to the constructor (remember encapsulation). Implement the interface using only the two Points to perform the calculations. Modify the toString method to display the parametric equation of a Line. See the previous lab. Provide get methods for the two instance variables (remember encapsulation). LineSlopeIntercept will only contain the slope and the intercept as instance variables. The slope and intercept will be passed to the constructor. Implement the interface using only the slope and the intercept to perform the calculations. You may find it necessary to write some private helper methods. The toString method should display the equation of the line as done in the previous lab. Provide get methods for the instance variables. Part II: Using an Interface Type Write a driver (LineDriver) to instantiate both a LineParametric and a LineSlopeIntercept. It is not necessary to make your driver interactive. Often when you are testing your work, you simply "hard-code" values into your program. That is, instead of asking for the x and y coordinate for a Point from the user, you simply create one with an x and y coordinate of your choosing. Your code in your driver class might look like this: LineParametric line = new LineParametric(new Point(3, 7), new Point(5, 19)); Display both of the lines. Evaulate the lines at various locations. Compute their intersection twice, one time with the LineParametric as the calling object, and one time with the LineSlopeIntercept as the calling object. Call the respective get methods. Make sure that all of your results are correct. Now change the type of both of your lines to LineInterface. For example: LineInterface line = new LineParametric(new Point(3, 7), new Point(5, 19)); What happened when you tried to compile? Why? Fix this while leaving the type as LineInterface and without removing any of the code in your driver. This makes it inconvenient for the user to call methods not in the interface. When you use an interface type, you typically don't care about the implementation, so you will only call the methods in the interface. Remove any calls to methods not in the interface. Part III: A Line Factory You can do more to ensure that it will be very unlikely that the user will be able to call methods not in the interface. You will be taking the idea of abstraction even further. Instead of providing the option of abstraction through the use of an interface type, you will be forcing the idea of abstraction on your users. This is important because it allows other programmers to use your interface to design their code, even if the actual implementations for a given interface haven't been written. Write a class (LineFactory.java) that contains two static, overloaded methods called createLine. Depending on which overloaded method is called (which depends on the parameters given to the method), instantiate and return the appropriate line implementation. However, make the return type of both of the static methods be the interface type, LineInterface. Modify your driver to use the factory methods to create the lines. Note that the new keyword is never directly used in the driver. It is "hidden" inside the factory. The user does not have to use the actual class name at all to obtain their line, which is a detail about how the line is implemented that they generally don't care about anyway. If they wanted to call methods not in the interface, it would be a bit of trouble for them to do this, as they would have to figure out what the names of the classes are. Part IV: UML Draw the UML diagram for Point, LineInterface, LineSlopeIntercept, LineParametric, LineFactory, and LineDriver. Hand this in. Post-lab: Packaging and Default Visibility Look on the Internet for resources concerning packaging in Java and default visibility. Try here for starters (look at the post-lab). In particular, look at the step by step instructions. Not all of the steps will apply. You can still do more to ensure that the implementations behind an interface are not directly instantiated. Instead of public classes, you will need to change the visibility of your two Line implementations to default visibility (omit a visibility modifier for a particular class altogether). Don't change the visibility of particular methods, however. LineFactory, LineInterface, and Point will still retain public class visibility. You can then "package" all the related Line classes together (the factory, the interface, the two implementations, and Point, but not LineDriver). What this procedure does is allows the classes in the package to instantiate one another (i.e. the factory class needs to instantiate the various implementations), but outside users cannot directly instantiate the implementations. They must go through the public factory class. Even if they somehow knew the class names for the implementations, it does the user no good. Laboratory 10: Object Arrays and ArrayList Java API ArrayList Documentation Lab 10 Documentation Pre-lab: You can find the rules of blackjack all over the Internet. To get an idea of what you are trying to accomplish in this lab, play my version of BlackJack. The dealer stands on all 17s. Doubling after splitting is always allowed. Multiple splitting is always allowed. The yellow highlighting is the optimal decision given your cards and the dealer's up card. Refer to the table below for the complete optimal strategy for blackjack. Across is the dealer's up card (T means a 10 or any face card). Down is your hand value. S means stand in that situation, H means hit, D means double down, and P means split (which is only relevant at the bottom of the table where the possible duplicate card values are listed). Note that the A/ entries represent soft hands of two or more cards. The row refers to the row in the strategy array (see BlackJackPlayer) where the desired move for that hand total can be found. After the row has been determined by the hand total, simply go to the column corresponding to the dealer's up card. Note: the hand totals begin with 2 (two aces) and go up to 21. Download BlackJack.exe. This executable contains a lot of the files that you need to run BlackJack but don't need to modify. For example, the card images are stored here. Put the executable in the directory where you will be working for this lab. When you think that you have completed the lab, run the executable and check for bugs. The executable will not run until all of the classes that you need to work on below have been compiled. Note that splitting will not work unless you have completed the postlab. Dealer's Up Card 2 3 4 5 6 7 8 9 T A <= 8 (row 0 - 6) H H H H H H H H H H 9 (row 7) H D D D D H H H H H 10 (row 8) D D D D D D D D H H 11 (row 9) D D D D D D D D D H 12 (row 10) H H S S S H H H H H 13 (row 11) S S S S S H H H H H 14 (row 12) S S S S S H H H H H 15 (row 13) S S S S S H H H H H 16 (row 14) S S S S S H H H H H >= 17 (row 15 - 19) S S S S S S S S S S A/2 (row 20) H H H D D H H H H H A/3 (row 21) H H H D D H H H H H A/4 (row 22) H H D D D H H H H H A/5 (row 23) H H D D D H H H H H A/6 (row 24) H D D D D H H H H H A/7 (row 25) S D D D D S S H H H A/8 (row 26) S S S S S S S S S S A/9 (row 27) S S S S S S S S S S A/10 (row 28) S S S S S S S S S S 2/2 (row 29) P P P P P P H H H H 3/3 (row 30) P P P P P P H H H H 4/4 (row 31) H H H P P H H H H H 5/5 (row 32) D D D D D D D D H H 6/6 (row 33) H P P P P H H H H H 7/7 (row 34) P P P P P P H H H H 8/8 (row 35) P P P P P P P P P P 9/9 (row 36) P P P P P S P P S S 10/10 (row 37) S S S S S S S S S S A/A (row 38) P P P P P P P P P P Refer to the ArrayList class as necessary. Lab: Reinforce o Constructors o Loops Randomizing Object Arrays For-each statement Object Arrays as Parameters/Return Values ArrayList Primitive Arrays o 1D o 2D Part I: Decks of Cards Download the Card class. You will need the Picture class to compile Card.java (but there is no work required in this file). Note that the compareTo method will compare by face value first, then by suit. Thus, a sorted Deck of Cards will have all the Aces first in the order Spades, Hearts, Clubs, Diamonds. Then the 2s in the same suit order, and so forth. Complete the constructor in the Decks class. Create the requested number of standard 52 card decks (check user input). You will need to use a nested for loop. After you have all the required Cards, shuffle all of the of Cards together. Complete the shuffle method in the Decks class. Use a for-each statement and your RandomNumbers class. After all of the Cards are shuffled, reset count so that all of the Cards in the Decks are again available. Look at the deal method (the code for this method has been given to you). The deal method uses the count instance variable to return the next Card in the Decks. After a Card has been selected from the Decks, count is decremented in preparation for the next call to deal. If there are no more Cards left to deal, shuffle is called to reset the Decks. Part II: BlackJackHand Complete the BlackJackHand class. A BlackJackHand object holds a minimum of two Cards, but the maximum number that the hand will hold is not known. Thus, it is convenient to use an ArrayList to hold the Cards in the BlackJackHand. Make your ArrayList able to hold only Card objects. The constructor will accept two Cards, which are placed in the ArrayList. You must also determine whether the hand is a soft hand or not. Simply determine if one of the two Cards is an Ace, in which case the hand is soft. The remaining methods that you need to complete are described in the comments. Part III: BlackJackPlayer Complete the BlackJackPlayer class to obtain the desired move given a player's hand total and the dealer's up card. You will also need the FileIO class to compile BlackJackPlayer.java (but there is no work in this file). The desired strategy is read in from a text file and stored in a 2D integer array (done for you). Use the row and column information provided above to determine the optimal strategy. Your result will be highlighted in yellow when the game is running. The user is not required to use the optimal strategy, however. Post-lab: Splitting Complete the methods in BlackJackHand and BlackJackPlayer relevant to splitting. Make-Up Post-lab: Matrix To make up a missed post lab (5-9), modify BlackJackPlayer. Write a new class called BlackJackPlayerMatrix. BlackJackPlayerMatrix will use the matrix package instead of a 2D array. Your instance variable will be type BasicMatrixInterface. You will need to use an import statement. Refer to the documentation for the Matrix classes. The MatrixCreator class has one static method needed to obtain a matrix: public static MatrixOperationsInterface create(int rows, int columns) Laboratory 11: Inheritance Hierarchies Java API Pre-lab: Review inheritance, abstract classes and methods, etc. Review Comparable and using an interface and an inheritance hierarchy together. Refer to the examples below for a sample bibliography containing all of the different types of citations. [1] Prince, Dinah. "Marriage in the '80s." New York 1 June 1987: 30-38. (paraphrase) o A magazine citation with a single author. The name of the periodical is New York, and the date of the issue is 1 June 1987. [2] Booth, Wayne, et al. "Kenneth Burke's Way of Knowing." Critical Inquiry 1 (1974): 1-22. (direct quote) o A journal citation with multiple authors. The name of the journal is Critical Inquiry, the volume number is 1. [3] Fairbanks, Carol. Prairie Women: Images in American and Canadian Fiction. New Haven: Yale UP, 1986. 325-327. (direct quote) o A book citation. New Haven is the city of publication. The publisher is Yale UP (University Press). [4] Baum, Rosalie. "Alcoholism and Family Abuse in Maggie and The Bluest Eye." Mosaic 19.3 (1986): 91-105. (paraphrase) o Another journal citation. Note that this citation has a volume number of 19 and an issue number of 3. Here is a good place for the use of a convenience constructor to provide an issue number. [5] Quirk, Randolph, et al. A Comprehensive Grammar of the English Language. London: Longman, 1985. 11-19. (paraphrase) o Another book citation. [6] Gordon, Alan, et al. Humanistic Scholarship in America. Proc. of the Conference on the Princeton Studies in the Humanities. 5-6 Nov. 1965. Princeton: Princeton U, 1966. 499-502. (paraphrase) o A proceedings citation with multiple authors. Note the name and date of the conference. [7] Winks, Robin, et al. "The Sinister Oriental Thriller: Fiction and the Asian Scene." Mosaic 19.3 (1986): 49-61. (paraphrase) o Another journal citation. Note that this journal appears earlier. Use a convenience constructor to pass in the earlier journal so that the repetitive information is easily obtained. [8] Ferrara, Jerry, et al. "Why Vultures Make Good Neighbors." National Wildlife June - July 1987: 16-20. (paraphrase) o Another magazine. [9] Reger, Zita, et al. "The Functions of Imitation in Child Language." Applied Psycholinguistics 7 (1986): 323-352. (paraphrase) o Another journal. [10] Morrison, Tim. Humanistic Scholarship in Europe. Proc. of the Conference on the Princeton Studies in the Humanities. 5-6 Nov. 1965. Princeton: Princeton U, 1966. 99-104. (paraphrase) o A proceedings citation that uses an earlier proceedings. [11] Hansberry, Lorraine. A Raisin in the Sun. Black Theater: A Twentieth Century Collection of the Work of its Best Playwrights. Ed. Lindsay Patterson. New York: Dodd, 1971. 221-276. (paraphrase) o An anthology citation. New items include the name of the work inside the anthology and the name of the editor. [12] Walsh, John. "U.S. - Japan Study Aim Is Education Reform." Science 16 Jan. 1987: 274-275. (paraphrase) o Another magazine. [13] Gilbert, Sandra, et al. Acts of Attention: The Poems of D. H. Lawrence. Ithaca: Cornell UP, 1972. 11-19. (direct quote) o Another book. [14] Lazard, Naomi. In Answer to Your Query. The Norton Book of Light Verse. Ed. Russell Baker. New York: Norton, 1986. 52-53. (paraphrase) o Another anthology. [15] Ferrara, Jerry, et al. "The Mysterious Platypus." Science 16 Jan. 1987: 77-78. (paraphrase) o Another magazine that uses an earlier magazine. [16] Truman, James, et al. The Light Fantastic. The Norton Book of Light Verse. Ed. Russell Baker. New York: Norton, 1986. 102-105. (paraphrase) o Another anthology that uses an earlier anthology. [17] Gilbert, Sandra, et al. Acts of Attention: The Poems of D. H. Lawrence. Ithaca: Cornell UP, 1972. 22-24. (paraphrase) o Another book that uses an earlier book with different page numbers. Lab: Inheritance o extends o super o protected o abstract classes and/or methods o overriding and overloading equals constructors o implements o indirect Reinforce o Comparable Interface o Get Methods Part I: The Parent Class For this lab, assume all instance variables have private visibility except for boolean multiple (see later). It is up to you to determine where abstract classes and methods should be used in the following description of the Citation Hierarchy. You should use abstract somewhere. Also, don't write any set methods in this lab. Instance variables can only be set through constructors. Write a class called Citation. As the parent class, Citation stores the elements of a cited work that are common to all possible Citations (but Citation may not represent a real Citation on its own). Citation stores the citation number (corresponding to the order that the citation appears in the associated paper, check user input) and whether the citation is a direct quote or a paraphrase. Citation also stores a boolean (multiple) that can be used to indicate whether the Citation requires special formatting for several authors or not (et al.). You will give the multiple indicator visibility such that it is directly available to subclasses only (protected visibility). Do not write a get method for multiple, use it directly when needed, and set it directly in the child constructors. A need for special formatting for several authors is common to all Citations. What does this fact imply about the author information? Make sure to store the first name and last name separately. What else, if anything, could be placed in Citation? So that your hierarchy is consistent with mine, use the following Citation constructor (additional Citation instance variables are possible, but place them in the child classes): public Citation(int citeNum, boolean quote, String authorLastName, String authorFirstName, int startPage, int endPage) //remember, multiple should be accessed directly in the child classes Write a protected method (endCitation) method to return a String with the starting and ending page numbers and the text "(direct quote)" or "(paraphrase)" that will be added to the end of a citation. As the starting and ending pages and the text direct quote/paraphrase must appear at the end of the citation, this part cannot be prepared in the Citation class but must be appended in the child classes when appropriate. Write a protected method (startCitation) to return the start of a citation correctly formatted. Write a public method citation to return the entire correctly formatted Citation. However, in the Citation class, the citation method can only prepare the start of the citation. The child classes will be responsible for making sure that the entire citation is correct for the particular work being cited. Use super wherever appropriate. Allow Citations to be compared by citation number (for sorting-- you need to implement an interface). Write two non-static equals methods. The first will override the equals method inherited from Object (and will call the second equals method). The second will overload the equals method to compare two Citations based on the citation number. Use your method for comparing citations to perform the test for equality. You will be comparing Citations in the next lab. Part II: The Child Classes Complete the hierarchy given the following class names, in no particular order: Proceedings (a collection of papers corresponding to talks given at a conference bound into book form) Periodical (any publication that appears regularly at fixed intervals) Anthology (a collection of works bound into book form) Journal (published at regular intervals) Book Magazine Each subclass should have overloaded constructors as needed that call one another. In particular, provide a convenience constructor for Citations that have several items in common with other Citations. For example, suppose that you need a citation for a given Book for pages 12-14 and another citation for the same Book but pages 64-65. It would be convenient to have a Book constructor accept another Book as a parameter so that all the elements in common can easily be placed into the new Book citation without the user having to specify all of the details again. Do the same for other subclasses as necessary. Also, note the use of issue in some cases for the Journal citations. Refer to the driver class below to determine the order that items should be accepted by your constructors. Your hierarchy should have at least three levels where Citation is the parent class to all of the other classes and counts as level 1. Part III: CitationDriver Test your hierarchy with CitationDriver. You should obtain the output shown in the pre-lab. Part IV: UML Draw the UML diagram for your Citation hierarchy and your CitationDriver. Include the Comparable interface in your diagram. You may omit the method section. Hand this in. Post-lab: Website Citations Websites are commonly used as sources in research papers. Find out how websites are cited here. Add a Website branch into your hierarchy. Start your Website branch with an abstract Website class that extends Citation. Include the following instance variables in your Website class: 1. private String siteTitle; 2. private String dateAccessed; 3. private String url; Extend this abstract class as much as necessary to do the job right. Add Website citations to your driver. Test all of your new concrete (i.e. non-abstract) classes. Make sure that the resulting output is correct. Laboratory 12: Collection Polymorphism Java API Pre-lab: Review polymorphism for both inheritance hierarchies and interfaces. Review the foreach statement. You will be building on your work in the previous lab. Refer to the ArrayList class as necessary. Lab: Polymorphism o Inheritance Polymorphism o Interface Polymorphism Reinforce o Comparable Interface o ArrayList o for-each o Set Methods Testing Part I: Bibliography Write a collection class (Bibliography.java) that encapsulates an ArrayList to store an unspecified number of any type of Citation. Write an add method that will accept a Citation and will return a boolean. Will this method allow you to add all of the different types of Citations? Inside the add method, the Citation object passed in is added into the ArrayList so that the items are stored in increasing citation number order even if they are not added to the Bibliography in that order. Do not use a sorting algorithm but rather find the correct insertion location for the item when it is added to the Bibliography. Do not use a get method to determine the insertion location. Do you need to cast to keep the citations in citation number order? Do not allow a citation to be added if there is already one in the Bibliography with the same citation number. Use the equals method in Citation to determine if there already is a Citation with that number in the Bibliography. Do you need to cast to check for equality? Return true if the insertion is successful and false otherwise. Have your add method filter out Periodicals so that they are not inserted into the Bibliography. Write a bibliography method to return the entire set of bibliographic citations in the order that they are stored in the ArrayList (return a String). Use a for-each statement. Do you need to cast to create the bibliography? Write a helper method to renumber the citation numbers (you will need to add a set method to the Citation class) to close any gaps in the numbering, if there are any gaps. Call this helper method just before generating the bibliography. Overload the add method to accept a Comparable. Call the other add method from within this method to actually perform the addition, however. Can you use this add method to add your Citations? Part II: CitationDriver Write a driver (CitationDriver) to test your Bibliography. Insert all of your Citations into a polymorphic array of type Citation[]. You may use the same Citations from the previous lab with any modifications required to use your polymorphic array. That is, start with CitationDriver. Write the following two static methods in CitationDriver: public static void add(Bibliography bib, Citation[] cites) //attempt to insert all of the Citations from your array into the Bibliography-- use a for-each statement public static void add(Bibliography bib, Comparable comp) //attempt to insert a single Comparable into the Bibliography Print to the screen whether an insertion was successful or not (simply print the value returned from the Bibliography add method). Temporarily give the Bibliography add method that takes a Citation private visibility. Does your driver still work? Why? Comprehensively test your Bibliography implementation. Add citations in unsorted order (add citation 7, then 4, then 27, etc.). Make sure that any gaps in citation numbering are closed. Make sure that duplicate citation numbers are not added. Make sure that Periodicals are filtered out. Make sure that you can add Citations through the add method that takes a Comparable (how do you do this?). Make sure that Comparables that are not actually Citations are filtered out (use the CD class to do this test). Download TestDriver.class, Debug.class, and CD.class (which is used in TestDriver). Run TestDriver. You should obtain the following output: true true true true false true true true true false true true true true false true false true true true [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] original number, 1. original number, 2. original number, 3. original number, 4. original number, 5. original number, 10. original number, 12. original number, 14. original number, 17. original number, 20. [11] [12] [13] [14] [15] [16] original original original original original original number, number, number, number, number, number, 24. 25. 27. 31. 32. 50. When you get this output, you are done with this part. Part III: UML Modify your UML diagram from the previous lab to include Bibliography. Make any other modifications that are necessary to describe the relationships of your classes in this lab. You may omit the method sections. Hand this in. Post-lab: Remove and Iterator Write a remove method which takes a citation number as a parameter. Look for that number in your Bibliography. If it is found, remove it and return true. Otherwise, return false. Test your work. Along with the Comparable interface, there is another useful built-in interface in Java, the Iterator interface (import java.util.Iterator;). This interface is important for "looping" over all of the items in a collection, such as all of the Citations in your Bibliography. In fact, the for-each statement really uses the Iterator interface behind the scenes. Modify your bibliography method in the Bibliography class to use an Iterator instead of the for-each statement. Simply call the iterator() method on your ArrayList to obtain the Iterator for the ArrayList. Once you have the Iterator, you may use the methods available to loop over all of your Citations. Typically a while loop is used with an Iterator. The Iterator interface has the following methods: public boolean hasNext() //are there any more Objects to process? public Object next() //get the next Object public void remove() //you don't need this one Laboratory 13: Exception Handling and File I/O Java API Pre-lab: Review exceptions and exception handling. In particular, review how checked and unchecked exceptions must be treated differently. Review file I/O including writing objects to a file. Lab: Exceptions o Custom Checked Exceptions Throwing Exceptions Error Messages Additional Information o Handling Exceptions File I/O o Text Files o Serializing Objects Part I: Custom Exception Create a custom checked exception (CitationException) similar to the class examples initially. Add a Citation instance variable. Overload the constructor to accept an error message and a Citation object. Have the first constructor call the second. What should be the second parameter? In the second constructor, copy the Citation object into the instance variable. Add a method (getProblemCitation) to return the Citation object associated with the error message. Modify the Citation hierarchy as necessary to throw a CitationException if the citation number is <= 0. You could (not required) also check to make sure that nulls have not been passed in as arguments to the Citation constructor. You will need to use the single parameter constructor in CitationException as no Citation object has been created. Use an appropriate error message for each problem that you check for. What would change if you had made CitationException an unchecked exception? Part II: Propagating and Handling Exceptions Book Proceedings (a collection of papers corresponding to talks given at a conference bound into book form) Anthology (a collection of works bound into book form) Allow Periodicals to be added to your Bibliography. Modify Bibliography to throw an exception if a duplicate citation number is detected. The add method can be void as we are using exceptions to identify the user of problems rather than a boolean. Also have Bibliography throw an exception if gaps are detected when the bibliography method is called. Use a helper method to determine if gaps are present. Do not renumber as you did in the previous lab. It is best not to assume how the user wants to handle a given problem. Use the CitationException constructor that allows you to store the Citation that caused the problem. Modify your driver from the previous lab to report any errors detected. Structure your try-catch blocks so that no additional processing is done once a problem has been detected. Display the Citation that caused the problem (by calling the citation method) when one is available. Test all possible errors (create errors as needed) to make sure that you are correctly handling all of the exceptions and reporting all of the correct information in each case. When you are sure that everything is working, take the errors out and move onto the next part. Part III: File I/O Complete the following methods in Bibliography (you will need to rethrow exceptions): 1. public void writeToFile(String fileName) throws CitationException //writes the bibliography out to a text file (i.e. bib.txt) 2. public void writeToDisk(String fileName) throws CitationException //writes the ArrayList encapsulated by the Bibliography object out to a file (i.e. bib.dat) 3. private static ArrayList readFromDisk(String fileName) throws CitationException //reads an ArrayList in from a file The third method is called from an overloaded constructor that accepts a file name to instantiate a Bibliography object based on the information stored in the file. At the end of your try-catch in your driver, add code to save your bibliography to a text file and to save your ArrayList to a file. In a separate try-catch, instantiate a new Bibliography based on the saved ArrayList and print the resulting bibliography out to a text file. Make sure that the two text files are not empty and have identical contents. Check everything with TestDriver. Here is the output that you should obtain. Your error messages will be different, but should convey the same information. The citation number must be greater than 0. Duplicate citation number encountered. [3] Hansberry, Lorraine. A Raisin in the Sun. Black Theater: A Twentieth Century Collection of the Work of its Best Playwrights. Ed. Lindsay Patterson. New York: Dodd, 1971. 221-276. (paraphrase) Gap found in bibliography. [55] Gilbert, Sandra, et al. Acts of Attention: The Poems of D. H. Lawrence. Ithaca: Cornell UP, 1972. 22-24. (paraphrase) In addition, the text files out.txt and test.txt should be exactly the same. Post-lab: Abstracting ArrayList Serialization Above, you wrote code to read and write an ArrayList of Citations to and from disk inside Bibliography. This is not ideal as you will need to use the same code with slight modifications in future programs to process ArrayLists. It is much better to abstract this process into a new class that can be used whenever you need to process ArrayLists. Write a class (SerializeArrayList) that will provide methods to read and write any ArrayList to and from disk. Include the following methods: 1. public static ArrayList readFromDisk(String fileName) //returns null if a problem occurs 2. public static int writeToDisk(String fileName, ArrayList al) //returns -1 if a problem occurs Modify Bibliography to use your new class. Test your work. More Object Serialization Sometimes your objects contain sensitive information that you don't really want to save to disk when you serialize those objects. Find out how to keep a field from being saved during object serialization (hint: look at page 685). Keep the author's last name from being saved to disk. Rerun your driver. What happened? Laboratory 14: Graphics and GUIs You may need the following Java API links: Entire Java API Graphics Class Timer Class MouseListener Interface Pre-lab: Review Graphics and GUIs. In this lab you will be modifying some existing code to create a moderately complex graphical scene that responds to mouse events. You are provided with a Shape hierarchy, a Tree class (and its component classes), a Car (yes, it's really a bus) class (and its component classes), and a JFrame subclass, DrawCanvas, to render the scene. Compile DrawDriver and run the program (download all the files below into the same directory). Use make.bat for compiling and running as the classpath must be modified to use matrix.jar (for complex transformations of objects in the scene). Click inside the window to start the car moving across the scene. Double click on DrawDriverFinal to see what you are trying to accomplish in this lab. Starting files: Get them all in a zip file Visual.java Shape.java Rectangle.java Square.java Ellipse.java Circle.java Trunk.java Branch.java Leaves.java Tree.java CarBody.java Wheel.java Car.java DrawDriver.java DrawCanvas.java Picture.class RGBA.class matrix.jar make.bat background.raw DrawDriverFinal.exe Lab: Reinforce o Has-a Relationship o Is-a Relationship o Object Arrays o Interfaces Basic Graphics o Shape Hierarchy o Visual Interface o Graphics class Basic GUIs o Mouse Events o Timer o repaint Part I: Creating a Forest Write a class called Forest. Implement the Visual interface to guarantee a visual behavior for your forest object. Write a constructor to allow the user to specify the number of trees in your forest. Allow the user to also specify the max and min x and y values for the horizontal center and base of the trees in the forest (you will need to refer to the Tree class). Finally, the user can specify the max and min width and height of the trees in the forest, and the max and min angles for the branches. Generate the number of trees specified, with randomly generated locations, sizes, and angles based on the ranges specified. Loop over the trees (use a for-each statement), drawing them in your draw method. Add your forest to the scene (in DrawDriver), and modify the ranges to generate a forest for your scene. Make sure that the car is rendered on top of your forest. Part II: Creating a Face Write a class called Face. Extend Circle and use inheritance to draw a face with eyes and a smile. Add a face to the Car class as an additional component (the driver of the car). Include the rendering of the face in the draw method of Car. Modify parameters as necessary to get the driver in the window of the car. You will need to add a move method to the Face class so that as the car moves, the face will move with it. Post-lab: Mouse Events Modify your DrawCanvas class so that when the mouse is pressed in the scene, the animation begins (already done for you). If the mouse is pressed again, the animation ends. If the mouse exits the scene, the smiley face turns to a frowny face. If the mouse enters, the smiley face returns. You will need to add a change method to some classes, and provide an alternate rendering of the face as necessary. Make-Up Post-lab: Be Creative To make up a missed post lab (10 - 13), do the following. Make some additions and/or modifications to this lab. You may do anything that you want as long as it involves some Graphics or GUI feature that has not been covered in this lab, has not been covered in class, and isn't a trivial change.