// FILE: AnimalGuess.java
// This animal-guessing program illustrates the use of the binary tree node class.
import edu.colorado.nodes.BTNode;
import java.util.Scanner;
/******************************************************************************
* The AnimalGuess
Java application illustrates the use of
* the binary tree node class is a small animal-guessing game.
*
*
Java Source Code for this class:
*
* http://www.cs.colorado.edu/~main/applications/Animals.java
*
*
* @author Michael Main
* (main@colorado.edu)
*
* @version Feb 10, 2016
******************************************************************************/
public class AnimalGuess
{
private static Scanner stdin = new Scanner(System.in);
/**
* The main method prints instructions and repeatedly plays the
* animal-guessing game. As the game is played, the taxonomy tree
* grows by learning new animals.
* @param args
* not used in this implementation
**/
public static void main(String[ ] args)
{
BTNode root;
instruct( );
root = beginningTree( );
do
play(root);
while (query("Shall we play again?"));
System.out.println("Thanks for teaching me a thing or two.");
}
/**
* Print instructions for the animal-guessing game.
**/
public static void instruct( )
{
System.out.println("Please think of an animal.");
System.out.println("I will ask some yes/no questions to try to figure");
System.out.println("out what you are.");
}
/**
* Play one round of the animal guessing game.
* @param current
* a reference to the root node of a binary taxonomy tree that will be
* used to play the game.
* Postcondition:
* The method has played one round of the game, and possibly
* added new information about a new animal.
* @exception java.lang.OutOfMemoryError
* Indicates that there is insufficient memory to add new
* information to the tree.
**/
public static void play(BTNode current)
{
while (!current.isLeaf( ))
{
if (query(current.getData( )))
current = current.getLeft( );
else
current = current.getRight( );
}
System.out.print("My guess is " + current.getData( ) + ". ");
if (!query("Am I right?"))
learn(current);
else
System.out.println("I knew it all along!");
}
/**
* Construct a small taxonomy tree with four animals.
* @return
* a reference to the root of a taxonomy tree with the animals:
* kangaroo, mouse, trout, robin.
* @exception OutOfMemoryError
* Indicates that there is insufficient memory to create the tree.
**/
public static BTNode beginningTree( )
{
BTNode root;
BTNode child;
final String ROOT_QUESTION = "Are you a mammal?";
final String LEFT_QUESTION = "Are you bigger than a cat?";
final String RIGHT_QUESTION = "Do you live underwater?";
final String ANIMAL1 = "Kangaroo";
final String ANIMAL2 = "Mouse";
final String ANIMAL3 = "Trout";
final String ANIMAL4 = "Robin";
// Create the root node with the question “Are you a mammal?”
root = new BTNode(ROOT_QUESTION, null, null);
// Create and attach the left subtree.
child = new BTNode(LEFT_QUESTION, null, null);
child.setLeft(new BTNode(ANIMAL1, null, null));
child.setRight(new BTNode(ANIMAL2, null, null));
root.setLeft(child);
// Create and attach the right subtree.
child = new BTNode(RIGHT_QUESTION, null, null);
child.setLeft(new BTNode(ANIMAL3, null, null));
child.setRight(new BTNode(ANIMAL4, null, null));
root.setRight(child);
return root;
}
/**
* Elicits information from the user to improve a binary taxonomy tree.
* @param current
* a reference to a leaf node of a binary taxonomy tree
* Precondition:
* current
is a reference to a leaf in a binary
* taxonomy tree
* Postcondition:
* Information has been elicited from the user, and the tree has
* been improved.
* @exception OutOfMemoryError
* Indicates that there is insufficient memory to add new
* information to the tree.
**/
public static void learn(BTNode current)
// Precondition: current is a reference to a leaf in a taxonomy tree. This
// leaf contains a wrong guess that was just made.
// Postcondition: Information has been elicited from the user, and the tree
// has been improved.
{
String guessAnimal; // The animal that was just guessed
String correctAnimal; // The animal that the user was thinking of
String newQuestion; // A question to distinguish the two animals
// Set Strings for the guessed animal, correct animal and a new question.
guessAnimal = current.getData( );
System.out.println("I give up. What are you? ");
correctAnimal = stdin.nextLine( );
System.out.println("Please type a yes/no question that will distinguish a");
System.out.println(correctAnimal + " from a " + guessAnimal + ".");
newQuestion = stdin.nextLine( );
// Put the new question in the current node, and add two new children.
current.setData(newQuestion);
System.out.println("As a " + correctAnimal + ", " + newQuestion);
if (query("Please answer"))
{
current.setLeft(new BTNode(correctAnimal, null, null));
current.setRight(new BTNode(guessAnimal, null, null));
}
else
{
current.setLeft(new BTNode(guessAnimal, null, null));
current.setRight(new BTNode(correctAnimal, null, null));
}
}
public static boolean query(String prompt)
{
String answer;
System.out.print(prompt + " [Y or N]: ");
answer = stdin.nextLine( ).toUpperCase( );
while (!answer.startsWith("Y") && !answer.startsWith("N"))
{
System.out.print("Invalid response. Please type Y or N: ");
answer = stdin.nextLine( ).toUpperCase( );
}
return answer.startsWith("Y");
}
}