Пятница, 17.11.2017, 23:22
Приветствую Вас Гость | RSS

Кузница миров

Меню сайта
Категории раздела
Мои статьи [2]
Курс : "Основы С++ для начинающих программистов игр." [25]
WindMill Engine [3]
XNA4 RPG [0]
Перевод туториалов но созданию RPG на C# c XNA4.
C# & Leadwerks [5]
Программирование Leadwerks Engine на языке С# с помощью врапера Le.NET.

Каталог статей и уроков

Главная » Статьи » Курс : "Основы С++ для начинающих программистов игр."

3.3. Игра «Угадай число»
3. Игра «Угадай число»


Возможно после предыдущего урока, после Лабиринта, эта игра покажется вам слишком простой, ведь она в десять раз меньше по объему кода. Но если бы мы на прошлом уроке знали то, что знаем сейчас, то и Лабиринт был бы раза в три меньше. После этой игры можете попробовать его переписать с использованием циклов.

Итак, как обычно начинаем с планирования:

Что же именно мы будем делать.
Сделаем мы простенькую игру. Программа генерирует случайное число, а игроку предстоит его отгадать. Сюжет я предлагаю вам придумать самостоятельно. Если у вас с этим туго, что ж, в данной игре можно обойтись и без сюжета.

Как это будет реализовано.
Реализовано это будет в виде диалога. Программа спрашивает, какое число она сгенерировала. Игрок пытается отгадать и вводит свое предположение. Игра проверяет введенные данные и выводит результат, сообщая больше введенное от сгенерированного, меньше или равно.

Что для этого понадобится.
Предполагается, что попыток отгадывания будет несколько, поэтому нам необходимо знать, как использовать циклы. С этим мы уже познакомились выше.
Единственное, что нам пока неизвестно – как сделать так, чтобы программа создавала некое случайное число. Об этом я сейчас и расскажу.

Генератор псевдослучайных чисел.


Для генерации случайных чисел в С++ предусмотрена специальная функция – rand(). Что такое функция, мы поговорим на следующем уроке. А сейчас вы просто следуйте предложенным примерам.
Для того, чтобы использовать ее в своих программах необходимо подключить к исходному коду заголовочный файл stdlib.h. Как это делается я надеюсь, вы помните:

Code


#include <stdlib.h>


Ну и небольшой пример :

Code

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

using namespace std;

void main()
{
      for(int i=0;i<10;i++)  // цикл
      {
       int r = rand();   // генерация случайного числа      
       cout<<r<<"\n";        
      }

      cin.get();
}


Здесь в строке

Code

int r = rand();   // генерация случайного числа      



происходит генерация случайного числа с помощью функции rand() и его присвоение переменной r, а затем эта переменная выводится на экран. Поскольку все это происходит в цикле, то этот код выполняется несколько, в данном случае 10, раз.

Запустим эту программу, и она выдаст нам столбик из десяти чисел. Затем запустим эту программу повторно. Как это не прискорбно, но в обоих случаях эти столбики будут идентичны.
Все дело в том, что сгенерировать абсолютно случайное число компьютер не может. Функция всего лишь берет некое начальное значение(по умолчанию это единица), производит над ним определенные арифметические действия и выводит нам результат. Затем, при повторной генерации предыдущий результат используется как начальное значение.
Поскольку арифметические действия всегда одинаковые, то и последовательность чисел всегда идентична. Именно поэтому функцию называют генератором псевдослучайных чисел.
Думаю понятно, что для того, чтобы сделать эти числа более случайными, необходимо как то изменить начальное значение, используемое в генерации.
Для этих целей используется функция инициализации генератора

Code

srand(начальное значение)



которая это начальное значение и устанавливает.
Все что остается, это сделать это значение случайным.
Замкнутый круг, но выход есть. В качестве начального используют значение системного времени. При запуске программы время каждый раз будет разное, соответственно и результат работы генератора будет неповторим.
Теперь нам осталось узнать, как получить это системное время.
Для этого нам понадобится еще одна функция – time(0), которая выдает время в секундах, ведя отсчет от 1 января 1970 года по текущий момент. Естественно, что это число никогда не повторится. Для использования этой функции необходимо подключить еще один заголовочный файл time.h.

Вот код примера:

Code

#include <iostream>
#include <stdlib.h>
#include <time.h>  // подключение заголовочного файла

using namespace std;

void main()
{
      srand(time(0));   // инициализация генератора
      for(int i=0;i<10;i++)  // цикл
      {
       int r = rand();  // генерация случайного числа      
       cout<<r<<"\n";        
      }

      cin.get();
}


Здесь мы видим подключение нового файла, и инициализацию генератора псевдослучайных чисел перед циклом. Казалось бы, правильнее поместить эту инициализацию внутри цикла, тогда каждое число будет еще более случайным. Но это не так. Дело в том, что компьютеры в наше время обладают чудовищной производительностью. Весь цикл займет всего лишь мгновение, соответственно и функция тайм все десять раз передаст в качестве начального значения одно и то же время. В результате все сгенерированные числа будут одинаковыми. Вы можете проверить это, поместив инициализацию внутри цикла.
Теперь нам нужно узнать какие же именно числа способен выдавать rand, то есть узнать диапазон возможных значений. Я и так знаю ответ, но думаю, что интереснее получить эти данные практически, получив в процессе крупицу опыта.

Следующая программа это и делает, а как – видно из комментариев:

Code

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

using namespace std;

void main()
{
      srand(time(0));  // инициализация генератора
      int max, min, r;  // переменные для максимального, минимального и случайного
      max=min=rand();  // присвоение случайного значение переменным

      for(int i=0;i<1000000;i++)    // цикл
      {
       r=rand();  // присвоение переменной r случайного значения

       if(r>max)  // если r больше имеющегося максимума
        max=r;    // то оно становится максимумом

       if(r<min)  // если r меньше минимума
        min=r;    // то оно становится минимумом
      }
      // вывод результата
      cout<<"min= "<<min;
      cout<<"\nmax= "<<max;

      cin.get();

}


Запустив эту программу мы узнаем, что минимальное значение равно 0, а максимальное 32767.
Это очень большой разброс значений, тогда как часто необходимо получить число в заранее определенном, и возможно весьма узком диапазоне.
В языке программирования С++ есть один интересный арифметический оператор - %. Этот знакомый значок процента называется деление по модулю или по другому взятие остатка. Из второго названия ясно, что он делает. Допустим, есть такое выражение

Code

20%6



результат равен 2. Это остаток от целочисленного деления. То есть 20 = (3*6)+2. Здесь тройка ближайший делитель, а оставшаяся двойка и есть результат.

Но чтобы стало еще понятнее, я продемонстрирую, как он работает. Не что он делает, а именно как он функционирует. Если не использовать деления по модулю, то выражение приняло бы такой вид:

Code

      int x=20,y=6,i,res;
      i = 20/6;
      res = 20-( i * 6 );



Здесь сначала происходит обычное деление 20 на 6. Результат равен 3,3 (3 целых 3 десятых). Поскольку i у нас целочисленная переменная, запомните, что числа вроде 3,3 в ней хранится не смогут, и в результате преобразования типов дробная часть пропадает. Остается только целая часть 3.
Теперь мы множим эту тройку на шесть и то, что получилось, отнимаем от двадцати.
Результат это и будет то, что называют остатком от деления, и это как раз то, что получается при делении по модулю.
Теперь мы знаем, как этот оператор работает, что же нам это дает. А то, что при делении по модулю результат всегда будет меньше делителя как минимум на единицу.
Поэтому поделив таким способом любое случайное число, например, на десять, мы в результате получим число от 0 до 9.
То есть:

Code

х = rand() % 10;



не зависимо от того что здесь выдаст rand(), х будет присвоено значение от 0 до 9.

Так, думаю, немного разобрались. Но что делать, если нам необходимо число не от 0 и до, а например от 50 и до 80.

Вот как это вычислить:

Code

      int min = 50;     // начало диапазона
      int max = 80;     // конец диапазона
      int res = min + (rand()%(max-min));



Сначала вычисляется разность между максимумом и минимумом, что равно 30.
Затем в части выражения rand()%(max-min) получаем случайное число в диапазоне от 0 до 30, и прибавляем его к 50 (минимуму в данном случае), получив таким образом число в необходимом диапазоне.
Надеюсь вам все понятно, ибо на этом с генерацией случайных чисел мы закончили и переходим непосредственно к написанию кода игры.

«Угадай число»

Теперь зная все что необходимо, написание программы не составит никакого труда.
Вот ее исходный код:

Code

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

using namespace std;

void main()
{
      setlocale(LC_ALL,"Rus");
      int r,    // случайное число
       i=-1,   // вводимое значение
       c=0;   // счетчик колличества попыток

      srand(time(0));  // инициализация генератора
      r=rand()%100;   // генерация случайного числа от 0 до 100

      cout<<"Программа задумала число от 0 до 100.\nПопробуй угадать!!!\n";
           
      while(r!=i)   // цикл
      {
       // ввод числа
       cout<<"Введите число\n";
       cin>>i;

       // проверка и вывод подсказки
       if(i>r)
        cout<<"Многовато будить\n";
       if(i<r)
        cout<<"Однако, маловато\n";

       c++;    // наращивание счетчика попыток
      }

      // отображение результата
      if(c < 10)
       cout << "Молодец, угадал с "<< c <<" попытки";
      if(c > 10)
       cout << "Ну с "<< c <<" попытки любой угадает";

      cin.get();
      cin.get();
}



Думаю, вдаваться в детали не нужно, лишь расскажу вкратце, как он работает.
Вначале объявлены три переменные для хранения случайного числа, введенного значения и счетчика, которым тут же и присвоено начальное значения. Для счетчика это начало отсчета – 0, а вот для вводимого это отрицательное значение, чтобы выражение в условии цикла r!=i было истинным. Ведь сгенерированное число всегда положительное.
Далее происходит инициализация генератора и генерация случайного числа. Это случайное число сравнивается в цикле с вводимым значением, и до тех пор, пока они не равны, программа выдает подсказку больше или меньше сгенерированное число от введенного. Каждый цикл происходит наращивание счетчика попыток.
Как только пользователь вводит верное значение, цикл завершается и выводится результат, с указанием количества попыток. Все.
Категория: Курс : "Основы С++ для начинающих программистов игр." | Добавил: nilrem (24.10.2011)
Просмотров: 4808 | Комментарии: 1 | Рейтинг: 0.0/0
Всего комментариев: 1
1  
Вот где работа.
http://www.rublik.com/5032232003f2449f0d0003c3

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0