CPS 100, Spring 2004, Twenty Questions/Animal

You may work on this assignment with a partner. You may choose your own partner or post to the bulletin board and try to find one.

As always, if you work on your own, you're expected to do the work on your own, but you can talk about high-level details with others (documented in your README file).

Introduction

The game of Twenty Questions is sometimes amusing, especially if the domain of questions is one you find interesting. For this assignment you'll write a program that permits the user to play a dynamic version of twenty questions --- dynamic in the sense that the user can add new questions, save the game, then replay the game with the new questions.

For this assignment you will write two programs

  1. animal: Play 20 questions with the user via the command line
  2. animal.cgi: Play 20 questions with the user via the web (extra credit) - due Mar. 22
Follow this link for information on the files you will need for the assignment.

Playing the Game on the Command-Line

Here's what a run of your final program should look like. The user-entered input is in italics.

prompt> animal
file name for game: animal.dat
Does it have feathers [y/n] yes
Does it live in a barnyard [y/n] yes
is it a(n) chicken [y/n] yes
I win!!!
Play again? [y/n] yes

Does it have feathers [y/n] n
Is it a mammal [y/n] y
does it have stripes [y/n] n
does it hop [y/n] n
is it a(n) elephant [y/n] n

I give up, what animal were you thinking of: lion
What question has a yes answer for a(n) lion
and a no answer for a(n) elephant.
does it have  mane

Play again? [y/n] yes
Does it have feathers [y/n] n
Is it a mammal [y/n] y
does it have stripes [y/n] n
does it hop [y/n] n
does it have a mane [y/n] yes
is it a(n) lion [y/n] y
I win!!!
Play again? [y/n] no

Thanks for playing twenty questions.
Write data to what file? [animal.dat] an2.dat

Input/Output

The input to the program will be any file in the schema below which is the pre-order traversal of a tree representing the guessing game. Note that in every such tree all non-leaf/internal nodes have two children.

  Question
  Yes Answer (left subtree)
  No  Answer (right subtree)

Questions are identified by the three-character string #Q: at the beginning of a line, lines that do not begin with the string #Q: represent answers/animals.

For the run above, the sample file animal.dat is reproduced below.



    #Q:Does it have feathers
    #Q:Does it live in a barnyard
    chicken
    #Q:is it wise
    owl
    #Q:does it gobble
    turkey
    #Q:does it say "Nevermore!"
    raven
    eagle
    #Q:Is it a mammal
    #Q:does it have stripes
    tiger
    #Q:does it hop
    kangaroo
    elephant
    gila monster

The tree that corresponds to this file is shown below. You'll need to construct a tree like this in the program you write. Note that yes answers in the tree are shown as left/blue arrows, no answers are right/red arrows.

Reading a pre-order tree

The code in treeread.cpp shows how to read a tree from the tree's pre-order traversal. The treeread.cpp program uses free functions (not in a class) and reads from cin/standard input. For example, here's a run on the data file tree.dat.

   prompt> treeread < tree.dat
   in order traversal
   
   dingo
   fox
   giraffe
   platypus
   racoon
   rhinoceros
   tasmanian devil
   tiger
   warthog
   
   
   pre order traversal
   
   platypus
   fox
   dingo
   giraffe
   tiger
   rhinoceros
   raccoon
   tasmanian devil
   warthog

Note that the format of the data file used above is similar (though not identical) to what you'll be writing for the animal guessing game program.

The Program You Write

You must write a program that prompts the user for the name of a file, reads that file into a tree, plays a game, and allows the user to add new information to the tree as the game is played. The user should be able to play more than once during a run of the program.

As shown in the example run above, the user is prompted for a filename in which the tree/game will be saved. The default filename is the one the user originally entered, but in the run above a different name is used. It's a good idea to use a different name for the file until you know your program works.

Code and Classes

You should write separate functions for the following:

You'll probably want to write more functions than these. The functions you write must be in a class AnimalGame. You may decide to use other classes, that's fine, but you must create at least one class and use it in the main function of the version of animal.cpp that you write. The declaration for the TreeNode class you use must be private to the AnimalGame class.

Private Tree Declaration

If you declare a struct Tree in the private section of a a class AnimalGame, e.g., class AnimalGame { public: // methods/constructors here private: struct Tree { string info; Tree * left; Tree * right; // more stuff (constructor) }; }; Then the name Tree can be used within a member function, of the AnimalGame class, but not as the return-type of a member function, because return types are outside the scope of a class. This means you have to use the scope resolution operator on a return type: AnimalGame::Tree.

So, a private function build could appear in the header file as follows.

// ... private: struct Tree { // stuff here }; Tree * build(istream & input); }; Here, Tree is ok, because it's inside the class declaration (literally). But in the .cpp file you MUST write: AnimalGame::Tree * AnimalGame::build(istream & input) { // stuff here }

Note that the function name is qualified using AnimalGame:: just as the struct name is qualified, though both appear in the header file without the qualifier.

If the Tree struct is private to AnimalGame, the public member functions cannot use Tree as a return type or as parameters of the public functions. Instead, the public functions will call private helper functions that do the work.

In general, classes in which trees are used will often have one private, helper function for each public function. The public function implementation calls the private function which does the work.

For example:

void AnimalGame::read(const string& filename) { ifstream input(filename.c_str()); myTree = doRead(input); } AnimalGame::Tree * AnimalGame::doRead(istream & input) { }

Input/Output from User

If you use getline or PromptlnString (or any other of the PromptlnlnXXX functions), then you must use only getline, you can't mix input using >>, extraction, with getline (and you can't mix PromptString with PromptlnString for the same reasons.)

When you use cin >> s the extraction leaves the newline character (entered when you press return) on the stream. When you call getline the character is read and you'll get an empty string as a result of the getline. See page 410 in Chapter 9 of Tapestry for a more complete explanation.

Summary: If you use getline, don't use >> input. You might want to use getline because it allows the user to enter complete sentences including spaces.

Code/Class Details

Your final executable should be named animal. Your final program should consist of at least animal.cpp, animalgame.h, and animalgame.cpp. The Makefile you're given has entries for being able to type make animal from animal.cpp and animalgame.cpp, but you should run make depend before compiling/creating animal since there are no files named animal.cpp and animalgame.cpp in the code you're given.

You may decide to write the code without using a class at first, or using a class but not creating separate .h and .cpp files. However, your final program needs to have separate .h and .cpp files.

Deleting Nodes

The tree nodes you create when the file is read should be deleted when the program finishes. Do not try to delete any nodes until you know your program works.

What to Submit

See snarfing/copying instructions.

This assignment is worth 25 points, the breakdown is as follows:

functionality points
read file into tree 4
play game/add info to tree 5
save file properly 4
coding style/classes 5
data file created 2
README 3
deleting nodes 2

You must also submit a README file in which you list all the people with whom you collaborated, and the TAs/UTAs you consulted with. You should include an estimated of how long you spent on the program and what your thoughts are about the assignment.

You must create a sample data file whose name indicates something about its contents. The questions should be yes/no questions about any topic, e.g., animals, elements from the periodic table, courses at Duke, and so on.

To submit use Eclipse or enter the following on acpub:

  submit_cps100 animal *.h *.cpp Makefile README foo.dat

Do not submit .o or .exe files.

Where the foo.dat file is the file of yes/no questions you created for this assignment. Failure to submit a working Makefile will cause you to lose 5 points.


Jeff Forbes
Last modified: Wed Mar 17 16:42:09 EST 2004