handout # 7
CSE143—Computer Programming II
Programming Assignment # 7: 20 Questions
due: Thursday, 11/29/18 11:30 pm
This assignment will give you practice with binary trees. You are to implement a yes/no guessing game. The idea is that you construct a binary tree where each leaf has the name of an object and each branch node has a yes/no question that distinguishes between the objects. It’s like a big game of 20 questions where each question is a yes/no question.
Each
round of the game begins by you (the human player) thinking of an object. The computer will try to guess your object by
asking you a series of yes or no questions.
Eventually the computer will have asked enough questions that it thinks
it knows what object you are thinking of.
It will make a guess about what your object is. If this guess is correct, the computer wins;
if not, you win.
The
computer keeps track of a binary tree whose nodes represent questions and
answers. (Every node's data is a string
representing the text of the question or answer.) A “question” node contains a left “yes”
subtree and a right “no” subtree. An
“answer” node is a leaf. The idea is
that this tree can be traversed to ask the human player a series of
questions.
For
example, in the tree below, the computer would begin the game by asking the
player, “Is it an animal?” If the player
says “yes,” the computer goes left to the “yes” subtree and then asks the user,
“Can it fly?” If the user had instead
said “no,” the computer would go right to the “no” subtree and then ask the user,
“Does it have wheels?”
This
pattern continues until the game reaches a leaf “answer” node. Upon reaching an answer node, the computer
asks whether that answer is the correct answer.
If so, the computer wins.
Initially
the computer is not very intelligent, but it grows more intelligent each time
it loses a game. If the computer's
answer guess is incorrect, you must give it a new question it can ask to help
it in future games. For example, suppose
that the player is thinking of a cat. They will end up at the leaf node for
mouse. The computer will guess mouse and
the user will say that the guess is wrong.
At that point, the computer asks what the user was thinking of (“cat”), a
question to distinguish it from a mouse (the user might say, “Does it meow?”),
and what the answer is.
The computer takes the new information from a lost
game and uses it to replace the old incorrect answer node with a new question
node that has the old incorrect answer and new correct answer as its children:
Your program also has to be able to write the tree to an output file and read it back in. That way your question tree can grow each time a user runs the program. To be able to read and write the tree, we need a set of rules for how to represent the tree which we’ll refer to as the standard format for a question tree. A tree is specified by a nonempty sequence of line pairs, one for each node of the tree. The first line of each pair should contain either the text “Q:” to indicate that it is a question node (i.e., a branch node) or the text “A:” to indicate that it is an answer node (i.e., a leaf node). The second line of each pair should contain the text for that node (the question or answer). The nodes should appear in preorder (i.e., in the order produced by a preorder traversal of the tree).
This program involves interaction with the user. As always, we will use a Scanner linked to System.in to do this. But with interactive programs, you don’t want to have more than one Scanner linked to System.in. For that reason, in this program your class will construct the console Scanner. It turns out that all that the main method needs is the ability to ask a yes/no question of the user. So the interface for your class will include a method yesTo that main will call when it wants to interact with the user. You must construct a single console Scanner that you store in a data field and use throughout your class. All calls to the console Scanner should be on the nextLine method so that you always read an entire line of user input.
The details of the yesTo method are fairly uninteresting, so it is being provided for you (this code assumes a data field called “console” has been initialized). You are to include this method without modification in your QuestionTree class and use it whenever possible to read user input.
// post: asks
the user a question, forcing an answer of "y "
or "n";
// returns true if the answer was yes,
returns false otherwise
public
boolean yesTo(String prompt) {
System.out.print(prompt + " (y/n)?
");
String response =
console.nextLine().trim().toLowerCase();
while (!response.equals("y")
&& !response.equals("n")) {
System.out.println("Please answer y or
n.");
System.out.print(prompt + " (y/n)?
");
response = console.nextLine().trim().toLowerCase();
}
return response.equals("y");
}
The main program is called QuestionMain.java. You are to write a class called QuestionNode.java (your tree node class) and QuestionTree.java. In defining your tree node class, you should decide what data fields you need for solving this particular problem. In other words, you don’t have to use a generic binary tree; you can use one that is highly specific to this program. Your node class should have at least one constructor. It can have more than one, but don’t include any constructors that you don’t actually use in your QuestionTree class.
Your QuestionTree class should store the binary tree and should have the following public methods:
Method |
Description |
QuestionTree() |
This method should construct a question tree with one leaf node representing the object “computer”. |
void read(Scanner input) |
This method will be called if the client wants to replace the current tree by reading another tree from a file. Your method will be passed a Scanner that is linked to the file and should replace the current tree with a new tree using the information in the file. Assume the file is legal and in standard format. Read entire lines of input using calls on nextLine. |
void write(PrintStream output) |
This method will be called if the client wants to store the current tree to an output file. The given PrintStream will be open for writing. |
void askQuestions() |
In this method you should use the current tree to ask the user a series of yes/no questions until you either guess their object correctly or until you fail, in which case you expand the tree to include their object and a new question to distinguish their object from the others. |
boolean yesTo(String prompt) |
This method asks the given question until the user types “y” or “n.” It returns true if “y”, false if “n”. |
A log of execution is provided at the end
of this write-up showing how the program should interact using your
QuestionTree class. You are to exactly
reproduce the format of this log. Many
students find it easier to test and debug the write method before attempting
the read method because it is simpler and easier to verify.
In terms of correctness, your class must
provide all of the functionality described above. In terms of style, we will be grading on your
use of comments, good variable names, consistent indentation and good coding
style to implement these operations.
Remember that you will lose points if you declare variables as data
fields that can instead be declared as local variables. You should also avoid extraneous cases (e.g.,
don’t make something into a special case if it doesn’t have to be). Refer to the General Style Deductions for a
more complete list of our style expectations.
You might be tempted in writing this
program to “morph” what used to be an answer node of the tree into a question
node. This is considered bad style. Question nodes and answer nodes are
fundamentally different kinds of data.
You can rearrange where they appear in the tree, but you shouldn’t turn
a former answer node into a question node just to simplify the programming you need
to perform. You also should only create
new QuestionNodes when necessary.
You should name your files QuestionNode.java and QuestionTree.java and you should turn them in electronically from the “homework” link on the class web page. A collection of files needed for the assignment is included on the web page as a7.zip. You will need to have QuestionMain in the same directory as your files in order to run QuestionMain. The folder contains a version of question.txt, although you should be able to generate such a file from your own program. The folder also contains a file called bigquestion.txt which contains a large data file of approximately 10 thousand animal names obtained from http://animalgame.com/. Also keep in mind that you can once again use the output comparison tool to check your solution.
Sample execution (short file)
Welcome
to the cse143 question program.
Do
you want to read in the previous tree? (y/n)? n
Please
think of an object for me to guess.
Would
your object happen to be computer? (y/n)? n
What
is the name of your object? dog
Please
give me a yes/no question that
distinguishes
between your object
and
mine--> Is it an animal?
And
what is the answer for your object? (y/n)? y
Do
you want to go again? (y/n)? y
Please
think of an object for me to guess.
Is
it an animal? (y/n)? y
Would
your object happen to be dog? (y/n)? n
What
is the name of your object? frog
Please
give me a yes/no question that
distinguishes
between your object
and
mine--> Does it hop?
And
what is the answer for your object? (y/n)? y
Do
you want to go again? (y/n)? y
Please
think of an object for me to guess.
Is
it an animal? (y/n)? y
Does
it hop? (y/n)? n
Would
your object happen to be dog? (y/n)? y
Great,
I got it right!
Do
you want to go again? (y/n)? n
Sample data file question.txt (after above log)
Q:
Is it an
animal?
Q:
Does it
hop?
A:
frog
A:
dog
A:
computer