Переопределение внутренней ошибки

Я учу себя C ++ на стороне, и я понимаю, что этот вопрос может показаться исправительным для некоторых. В игре, которую я делаю как часть процесса обучения, я хочу, чтобы пользователь мог выбрать сложность, а когда он выбирает одно или другое, изменяется диапазон значений случайных чисел. Кстати, компилятор, которым я пользуюсь, это x-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;

}

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

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, это слежка предыдущее определение, скрывая его на время текущей области. Таким образом, когда вы присваиваете значение внутренней версии, «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;
}

Демонстрация в реальном времени: http://ideone.com/dSTwPT

0

Другие решения

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

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

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

2

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

0
По вопросам рекламы [email protected]