Question

I'm teaching my self C++ on the side and i realize this question may seem remedial to some. In the game I'm making as part of the learning process I want the user to be able to pick a difficulty and when they pick one or the other the random number value range changes. The compiler I'm using is x-Code by the way. Here is the code:

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

using namespace std;

int secretNumber;

int main() //integrate difficulty chooser where easy is a number b/w 1 and 10, norm 1 and 50, and hard is 1 and 100
{
    srand(static_cast<unsigned int>(time(0))); //seeds random number by time read on system

    int guess;
    int choice;

    char again = 'y';

    cout << "\tWelcome to Guess My Number\n\n";
    cout << "Please choose a difficulty:\n";
    cout << "1 - Easy\n";
    cout << "2 - Normal\n";
    cout << "3 - Hard\n";
    cin >> choice;

    while (again =='y')
    {
        int tries = 0;
        int secretNumber;
        do
        {                
            cout << "Enter a guess: ";
            cin >> guess;
            ++tries;

            switch (choice)
            {
                case 1:
                    cout << "You picked Easy.\n";
                    int secretNumber = rand() % 10 + 1;
                    break;            
                case 2:
                    cout << "You picked Normal.\n";
                    int secretNumber = rand() % 50 + 1;
                    break;
                case 3:
                    cout << "You picked Hard.\n";
                    int secretNumber = rand() % 100 + 1;
                    break;                    
                default:
                    cout << "You have made an illegal choice.\n";
            }

            if (guess > secretNumber)
            {
                cout << "\nToo high!";
            }
            else if (guess < secretNumber)
            {
                cout << "\nToo low!";
            }
            else if (guess == secretNumber && tries == 1)
            {
                cout << "\nThat's unbelievable! You guessed it in exactly 1 guess";
            }
            else
            {
                cout << "\nGreat job, you got it in just " << tries << " guesses!\n";
            }

        }
        while(guess != secretNumber);

        cout << "Do you want to play again y/n: ";
        cin >> again;
    }

    return 0;

}

The 2 errors occur in case 2 and 3 where i try to redefine the value of secretNumber.

Était-ce utile?

La solution 2

It looks like you have some background in some other languages - perhaps a functional language and perhaps some JavaScript.

One of the key features of C++ is scoping. Variables (named value holders) have a lifetime of the scope they are within, and variables are only visible within the scope they are defined. (Not to be confused with objects, which through pointers and allocation can be teased off the stack and into heap memory, only to be lost when the variables with their address go out of scope if they are not properly deallocated).

{
    int i = 1;
}
std::cout << "i is " << i << std::endl; // compiler error, i does not exist here.
void foo() {
    int i = 1;
}
void bar() {
    foo();
    std::cout << i << std::endl;  // compiler error, i does not exist here.
}

Also, unless decorated as "const", C++ variables are mutable - they can be changed.

int i = 1;
i = 2;
std::cout << i << std::endl; // writes 2, not 1. 

So: your code is not 'redefining' secretNumber, it is shadowing the previous definition, hiding it for the duration of the current scope. Thus when you assign a value to the inner version, the "secretNumber" visible to code outside the scope is untouched.

#include <iostream>

int main()
{
    int foo = 1; // outer foo
    std::cout << "Originally, foo = " << foo << std::endl;

    {
        int foo = 2; // inner foo
        std::cout << "Inside the inner scope, foo = " << foo << std::endl;
    }

    // inner foo doesn't exist here, so it references outer foo.
    std::cout << "But the original foo still exists, " << foo << std::endl;
}

What you actually want to do is simply assign a new value to the original secretNumber variable you declared in the outer scope, since that is the only variable named "secretNumber" available to code in that scope.

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

using namespace std;

int secretNumber;

int main() //integrate difficulty chooser where easy is a number b/w 1 and 10, norm 1 and 50, and hard is 1 and 100
{
    srand(static_cast<unsigned int>(time(0))); //seeds random number by time read on system

    int guess;
    int choice;

    char again = 'y';

    cout << "\tWelcome to Guess My Number\n\n";
    cout << "Please choose a difficulty:\n";
    cout << "1 - Easy\n";
    cout << "2 - Normal\n";
    cout << "3 - Hard\n";
    cin >> choice;

    while (again =='y')
    {
        int tries = 0;
        int secretNumber;
        do
        {                
            cout << "Enter a guess: ";
            cin >> guess;
            ++tries;

            switch (choice)
            {
                case 1:
                    cout << "You picked Easy.\n";
                    secretNumber = rand() % 10 + 1;
                    break;            
                case 2:
                    cout << "You picked Normal.\n";
                    secretNumber = rand() % 50 + 1;
                    break;
                case 3:
                    cout << "You picked Hard.\n";
                    secretNumber = rand() % 100 + 1;
                    break;                    
                default:
                    cout << "You have made an illegal choice.\n";
            }

            if (guess > secretNumber)
            {
                cout << "\nToo high!";
            }
            else if (guess < secretNumber)
            {
                cout << "\nToo low!";
            }
            else if (guess == secretNumber && tries == 1)
            {
                cout << "\nThat's unbelievable! You guessed it in exactly 1 guess";
            }
            else
            {
                cout << "\nGreat job, you got it in just " << tries << " guesses!\n";
            }

        }
        while(guess != secretNumber);

        cout << "Do you want to play again y/n: ";
        cin >> again;
    }

    return 0;

}

This is one reason why many C++ programmers choose to use prefix and suffix notations to distinguish certain types of variables:

#include <iostream>

class Foo {
public:
    int m_i;  // member variable, m_xxx
    Foo(int); // constructor taking an int.
};

static int s_i;

Foo::Foo(int i_)   // arguments use _ suffix
{
    int i = i_;    // local value of i
    i *= 3;
    m_i = i;       // we're assigning it the local value, not the argument.
}

int main()
{
    int i = 1;
    Foo foo(2);
    s_i = 3;

    std::cout << "i = "<<i<<", foo.m_i = "<<foo.m_i<<", s_i = "<<s_i<< std::endl;
}

Live Demo: http://ideone.com/dSTwPT

Autres conseils

The case blocks do not open different scopes, but are rather part of the same block. Your code (considering only scopes) looks somehow similar to:

int secretNumber;
{
int secretNumber = rand() %  10 + 1;
...
int secretNumber = rand() %  50 + 1;
...
int secretNumber = rand() % 100 + 1; 
}

Three different variables with the same name are being declared in the same scope, which is not allowed in the language. Note that all three declarations inside the switch would also hide the variable declared in the outer scope, which is probably not what you want anyway.

You are getting the compile time error because you are redeclaring the same variable within the same scope (case statement block level scope). You need to delete int before secretNumber in all the case statements. Doing otherwise, the secretNumber variable declared at the while loop block level will stay undefined.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top