I started coding C++ this past week, and yesterday I challenged myself to write something original that my book doesn't have hints on. It is a program that prompts the user to think of a number between 1 and 100, and proceeds to guess the user's number. The user tells the program whether it's guess is too high or too low, and the computer uses that information to refine its guess until it has the right number. I have tried several different ideas on how to set the limits which the computer must guess within, but nothing seems to work. This is what I have right now. It compiles and runs just fine, but is a terrible guesser. If I say it's too high, it goes lower, but if I say it's too low, it gives me a seemingly random number. I have a feeling this is a simple mathematical error and I'm really over-thinking this, but any help would be appreciated. Also, please go easy on me if my code is super inefficient or convoluted, it's my fourth day :

Don't know why all the colors got screwed up

#include "stdafx.h"

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int setLimits(int, int, int);


int main()
{
    char guessCorrect;
    char playAgain;
    srand(static_cast<unsigned int>(time(0)));
    int tries = 0;
    int computerGuess;
    int highLimit = 100;
    int lowLimit = 1;
    cout<<"\n\t\t**Welcome, I am the psychic computer!**";
    cout<<"\n\nThink of a number between 1 and 100.";
    cout<<"\nReady? (y/n):";
    cin>>playAgain;
    do
    {
        if (playAgain == 'y')
        {
            computerGuess = (rand() % 100) + 1;
            do
            {
                ++tries;
                cout<<"\nAre you thinking of the number "<<computerGuess<<"? (y/n):";
                cin>>guessCorrect;
                if (guessCorrect == 'y')
                {
                    break;
                }
                else 
                {
                    computerGuess = setLimits(computerGuess, lowLimit, highLimit);

                }
            }while (guessCorrect != 'y');

            cout<<"\nI guessed your number in "<<tries<<" tries!";
            cout<<"\nPlay again? (y/n):";
            cin>>playAgain;
        }
        else
        {
            continue;
        }
    }while (playAgain == 'y');

    cout<<"\nGoodbye!";

    cin.clear();
    cin.ignore(255, '\n');
    cin.get();
    return 0;
}

int setLimits(int computerGuess, int lowLimit, int highLimit)
{
    char tooHigh;
    cout<<"\nDid I guess too high? (y/n)";
    cin>>tooHigh;
        if (tooHigh == 'y')
            {
                highLimit = computerGuess-1;
                computerGuess = ((rand() % (computerGuess-1))+1);
                if (computerGuess < lowLimit)
                {
                    computerGuess = (computerGuess + ((lowLimit - computerGuess)+1));
                }                               
            }
        else
            {
                lowLimit = highLimit-(highLimit-computerGuess);
                computerGuess = ((rand() % (highLimit-lowLimit))+lowLimit);
                if (computerGuess > highLimit)
                {
                    computerGuess = (computerGuess - ((highLimit - computerGuess)-1));
                }
            }
    return computerGuess;
}

This is a classic example of binary searching. The appropriate solution for your computer is to guess at half the range every time. So the guess is always half way between the previous guess and the end of the range. When the guess is lower, set the bottom of the range to one plus the guess, and when the guess is higher, set the top of the range to the guess.

What I would do in this case is print out values the program calculates at key places and see what the variables contain. For example
After line 29 output computerguess
After line 41, 76, 85 output computerGuess, lowLimit, highLimit
An example, after 76:
cout << "In setLimits (high)" << computerGuess << lowLimit << highLimit << endl;

Also, you can delete lines 35 thru 43 by moving 41 after line 31. In place of line 29, set lowLimit, highLimit to appropriate values.

I did what you suggested. The setLimits function does its job perfectly, but when the limits seem to get reset to 1 and 100 after they get sent back to int main(). Is this because I'm declaring and setting the initial values of highLimit and lowLimit in the wrong place?

when the limits seem to get reset to 1 and 100 after they get sent back to int main()

That's because you're working with a copy of the variables from main(), not the original objects. Try passing references instead:

int setLimits(int computerGuess, int& lowLimit, int& highLimit)

That works perfectly! Thank's so much. Could you explain to me what exactly I did by adding that? I really want to know how this works.

All function parameters are passed by value in C++ (the argument could be made that references are passed by value too), which means a copy of the value is made and put into a new local variable (the function parameter) for use inside the function body. By passing a reference, you're essentially aliasing the original object and thus any changes made to the parameter will be reflected in the object that you passed as an argument.

Pass by value.
Pass by reference.

Edited 4 Years Ago by deceptikon

Now I feel like a dumbass. My friend did the same program in less than half as many lines. Granted, his is really predictable and kind of lame because it has the same pattern for guessing every time instead of using random numbers, but it's way more efficient.

#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int main()
{
    cout << "**Welcome, I am the ultimate Psychic Computer**\n" 
    << "Think of a number between 1 and 100 and I will guess it.\n" 
    << endl << "Ready?(y/n): ";

    char response1 = '0';
    char response2 = '0';
    int pow = 2;
    int tries = 1;

    srand(static_cast<unsigned int>(time(0)));
    int CG = (rand() % 2) + 50;

    while (response1 != 'y')
    {
        cout << endl << CG << "?";
        cin >> response1;
        if (response1 == 'n')
        {
            cout << "Just kidding! But is that number too high? ";
            cin >> response2;
            if (response2 == 'n')
                CG = CG + max(1,50/pow);
            else 
                CG = CG - max(1,50/pow);
        pow = 2*pow;
        ++tries;
        }
    }

    cout << "I KNEW IT! Only " << tries
        << " mistake(s) made!\n";
    system("PAUSE");
    return 0;
}

My friend did the same program in less than half as many lines.

The number of lines aren't indicative of the quality of a program. I'm not saying there's anything wrong with your friend's program, but just because it's shorter doesn't mean it's better.

Better or not, it is more efficient and usually guesses in less tries than mine. I think mine is more fun though, because the computer never guesses the same way.

Shorter's not always better.

I keep telling that to my husband, but he says I don't know what I'm talking about.

Comments
Ouch!
This article has been dead for over six months. Start a new discussion instead.