APCS Twenty Questions

Introduction

The game of Twenty Questions can be 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. For example, a brief run of a simple version of the program is shown below. Note that new questions are added during the run reflecting new "knowledge" in the program.

prompt> guess
file: animal.dat
Does it have feathers [yes/no] yes
Does it live in a barnyard [yes/no] yes
Is it a chicken [yes/no] yes
I win!!!

play again? [y/n] y
Does it have feathers [yes/no] n
Is it a mammal [yes/no] y
does it have stripes [yes/no] no
Is it a elephant [yes/no] no
I give up: what were you thinking of? kangaroo

please type a question that has a yes answer
for a kangaroo and a no answer for a elephant

does it hop

play again? [y/n] y
Does it have feathers [yes/no] no
Is it a mammal [yes/no] yes
does it have stripes [yes/no] no
does it hop [yes/no] yes
Is it a kangaroo [yes/no] yes
I win!!!

play again? [y/n] n

Input/Output

The input to the program will be any file in the schema below:

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

Files begin with an optional comment string, preceded by a question mark. Questions are identified by the string #Q: at the beginning of a line, answers do not have #Q:. For the simulated game shown above the data file might look like this:

   ? animals of all types
   #Q:Does it have feathers
   #Q:Does it live in a barnyard
   chicken
   #Q:is it wise
   owl
   #Q:does it say "Nevermore!"
   raven
   #Q:does it gobble
   turkey
   eagle
   #Q:Is it a mammal
   #Q:does it have stripes
   tiger
   #Q:does it hop
   kangaroo
   elephant
   gila monster
Code in the GameTree::DoBuild function is provided for you. This code reads a stream and constructs and returns a tree.

The Program

Several files are provided as a start (if you use this as the basis for an assignment, you can leave some of these out, or leave out implementations of more member functions than are left out here). You must implement two member functions and write a new GameFactory class.

You must also implement a new kind of GameFactory class, one that derives or inherits from GameFactory. In this new class, instead of prompting the user for the name of a file, prompt for the name of a directory which (presumably) will contain many .dat files that represent different kinds of games. All the files ending in .dat that are found in the specified directory should be displayed for the user, along with the one line comment (if it exists) at the beginning of each file. The user should then be allowed to select one of the filenames (e.g., by typing in a number) and the new GameFactory subclass will create a game from this file. For example, the user might be prompted as follows:

    enter name of directory:  data 

    1.  animal.dat -- all types of animals
    2.  guts.dat -- easy courses at Duke
    3.  elements.dat -- yes/no question from the periodic table

    which quiz [1--3]:  2 

Use the provided program dirreader.cpp to see how to read all the entries in a directory. You might also want to check the header file directry.h (which, unfortunately, is provided only for Borland compilers, not currently for CodeWarrior as we go to press).

You must do all user input from cin using getline and not with >> or you may run into trouble because other user input (like what question to ask) will be processed using getline. If you mix >> with getline without being attentive you'll miss newlines that will make it seem like the program is ignoring your input.

To create a new GameFactory class you should make a new .h and new .cc file. Here's a start on the .h file

#ifndef _DIRGAMEFACTORY_H
#define _DIRGAMEFACTORY_H

#include "gamefactory.h"

class DirGameFactory : public GameFactory
{
   public:

       DirGameFactory();
       virtual Game * MakeGame();
};

#endif
You can then substitute new DirGameFactory for new GameFactory in playgame.cc without changing any other source code.

    GameFactory * factory = new DirGameFactory;    // create a factory 

You'll need to modify the Makefile by replacing all occurrences of gamefactory with dirgamefactory (if you implement the class in a file named dirgamefactory.cc).


Owen L. Astrachan
Last modified: Thu Jun 5 23:56:59 EDT