2013-08-20 2 views
0

Я преподаю свое С ++ на стороне, и я понимаю, что этот вопрос может показаться полезным для некоторых. В игре, которую я делаю как часть процесса обучения, я хочу, чтобы пользователь мог выбрать трудность, и когда они выбирают тот или иной диапазон значений случайных чисел. Компилятор, который я использую, кстати, это x-Code. Вот код:Redefiniton of int error

#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; 

} 

В 2 ошибки возникают в случае 2 и 3, где я пытаюсь переопределить значение secretNumber.

+2

Я не совсем уверен, что вопрос в том...? –

+0

Вы предполагали, что число меняется после каждой догадки, правильно или неправильно? Потому что это то, что он делает прямо сейчас.Оператор 'switch (choice)' должен находиться вне внутреннего цикла, если вы хотите один номер за игру, а не за догадку. – cHao

ответ

0

Похоже, что у вас есть фон на некоторых других языках - возможно, на функциональном языке и, возможно, на JavaScript.

Одной из ключевых особенностей C++ является область охвата. Переменные (владельцы названных значений) имеют срок действия области, в которой они находятся, и переменные видны только в пределах области, которую они определены. (Не путать с объектами, которые с помощью указателей и выделения могут быть дразнированы со стека и в память кучи, только для того, чтобы их потеряли, когда переменные с их адресом выходят за пределы области действия, если они не были должным образом освобождены).

{ 
    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. 
} 

Кроме того, если они не были представлены как «const», переменные C++ являются изменяемыми - их можно изменить.

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

Итак: ваш код не является «переопределение» secretNumber, это shadowing предыдущее определение, скрывая его на протяжении текущей области. Таким образом, когда вы присваиваете значение внутренней версии, «secretNumber», видимый для кода вне области, не затрагивается.

#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; 
} 

То, что вы на самом деле хотите сделать, это просто присвоить новое значение исходной secretNumber переменной, объявленной в внешней области, так как это единственная переменная с именем «secretNumber» доступными для кода в этой области.

#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; 

} 

Это одна из причин, почему многие C++ программисты предпочитают использовать префикс и суффикс обозначения различать некоторые типы переменных:

#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

2

Блоки case не открывают разные области, а являются частью одного и того же блока. Ваш код (с учетом только областей) выглядит как-то подобное:

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

три разные переменные с тем же именем объявляются в том же объеме, что не допускается в языке. Обратите внимание, что все три объявления внутри switch также будут скрывать переменную, объявленную во внешней области видимости, что, вероятно, не так, как вы хотите.

+0

Я думал, что вы не можете объявлять переменные в инструкции switch, но я, очевидно, не полностью понял ограничения оператора switch? Пожалуйста, объясни. увидел это сейчас http://stackoverflow.com/questions/1231198/declaring-variables-inside-a-switch-statement, но это было объективно c. – user2672165

+0

@ user2672165: Это сложно; вы можете иметь переменные непосредственно в коммутаторе, потому что коммутатор - это всего лишь блок со специальными метками и встроенный 'if' /' goto'. Но так же, как с gotos, вам не разрешается переходить определение переменной в свою область действия - что фактически делает переменные незаконными за пределами последнего случая. (Эта странность почти не исчезает, когда вы используете фигурные скобки для каждого случая, который определяет переменную, которая создает новую область для переменной; прыгает мимо случая, а затем перескакивает мимо всей области, поэтому вы хорошо.) – cHao

+0

Да, вы могут определять переменные уровня блока, но в этом случае вам это не нужно. На уровне оператора switch вы можете объявить переменную только один раз. – Tarik

0

Вы получаете ошибку времени компиляции, потому что вы обновляете одну и ту же переменную в той же области (область измерения уровня блока case). Вам нужно удалить int перед secretNumber во всех случаях. В противном случае переменная secretNumber, объявленная на уровне блока while, останется неопределенной.