![]() |
Wellesley College, Summer 2003
Problem Set 8Due: Tue., July 8 by 6pm |
IntListList ContractIntListListOps ContractIntListListFunctions.java
within the lec10_lists/IntListLists folder.IterationWorld.java
within the lec11_iteration/BuggleIteration folder.IntFunctions.java
within the lec11_iteration/IntIteration folder.
IntListFunctions.java
within the lec11_iteration/IntListIteration folder.
GraphicsDemo.java,
Circles.java, and
Ovals.java
within the lec12_graphics_objects/GraphicsDemo folder.
The purpose of this problem set is to give you with lists of lists, iteration (tail recursion, while loops, and for loops), and Java graphics. In Task 1, you will use list of lists to determine all the different ways to make change for a given amount of money. In Task 2, you will use iteration to manipulate lists. In Task 3, you will use Java graphics to draw simple cartoon faces.
There are also an optional open-ended extra-credit opportunity for you to use Java Graphics to draw any picture(s) of your own design.
All code for this assignment is available
in the ps8_programs folder in the cs111d download
directory on the cs file server.
ChangeMaker.java file from Task 1.
Partition.java file from Tasks 2b, 2c, 2d, and 2e;
Faces.java from Task 3.
MyPicture.java from
(optional) Extra Credit Challenge 1.
ps8_programs folder. In particular,
ChangeMaker subfolder should
contain your final version of ChangeMaker.java.
Partition subfolder should
contain your final version of Partition.java.
Faces subfolder should
contain your final version of Faces.java.
MyPicture subfolder should
contain your final version of MyPicture.java
(if you did the first extra credit challenge).
Lists of lists are useful data structures for holding lists of possibilities. We can use them to hold the list of all subsets of a set of numbers like we saw in lecture. We could also use them to hold a list of all permutations of a list of numbers, using an approach similar to computation of string permutations considered in the previous problem set. In this problem, we will use lists of lists to represent all the possible ways of making change for a given amount of money given an unlimited number of coins with certain denominations. Some examples are given below (assume all values are in cents).
| Amount to change | Denominations | Ways to Make Change |
|---|---|---|
| 5 | [5,1] | [[5], // 1 nickel [1, 1, 1, 1, 1] // 5 pennies ] |
| 16 | [10,5,1] | [[10, 5, 1], // 1 dime, 1 nickel, and 1 penny [10, 1, 1, 1, 1, 1, 1], // 1 dime and 10 pennies [5, 5, 5, 1], // 3 nickels and 1 penny [5, 5, 1, 1, 1, 1, 1, 1], // 2 nickels and 6 pennies [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], // 1 nickel and 11 pennies [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] // 16 pennies. ] |
Your goal is to formulate a strategy that will list all the possible
ways to make change for a given amount of money with a list of possible
coin denominations provided in descending order of value. You will be completing
the method makeChange of the ChangeMaker class.
The skeleton for the method is provided below:
public static IntListList makeChange (int amount, IntList coins)
Returns a list of possible ways to make change foramountusing the coin denominations in the listcoins. Assume the integers incoinsare in descending order of value.
Complete this problem by fleshing out the definition of makeChange
in the ChangeMaker.java file within the ChangeMaker
folder.
ChangeMaker.mcp project is configured so that it
tests makeChange on a number of test cases when you
run the project.
The correct output for the test cases is provided at the end of this problem
description. You need to get the same number of ways to make change and the same ways to
make change as listed, but you may list the ways to make change in any order and may list
the coins in any order.
ChangeMaker class has been configured so that you can use the
IL. prefix for IntList methods, and the
ILL. prefix for IntListList methods.
| IntList Methods (IL) | IntListList Methods (ILL) |
|---|---|
IL.empty IL.prepend IL.head IL.tail IL.isEmpty IL.toString IL.fromString IL.length IL.append IL.postpend |
ILL.empty ILL.prepend ILL.head ILL.tail ILL.isEmpty ILL.toString ILL.fromString ILL.length ILL.append ILL.postpend ILL.mapPrepend |
Note that the IntListList operations include the
mapPrepend method discussed in lecture. It is defined as:
public static IntListList mapPrepend (int n, IntListList L) {
if (ILL.isEmpty(L)) {
return L;
} else {
return ILL.prepend (IL.prepend(n, ILL.head(L)),
mapPrepend(n, ILL.tail(L)));
}
}
Correct Test Case Answers
---------------------------------------------------- There are 1 ways to make change for 5 cents using [5]: [[5] ] ---------------------------------------------------- There are 1 ways to make change for 5 cents using [10, 5]: [[5] ] ---------------------------------------------------- There are 1 ways to make change for 10 cents using [5]: [[5, 5] ] ---------------------------------------------------- There are 2 ways to make change for 10 cents using [10, 5]: [[10], [5, 5] ] ---------------------------------------------------- There are 1 ways to make change for 15 cents using [5]: [[5, 5, 5] ] ---------------------------------------------------- There are 2 ways to make change for 15 cents using [10, 5]: [[10, 5], [5, 5, 5] ] ---------------------------------------------------- There are 0 ways to make change for 16 cents using [10, 5]: [] ---------------------------------------------------- There are 2 ways to make change for 5 cents using [5, 1]: [[5], [1, 1, 1, 1, 1] ] ---------------------------------------------------- There are 3 ways to make change for 10 cents using [5, 1]: [[5, 5], [5, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ] ---------------------------------------------------- There are 4 ways to make change for 10 cents using [10, 5, 1]: [[10], [5, 5], [5, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ] ---------------------------------------------------- There are 4 ways to make change for 15 cents using [5, 1]: [[5, 5, 5], [5, 5, 1, 1, 1, 1, 1], [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ] ---------------------------------------------------- There are 6 ways to make change for 15 cents using [10, 5, 1]: [[10, 5], [10, 1, 1, 1, 1, 1], [5, 5, 5], [5, 5, 1, 1, 1, 1, 1], [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ] ---------------------------------------------------- There are 6 ways to make change for 16 cents using [10, 5, 1]: [[10, 5, 1], [10, 1, 1, 1, 1, 1, 1], [5, 5, 5, 1], [5, 5, 1, 1, 1, 1, 1, 1], [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ] ---------------------------------------------------- There are 13 ways to make change for 26 cents using [25, 10, 5, 1]: [[25, 1], [10, 10, 5, 1], [10, 10, 1, 1, 1, 1, 1, 1], [10, 5, 5, 5, 1], [10, 5, 5, 1, 1, 1, 1, 1, 1], [10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [5, 5, 5, 5, 5, 1], [5, 5, 5, 5, 1, 1, 1, 1, 1, 1], [5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ] ---------------------------------------------------- There are 60 ways to make change for 56 cents using [25, 10, 5, 1]: [[25, 25, 5, 1], [25, 25, 1, 1, 1, 1, 1, 1], [25, 10, 10, 10, 1], [25, 10, 10, 5, 5, 1], [25, 10, 10, 5, 1, 1, 1, 1, 1, 1], [25, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [25, 10, 5, 5, 5, 5, 1], [25, 10, 5, 5, 5, 1, 1, 1, 1, 1, 1], [25, 10, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [25, 10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [25, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [25, 5, 5, 5, 5, 5, 5, 1], [25, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1], [25, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [25, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [25, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [25, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [25, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 10, 10, 10, 10, 5, 1], [10, 10, 10, 10, 10, 1, 1, 1, 1, 1, 1], [10, 10, 10, 10, 5, 5, 5, 1], [10, 10, 10, 10, 5, 5, 1, 1, 1, 1, 1, 1], [10, 10, 10, 10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 10, 10, 5, 5, 5, 5, 5, 1], [10, 10, 10, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1], [10, 10, 10, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 10, 10, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 10, 10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 10, 5, 5, 5, 5, 5, 5, 5, 1], [10, 10, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1], [10, 10, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 10, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 10, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 10, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1], [10, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1], [10, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1], [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1], [5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ]
The following partitionIter method takes an integer named
pivot and a list of integers named L and
partitions the list into two lists:
L less than pivot.
L greater than or equal to pivot.
The two resulting lists are returned in a two-element IntListList --
i.e., a list of two integer lists.
public static IntListList partitionIter (int pivot, IntList L) {
return partitionTail(pivot, L, IL.empty(), IL.empty());
}
public static IntListList partitionTail (int pivot, IntList list,
IntList lesses, IntList greaters) {
if (IL.isEmpty(list)) {
return twoLists(lesses, greaters);
} else if (IL.head(list) < pivot) {
return partitionTail(pivot, IL.tail(list),
IL.prepend(IL.head(list), lesses), greaters);
} else {
return partitionTail(pivot, IL.tail(list),
lesses, IL.prepend(IL.head(list), greaters));
}
}
Because the program manipulates both IntList and IntListList
objects, it is necessary to distinguish the list operations for these
different kinds of lists. As in Task 1, we will use IL. to prefix
IntList operations and ILL. to prefix
IntListList operations. To make the code more readable, we
use the following helper method:
public static IntListList twoLists (IntList L1, IntList L2) {
return ILL.prepend(L1, ILL.prepend(L2, ILL.empty()));
}
partitionTail method is a tail recursive method that
specifies an iteration in four state variables named
pivot, list, lesses, and
greaters. Any iteration can be characterized by how the
values of the state variables change over time. Below is a table with
four columns, one for each state variable of the iteration described
by partitionTail. Each row represents the values of the
parameters to a particular invocation of partitionTail.
| pivot | list | lesses | greaters |
Suppose that the list A has the printed representation
[7,2,3,5,8,6,1]. Fill in the above table to show
the parameters passed to successive calls to partitionTail in the computation that begins with the
invocation partitionIter(5, A). There are more rows shown here than you need, so you should draw only
as many rows as you need to in your table.
partitionWhilewhile loop.
Flesh out the following code skeleton of a partitionWhile method that
behaves just like the above partitionIter method except that it uses a
while loop rather than tail recursion to express the same iteration
as partitionTail.
public static IntListList partitionWhile (int pivot, IntList L) {
// Replace this stub
return ILL.empty();
}
Notes:
partitionWhile
method in the file Partition.java within the
Partition folder.
IntList
operations from IntListList operations. The prefix
IL. will be used for the former and ILL.
for the latter.
while loop has the syntax
while (test-expression) {
body-statements
}
while loop
to implement the iteration implied by the iteration table.
The body of this loop may contain any Java statements, including
conditionals, but should not contain other while loops.
Partition.mcp project invokes the main
method of the Partition class, which will run the methods of
this task on various test cases. You should study the results of
the test cases in the Java console window to verify
that the results are what you expect.
partitionForpartitionTail and
partitionWhile can also be expressed via a
for loop whose index variable is the list
state variable. Flesh out the skeleton of the following method
so that it expresses the partitioning iteration with a
for loop:
public static IntListList partitionFor (int pivot, IntList L) {
// Replace this stub
return ILL.empty();
}
Recall that a Java while loop has the syntax
for (init-statement; test-expression; update-statement) {
body-statements
}
The above for loop is
equivalent to the following
while loop:
init-statement;
while (test-expression) {
body-statements;
update-statement;
}
partitionRecpartitionIter method, elements in the two
returned lists are in a relative order opposite to their relative
order in the original lists. For instance, partitioning the list
[1, 4, 8, 3, 6, 7, 5, 2] about the pivot 6 yields the lists
[2, 3, 4, 1] and [7, 6, 8].
Suppose that we want the resulting lists to have the same relative
order as in the original list. If we are provided with an IntList reversal
method IL.reverse, we can easily accomplish this by reversing the two
lists before gluing them together. That is, we can
change the line
return twoLists(lesses, greaters);within
partitionTail to be
return twoLists(IL.reverse(lesses), IL.reverse(greaters));
An alternative to using IL.reverse to achieve this behavior is
to define a non-tail-recursive version of partitionIter
that we will call partitionRec. Flesh out the
following skeleton of partitionRec, which partitions the elements
of a list about the pivot but maintains the relative order of the
elements in the resulting lists:
public static IntListList partitionRec (int pivot, IntList L) {
if (IL.isEmpty(L)) {
return twoLists(IL.empty(), IL.empty());
} else {
IntListList subresult = partitionRec(pivot, IL.tail(L));
// replace the following stub:
return ILL.empty();
}
}
Notes:
partitionRec should be a self-contained non-tail-recursive method
that should not invoke any of the other partitioning methods
mentioned in this problem.
The "Rec" in the name "partitionRec" stands for "Recursive",
and is intended to suggest a non-tail-recursive method.
partitionRec method is tested by the main
method of the Partition class.
quicksortTo sort the elements of a list, partition the elements of the tail of the list around its head into result lists that we'll call lesses and greaters. Then result of sorting the whole list can be obtained by appending the result of sorting lesses to the result of prepending the head of the list to the result of sorting greaters.
For example, if the initial list is [5, 2, 8, 3, 6, 7, 1, 4],
then partitioning the tail of the list around the head (5) yields:
lesses = [4, 1, 3, 2] greaters = [7, 6, 8]
By wishful thinking, sorting lesses will yield [1, 2, 3, 4]
and sorting greaters will yield [6, 7, 8].
The result of sorting the original list is the result of appending
[1, 2, 3, 4] to the result of prepending 5 to
[6, 7, 8].
Flesh out a method with header public static IntList quicksort (IntList L)
that uses this idea to sort the elements of a list. You may use IL.append
to append two lists and any of the above partitioning methods to partition a list.
The quicksort method is tested by the main
method of the Partition class.
It turns out that quicksort, true to its name, is one of the fastest algorithms for sorting a list. If you take CS230 and CS231, you will learn (among other things) much more about various sorting algorithms and how to compare them in terms of efficiency.
In this problem, we will model simple cartoon faces like those shown below:
Each face is characterized by the following features:
For example, the following table shows the values for the color (r = red, g = green, and b = blue), happiness (h) and sleepiness (s) of each face in the corresponding position in the figure above:
|
r=255,
g=0,
b=0, h=0.0, s=0.0 |
r=255,
g=63,
b=0, h=0.25, s=0.0 |
r=255,
g=127,
b=0, h=0.50, s=0.0 |
r=255,
g=191,
b=0, h=0.75, s=0.0 |
r=255,
g=255,
b=0, h=1.0, s=0.0 |
|
r=255,
g=0,
b=63, h=0.0, s=0.25, |
r=255,
g=63,
b=63, h=0.25, s=0.25 |
r=255,
g=127,
b=63, h=0.50, s=0.25 |
r=255,
g=191,
b=63, h=0.75, s=0.25 |
r=255,
g=255,
b=63, h=1.0, s=0.25 |
|
r=255,
g=0,
b=127, h=0.0, s=0.50 |
r=255,
g=63,
b=127, h=0.25, s=0.50 |
r=255,
g=127,
b=127, h=0.50, s=0.50 |
r=255,
g=191,
b=127, h=0.75, s=0.50 |
r=255,
g=255,
b=127, h=1.0, s=0.50 |
|
r=255,
g=0,
b=191, h=0.0, s=0.75 |
r=255,
g=63,
b=191, h=0.25, s=0.75 |
r=255,
g=127,
b=191, h=0.50, s=0.75 |
r=255,
g=191,
b=191, h=0.75, s=0.75 |
r=255,
g=255,
b=191, h=1.0, s=0.75 |
|
r=255,
g=0,
b=255, h=0.0, s=1.0, |
r=255,
g=63,
b=255, h=0.25, s=1.0 |
r=255,
g=127,
b=255, h=0.50, s=1.0 |
r=255,
g=191,
b=255, h=0.75, s=1.0 |
r=255,
g=255,
b=255, h=1.0, s=1.0 |
In the following parts, you will be implementing in stages
the following drawFace class method
within the Face class:
public static void drawFace (Graphics g, Rectangle r, Color c, double h, double s)
Using graphics contextg, draws a face with colorc, happinessh, and sleepinesssin the specified rectangler.
drawFace class method.
For this part,
you should ignore the actual happiness parameter h
and sleepiness parameter s and
assume that they both have values 1.0.
That is, the face you draw should be happy and alert.
However, your method should draw the face
using the actual color c of the face.
When you run the ManyFaces.html applet,
the goal is to get the following picture:
Below is a diagram of a happy face inscribed in the unit square indicating the placement of the eyes, nose, and mouth. You should draw the happy face exactly as depicted in this diagram.
Notes:
Graphics class presented
in lecture and lab. As part of doing this problem, you should
consult the contract for the Graphics class.
You will also need to use the contracts for the
Rectangle
and
Polygon
classes.
Graphics class expect
integers as arguments. The java compiler will complain if you
pass a floating point number rather than an integer as an argument
to one of these methods. For instance, if
g denotes a Graphics instance and
r denotes a Rectangle instance,
then the following is incorrect:
g.drawLine(r.x + (0.1 * r.width),
r.y + (0.3 * r.height),
r.x + (0.7 * r.width),
r.y + (0.6 * r.height));
This problem can be fixed by using an integer cast expression
(int) E to convert the result of a floating point
expression E to an integer. A corrected
version of the above example is:
g.drawLine(r.x + (int) (0.1 * r.width),
r.y + (int) (0.3 * r.height),
r.x + (int) (0.7 * r.width),
r.y + (int) (0.6 * r.height));
OneFace.html applet. You can do this
by moving OneFace.html before
ManyFaces.html in the Face.mcp project file.
Here is the window produce by this applet:
drawFace method so that it correctly shows
droopy eyelids for sleepy faces, as shown below:
A face with sleepiness factor s (between 0.0 and 1.0) should have "eyelids" covering a fraction s of the height of the eyes from the top to the bottom. This effect can be achieved as follows:
Note that, according to its contract,
the drawOval() method
covers an area that is width + 1 pixels wide and
height + 1 pixels tall. In contrast, the
the fillOval() method
covers an area that is width pixels wide and
height pixels tall.
Because of this discrepency, to get your picture to
"look right" you may need to subtract 1 from the
width and height arguments of drawOval().
drawFace method so that it takes
into account the happiness of the face. A face with
happiness 0.0 should have a line as a mouth, while
larger happiness values (up to 1.0) should be drawn
as filled half-ovals whose height is proportional
to the happiness value.
For example, here are faces whose happiness value changes from left to right:
Here is the specification for the mouth that you should implement:
Math.max()
method, which returns the maximum of two integers.
The above specification can be implemented via a single
invocation of the fillArc() method that
handles all happiness values between 0.0 and 1.0.
The key to getting this to work is to determine
the coordinates of the rectangle in which the arc is
inscribed as a function of the happiness value.
Do not attempt to do this by trial and error!
Instead, determine the correct formula on a sheet
of paper before you attempt to implement this
part!
This is a completely optional problem. You should only attempt it after completing the rest of the assignment.
You can use Java graphics as a tool to create fascinating pictures. Here is a chance to be artistically creative and earn some extra credit points at the same time.
For this challenge, flesh out the paint()
method in the MyPicture class within
the MyPicture folder to draw whatever
picture you imagine. If you like, you can draw more
than one by making copies of MyPicture.java
where the files (and the contained class) have different
names.
Notes: