'How can I finish this C++ Animal Guessing homework assignment [closed]

I need to add two things to my Animal Guessing Game and I'm not sure how to do them.

  1. saving your database tree and
  2. loading/reloading a database into your game.

For the first thing, our teacher told us that to save the tree, we will need 2 functions:

  1. Prepare an output file to print the tree to.
  2. Recursively traverse and print the tree using preorder traversal (node, left subtree, right subtree), printing each node as we come to it. We will start with the root node.

I plan to use the names :

  • void displayPreOrder (animalNode* curNode) – using cout, as shown in our text
  • void printPreOrder(animalNode* curNode) – using a file stream that we create

An example of the output file I am trying to do:

Q
does it have cubs for babies?
Q
does it perform in the circus?
G
Tiger
G
bear
Q
does it swim?
Q
did it swallow Jonah?
G
whale
G
fish
Q
does it eat cheese?
G
mouse
Q
does it purr?
G
cat
Q
is it afraid of mice?
G
elephant
Q
is it often nicknamed Billy?
G
goat
G
Lizard

This is the code I have so far (C++):

#include<iostream>
#include<string>
#include<stdlib.h>

using namespace std;

struct animalNode
{
    string question;
    string guess;
    animalNode* yesAnswer, * noAnswer;
};

class Game
{
    struct animalNode* root;

public:

    Game()
    {
        root = new animalNode();
        root->question = "";
        root->guess = "lizard";
        root->yesAnswer = NULL;
        root->noAnswer = NULL;
    }

    void operation()
    {
        int end1 = 0; //learning a new animal:end game
        int end2 = 0; //correctly guesses animal:end game

        while (end1 == 0 && end2 == 0)
        {
            cout << "\nHello user, just think of an animal and Press enter to continue...\n";
            cin.ignore();
            animalNode* temp = root;
            char answer;
            string name, q;
            while (1)
            {
                if (temp->question == "")
                {
                    cout << "\nWere you thinking about " << temp->guess;
                    cout << "\n(y or n)";
                    cin >> answer;

                    if (answer == 'y' || answer == 'Y') //makes the input case insensitive
                    {
                        end2 = 1;
                        break;
                    }
                    else
                    {
                        animalNode* newYesAnswer, * newNoAnswer;
                        newYesAnswer = new animalNode();
                        newNoAnswer = new animalNode();

                        newYesAnswer->yesAnswer = NULL;
                        newYesAnswer->noAnswer = NULL;

                        newNoAnswer->yesAnswer = NULL;
                        newNoAnswer->noAnswer = NULL;

                        cin.ignore();
                        cout << "\nWhat animal it was?";
                        getline(cin, name); //adds a new animal to the guesses
                        cout << "\nA question that can be used to differentiate that animal?\n";
                        getline(cin, q); //adds a correlating question for the new animal

                        temp->question = q;

                        cout << "\nWhat would be its answer to identify it as " << name;
                        cout << "\nenter y for Yes and n for No: "; //verifies that the question matches the animal
                        cin >> answer;
                        if (answer == 'y' || answer == 'Y')
                        {
                            //answer yes=guesses the new animal
                            newYesAnswer->guess = name;
                            newNoAnswer->guess = temp->guess;
                        }
                        else
                        {
                            //answer no==guesses the new animal
                            newNoAnswer->guess = name;
                            newYesAnswer->guess = temp->guess;
                        }

                        temp->yesAnswer = newYesAnswer;
                        temp->noAnswer = newNoAnswer;
                        end1 = 1;
                        break;
                    }
                }
                else
                {
                    cout << "\n" << temp->question;
                    cout << "\nEnter y for Yes and n for No: ";
                    cin >> answer;
                    if (answer == 'y' || answer == 'Y')
                        temp = temp->yesAnswer;
                    else
                        temp = temp->noAnswer;
                }

            }

            if (end1 == 1) //prompt to play again if new animal was learned
            {
                cout << "\nDo you want to play again.. (y/n)";
                cin >> answer;
                if (answer == 'y' || answer == 'Y')
                    end1 = 0;
            }

            if (end2 == 1) //prompt to play again if animal was guessed
            {
                cout << "\nThe program guessed it right...\n";
                cout << "\nDo you want to play again.. (y/n)";
                cin >> answer;
                if (answer == 'y' || answer == 'Y')
                    end2 = 0;
            }
        }
    }
};

int main() //main function that runs the game
{
    Game g;

    g.operation();
    return 0;
}


Solution 1:[1]

Some general remarks first:

stdlib.h is a C, not C++ header. Include cstdlib instead. However you do not even use that library, so do not include it at all.

Next, read Why is using namespace std considered bad practice

If you deem it necessary, you can use using std::cout; etc. instead.

Instead of using raw pointers, smart pointers should be used. I see that this task requires raw pointers, but it's something worth discussing with your teacher.

Because you don't use smart pointers, you need a destructor to free (delete) the memory you required with new.

Instead of NULL use nullptr.

If you use a constructor, you can save a lot of written code

void operation is a bad function name, because it gives no description what the function is supposed to be doing.

To do the output to a file, you can use filestreams.

I have adapted some of my changes and provided a crude implementation of the output, you may change however you feel it's convenient. Also, if there are any question about the changes, feel free to ask.

#include <fstream>
#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::string;

struct animalNode
{
    string question;
    string guess;
    animalNode* yesAnswer, * noAnswer;
    animalNode(string q = "", string g = "", animalNode* y = nullptr, animalNode* n = nullptr)
    : question(q)
    , guess(g)
    , yesAnswer(y)
    , noAnswer(n)
    {
    }
    ~animalNode(){
        delete yesAnswer;
        delete noAnswer;
    }
};

class Game
{
    struct animalNode* root;

public:

    Game()
    {
        root = new animalNode("", "lizard");
    }

    ~Game(){
        delete root;
    }

    void recursive_print(std::ofstream& out, animalNode* node){
        if( node == nullptr ){
            return;
        }
        out << node->question;
        out << node->guess;
        out << "\n";
        recursive_print(out, node->yesAnswer);
        recursive_print(out, node->noAnswer);
    }

    void save_to_file(string file_name)
    {
        std::ofstream out(file_name);
        if( out ){
            recursive_print(out, root);
        }
    }

    void play()
    {
        int end1 = 0; //learning a new animal:end game
        int end2 = 0; //correctly guesses animal:end game

        while (end1 == 0 && end2 == 0)
        {
            cout << "\nHello user, just think of an animal and Press enter to continue...\n";
            cin.ignore();
            animalNode* temp = root;
            char answer;
            string name, q;
            while (true)
            {
                if (temp->question == "")
                {
                    cout << "\nWere you thinking about " << temp->guess;
                    cout << "\n(y or n)";
                    cin >> answer;

                    if (answer == 'y' || answer == 'Y') //makes the input case insensitive
                    {
                        end2 = 1;
                        break;
                    }
                    else
                    {
                        animalNode* newYesAnswer, * newNoAnswer;
                        newYesAnswer = new animalNode();
                        newNoAnswer = new animalNode();

                        cin.ignore();
                        cout << "\nWhat animal it was?";
                        getline(cin, name); //adds a new animal to the guesses
                        cout << "\nA question that can be used to differentiate that animal?\n";
                        getline(cin, q); //adds a correlating question for the new animal

                        temp->question = q;

                        cout << "\nWhat would be its answer to identify it as " << name;
                        cout << "\nenter y for Yes and n for No: "; //verifies that the question matches the animal
                        cin >> answer;
                        if (answer == 'y' || answer == 'Y')
                        {
                            //answer yes=guesses the new animal
                            newYesAnswer->guess = name;
                            newNoAnswer->guess = temp->guess;
                        }
                        else
                        {
                            //answer no==guesses the new animal
                            newNoAnswer->guess = name;
                            newYesAnswer->guess = temp->guess;
                        }

                        temp->yesAnswer = newYesAnswer;
                        temp->noAnswer = newNoAnswer;
                        end1 = 1;
                        break;
                    }
                }
                else
                {
                    cout << "\n" << temp->question;
                    cout << "\nEnter y for Yes and n for No: ";
                    cin >> answer;
                    if (answer == 'y' || answer == 'Y')
                        temp = temp->yesAnswer;
                    else
                        temp = temp->noAnswer;
                }

            }

            if (end1 == 1) //prompt to play again if new animal was learned
            {
                cout << "\nDo you want to play again.. (y/n)";
                cin >> answer;
                if (answer == 'y' || answer == 'Y')
                    end1 = 0;
            }

            if (end2 == 1) //prompt to play again if animal was guessed
            {
                cout << "\nThe program guessed it right...\n";
                cout << "\nDo you want to play again.. (y/n)";
                cin >> answer;
                if (answer == 'y' || answer == 'Y')
                    end2 = 0;
            }
        }
    }
};

int main() //main function that runs the game
{
    Game g;

    g.play();
    g.save_to_file("filename.txt");
    return 0;
}

I think it would be helpful to add indentation or another way of marking the nested level of questions. You can add a counter to the recursive function to keep track of that.

For the loading part, use an std::ifstream.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 infinitezero