Разработка приложения, представляющего собой компьютерную игру «Змейка»

Автор: Пользователь скрыл имя, 01 Августа 2011 в 18:43, курсовая работа

Краткое описание

Введение в объектно-ориентированное программирование.
Объектно-ориентированное программирование представляет собой чуть более автоматизированный способ программирования. Объектно-ориентированные программы – это не просто процедурные программы, переведенные на новый синтаксис.

Оглавление

1. Введение

2. Постановка задачи

3.Опиание алгоритма решения в псевдокоде(команды в виде текста на русском языке

4.Исходный текст программы на С

5.Тестирование программы

6.Заключение

7.Список литературы

Файлы: 1 файл

курсовая работа.doc

— 389.00 Кб (Скачать)

 

    • СОДЕРЖАНИЕ
     

    1. Введение

    2. Постановка  задачи 

    3.Опиание алгоритма  решения в псевдокоде(команды  в виде текста на русском  языке

    4.Исходный текст  программы на С

    5.Тестирование  программы

    6.Заключение

    7.Список литературы

    1.Введение. 

         Введение  в объектно-ориентированное программирование. 
    Объектно-ориентированное программирование представляет собой чуть более автоматизированный способ программирования. Объектно-ориентированные программы – это не просто процедурные программы, переведенные на новый синтаксис. Они должны строится на новой философии разработки. Для них требуется новая стратегия программирования, которую часто бывает трудно освоить

         Основная  идея ООП: программа состоит из группы объектов, часто связанных между  собой. В С++ объекты описываются  при помощи нового типа данных class. Класс включает в себя набор переменных (данных) и операций (методов или функций-членов), которые действуют на эти переменные. Полученными объектами можно управлять при помощи сообщений. В ООП объекты включают в себя не только данные (данные-члены), но и методы (функции-члены) воздействия на эти данные. Эти две части в сочетании образуют функциональную единицу программы. Другими словами, объекты содержат данные и методы работы с этими данными. Ниже приведены три основных преимущества объектно-ориентированных программ по сравнению с эквивалентными программами, разработанными сверху вниз.

           Сопровождение программы. Программы  проще читать и понимать, ООП  позволяет управлять сложностью  программы, оставляя видимыми  программисту только существенные детали.

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

         Основные  термины и положения ООП. Инкапсуляция данных. Этот термин включает в себя логическое связывание данных с конкретной операцией. Она так же означает, что  они являются не -глобальными доступными всей программе, а локальными – доступными только малой ее части. Инкапсуляция также автоматически подразумевает защиту данных. Именно для этого предназначена структура class в С++. В классе управление функциональными деталями объекта осуществляется при помощи спецификаторов private, public, protected.

         Иерархия  классов. В общем случае можно  представить себе иерархию классов  как родословную в генеалогическом  древе, где класс С++ представляет собой шаблон для создания классов-потомков. Объекты, полученные из описания класса, называют экземплярами этого класса. Можно создать иерархию классов с классом-родителем и несколькими классами-потомками. Основой для этого являются производные классы.

         Наследование.

         Наследование  в ООП позволяет классу получать свойства другого класса объектов. Родительский класс служит шаблоном для производного класса; этот шаблон можно менять различными способами. Наследование является важным положением, поскольку оно позволяет повторно использовать определение класса без значительных изменений в коде.

         Полиморфизм. Строится на описанной выше концепции наследования. Программа посылает одно и тоже сообщение как объекту родительского класса, так и всем объектам производных классов. И родительский класс, и классы-потомки ответят на сообщение соответствующим образом. Полиморфизм дает возможность дополнять уже существующие части программы.

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

         2.Постановка  задачи. 

         ООП полностью принадлежит к миру С++, поскольку в С нет основного  ядра– абстрактного типа данных class . Поэтому переписать процедурно-ориентированную  программу как объектно-ориентированную  гораздо сложнее, чем просто подставить вместо одного ключевого слова другое.

         ООП представляет собой технику программирования, которая позволяет рассматривать  основные идеи как множество объектов. Используя объекты, можно представить  задачи, которые необходимо выполнить, их взаимодействие и любые заданные условия, которые должны быть соблюдены. Структура данных часто образует основы объектов; таким образом в С или С++ тип struct может образовывать элементарный объект. Связь с объектом можно организовать при помощи сообщений. Использование сообщений похоже на вызов функций в процедурно-ориентированной программе. Когда объект получает сообщение, вступают в действие методы, содержащиеся в объекте. Методы (их иногда называют функциями - членами) аналогичны функциям процедурно-ориентированного программирования. Тем не менее метод является частью объекта, а не чем-то отдельным, как было бы в процедурном аналоге.

         С++ -язык предметно-ориентированного программирования. Язык С++ поддерживает процедурную и  объектно-ориентированную парадигмы  программирования.

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

         Наиболее  важное понятие языков объектно-ориентированного программирования –это понятие объекта (object). Объект – это логическая единица, которая содержит данные и правила (методы) обработки этих данных. В  языке С++ в качестве таких правил обработки выступают функции, т. е. объект в Borland C++ объединяет в себе данные и функции, обрабатывающие эти данные. Одним из самых главных понятий языка С++ является понятие класса. В языке С++ для того, чтобы определить объект, надо сначала определить его форму с помощью ключевого слова Ближайшей аналогией класса является структура. Память выделяется объекту только тогда, когда класс используется для его создания. Любой объект языка С++ имеет одинаковые атрибуты и функциональность с другими объектами того же класса. За создание своих классов и поведение объектов этих классов полную ответственность несет сам программист. Работая в некоторой среде, программист получает доступ к обширным библиотекам стандартных классов. Обычно, объект находится в некотором уникальном состоянии, определяемом текущими значениями его атрибутов. Функциональность объектного класса определяется возможными операциями над экземпляром этого класса.

         Структуры.

         Структура-группа данных различных типов и(или) назначения, которые представляют собой единый информационный элемент.

         struct Zmeja // структура змейка 

         {

               COORD *t; //точки

               int PCount; //количество  квадратиков

         };

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

         Поскольку в объектах также можно хранить  группы разнотипных данных, то они  тоже содержат структуры. Отличие структуры  от класса в том, что в структуре нет закрытых и защищенных членов. Все члены структуры открыты.

         Объявление  структуры аналогично объявлению класса но вместо ключевого слова class ставится ключевое слово Struct :

         struct идентификатор

         {

         Объявление  данных или объектов

         }; 

         Объявление  структуры не подразумевает создание объекта или переменной. Объявление-это просто описание будущего объекта, в данном случае змейки. Чтобы использовать объект определенного класса или переменную определенного типа их сначала необходимо объявить в качестве объекта этого класса или переменной этого типа.

         Аналогично  для использования структурной  переменной необходимо объявить переменную этой структуры.

         Графический интерфейс.

         Пользовательский  интерфейс-это средства общения  пользователя с вашей программой. которые могут включать в себя изображения , звуки и текст. Ориентируясь на среднего пользователя интерфейс должен быть простым и удобным. Это снизит вероятность ошибок. 
     

         3.Опиание алгоритма решения в псевдокоде (команды в виде текста на русском языке).

         Алгоритм. 

         1) Описываются переменные и константы

         2) Выбор начальных координат случайным  образом

         3) Прорисовка начального положения

         4) Генерация на поле квадратиков  случайным образом

         5) Проверка: не появился ли квадратик  на черве.

         6) Управление “Змейкой” с клавиатуры.

         7) Проверка: “не укусила” ли “змейка сама себя”, если укусила выводится информационное окно (Информационная форма), в противном случае переходим к следующему пункту.

         8) Проверка: “не съела” ли “змейка”  “квадратик” если съела, то  наращиваем ей хвост и переходим к пункту 3), в противном случае см. Следующий пункт.

         9) Перерисовка “Змейки” 

         Постановка  задачи. 

         Цель: Создать игру на ловкость “Змейка” 

         Законченный вариант игры змейка должен содержать:

    1. “Змейку”, которая может двигаться в ограниченной плоскости. Маневрами “Змейки” должен управлять играющий. “Змейка” должна увеличиваться в размерах при столкновении с “квадратиком” и погибать при столкновении с “стеной”, при пересечении самой себя и при выходе за границы плоскости заданной программистом.
    2. “Квадратик” или другой объект, при столкновении с которым “Змейка” “съедает” его(увеличивается в длину в зависимости от условий заданных программистом).
    3. “стена” объект при столкновении с которым змейка погибает.

         “змейка”  может управляться с помощью  клавиш на форме, игра может иметь счетчик набранных очков, таблицу лучших игроков, которая может сохранятся и считываться из файла, а также другие элементы которые увеличивают играбельность игры. 

         Функции управления экранными  объектами. 

    сообщение назначение аргументы
    GotoXY( ) Размещение  объекта Координаты  х,у
    Level() Вы никогда  не выиграете, если не будете бдительны Координаты  х,у
    Move(Game &g) Функция которая  двигает и рисует Game &g
    PlusJabloko(Game &g) Функция разброски  квадратов Game &g
    skorostGame(Game &g) Функция старта змейки ее координат и скорости 
    Game &g
    SetColor(ConsoleColor text, ConsoleColor background) Изменение цвета ConsoleColor text, ConsoleColor background
    STENA_2()  Функция рисования  стены Координаты  х,у

    стены

    ZmejaStart() Старт игры GotoXY(10,15)
    Main() Главная функция  
     

         Описание  функций.

         //Функция  разброски квадратиков

         void PlusJabloko(Game &g){}

         1.Процесс….int x,y,i;

         Int n=g.gaduka.pCount;

         2.Заводим  цикл do while ,в котором задаем координаты объекта- яблоко

         x = rand() % 56+3; //

         y = rand() % 19+3; //кординаты яблока

         3.проверяем  объект-квадрат,попало ли оно  на объект-змейку.

         4. Если попало->break;

         5.Если  все нормально,запоминаем позицию  объекта-квадрат

         6.переносим  курсор в эту позицию

         7.присваиваем  цвет объкту-квадрат

         8.рисуем  объект-квадрат-> символом 4(5,6)

         printf("%c", 6); //рисуем яблоко каким хотим  символом 

         // Функция старта змейки ее координат  и скорости

         void skorostGame(Game &g){}

         1.задаем  точки-размер объека-змейка

         2.когда  создали-запоминам позицию

         3.задаем  скорость передвижения объекта-змейки

         4.рисуем  объект-квадратик 

         //Функция  которая двигает и рисует 

         int Move(Game &g){} 

         1.вводим  координаты головы объекта- змейка

         2. вводим координаты хвоста объекта-  змейка

         3.проверяем  следующую точку по направлению.

         4.проверяем  объект-змейка и объект- стенка, не наехал ли объект-змейка на объект-стенка

               -если да-то выход

               -если нет, то  продолжаем

         5.проверяем  объект-змейка саму на себя ,не  наехали на себя

               -если да – то  конец

               -если нет –  то продолжаем

         6.при  создании объекта- змейка перекомпилируем  змейку путем увеличения ее длины на одну точку

         7.появляется  новый массив, больший на 1-цу

         8.при  съедании объекта-квадратик -закрашиваем  его в цвет змейки

         9.закрашиваем  хвостик змеи в зеленый цвет

         10.закрашиваем  курсор в красный цвет(голова  змейки)

         Цвета.

         Экранные объекты можно закрашивать разными цветами .В объекте могут присутствовать два цвета- внутренний и цвет контура.

         Цвета кодируются цифрами:

         enum ConsoleColor

         {

            Pink  = 0,

                Blue  = 1,

                Green  = 2,

                Cyan  = 3,

                Red   = 4,

                Magenta  = 5,

                Brown  = 6,

                LightGray = 7,

                DarkGray  = 8,

                LightBlue = 9,

                LightGreen = 10,

                LightCyan = 11,

                LightRed  = 12,

                LightMagenta = 13,

                Yellow = 14,

                White  = 15 

         Если  значение кода задать большим 7,будет  использован остаток от его деления  на 7.

         При создании экранных объектов по умолчанию происходит следующее:

         -информационные  рамки располагаются вертикально  друг под другом в правой  части экрана, остальные объекты  размещаются в точке с координатами(0,0)

         -все  объекты создаются белыми с  черным контуром.  

         Структуры:

         struct Zmeja // структура змейка

         { COORD *t; //точки

               int PCount; //количество квадратиков

         };

         enum uprawlenie{LEFT,UP,RIGHT,DOWN}; //направление змейки 

         struct Game //даные-точности: змейки, квадратиков,  передвижение по X и Y, задержка, направление

         {

               Zmeja gaduka; //змейка

               COORD jabloko; //квадратик

               int dx,dy, //передвижение

                     pause; //задержка

               int nap; //направление

         };

         Сообщения.

    функция координаты сообщения
    Void Level() GotoXY(10,10) 

    GotoXY(10,11)

    <<"Wu nikogda ne wuigraete "<<endl;

    <<"eslu ne bydete bdutelnu!!!"<<endl;

    Void ZmejaStart() GotoXY(10,15) <<"Soberite 75 Kvadratov "<<endl;
    Void STENA_2() GotoXY(20,0)

    GotoXY(64,2)

    GotoXY(64,3)

    GotoXY(64,4)

    GotoXY(64,5)

    GotoXY(64,7)

    GotoXY(64,8)

    GotoXY(64,9)

    GotoXY(64,10)

    GotoXY(64,11)

    GotoXY(64,13)

    GotoXY(64,14)

    GotoXY(64,15)

    GotoXY(64,16)

    GotoXY(2,2)-(2,23)

    GotoXY(61,3)-(61,23)

    << "Igra \"Zmejka\" Maiko Ekaterini" <<endl;

    << "Danue:" << endl ;

    << "Kvadratov:0" << endl ;

    << "Dlina:3"<< endl;

    << "Speed:0" << endl;

    << "Uprawlenie:" << endl;

    << "Esc:Wuxod" << endl;

    << "P:Pause" << endl;

    <<"S:Start" << endl;

    <<"L:Level" << endl;

    <<":Wwerx"<<endl;

    <<":Wniz"<<endl;

    <<":Wlewo"<<endl;

    <<":Wprawo"<<endl;

    printf("*"); 

    printf("*");

    Void main() GotoXY(15,1)

    GotoXY(15,6)

    GotoXY(15,7)

    GotoXY(23,1)

    << "Wu wuigrali(maladec!!!)" << endl;

    printf( "\n\t\t\t" );

    printf( "\n\t\t\t" );

    printf("Wu proigrali(xa-xa-xa!!!)\n\n\t\t\t");

     

         Входные параметры:

         1.установка  позиции курсора х,у;

         void GotoXY(int X, int Y)

         {

               COORD coord = { X, Y };

               SetConsoleCursorPosition(hStdOut, coord);

         }

         2. Структура объекта – змейка 

         struct Zmeja // структура змейка

         {

               COORD *t; //точки

               int PCount; //количество квадратиков

         };

         3. данные- точности: змейки, квадратиков,  передвижение по X и Y

         struct Game задержка, направление

         {

               Zmeja gaduka; //змейка

               COORD jabloko; //квадратиков

               int dx,dy, //передвижение

               pause; //задержка

               int nap; //направление

         };

         Выходные параметры:

         1.Если  выиграл

    GotoXY(15,1); cout << "Wu wuigrali(maladec!!!)" << endl;

                                  GotoXY(15,6);printf( "\n\t\t\t" );

                                  GotoXY(15,7);printf( "\n\t\t\t" );

                                  getch();

                                  getch();

                                  getch();

                                  getch();

                                  getch();

                                  return;

         2.Если проиграл

         case KONEC:

         GotoXY(23,1); printf("Wu proigrali(xa-xa-xa!!!)\n\n\t\t\t");

                                 getch();

                                 return;

                                 break;

         4.Исходный текст программы С++

         Разработка  приложения, представляющего собой  компьютерную игру «Змейка».

         #include "StdAfx.h"

         #include "BaseObject.h"

         CBaseObject::CBaseObject(void)

         {

         }

         CBaseObject::~CBaseObject(void)

         {

         }

         void CBaseObject::SetX(int vx)

         {

               if (vx > -1)

                     pos_x = vx;

         }

         int CBaseObject::GetX(void)

         {

               return pos_x;

         }

         void CBaseObject::SetY(int vy)

         {

               if (vy > -1)

                     pos_y = vy;

         }

         int CBaseObject::GetY(void)

         {

               return pos_y;

         }

         void CBaseObject::SetColor(COLORREF e_clr)

         {

               clr = e_clr;

         }

         COLORREF CBaseObject::GetColor(void)

         {

               return clr;

         }

         #include "StdAfx.h"

         #include "Element.h"

         CElement::CElement(void)

         {

               pos_x = -1;

               pos_y = -1;

               clr = RGB(0,255,0); 

         }

         CElement::CElement(int vx, int vy)

         {

               pos_x = vx;

               pos_y = vy;

               clr = RGB(0,255,0);  

         }

         CElement::~CElement(void)

         {

         }

         void CElement::Show(CDC * DC)

         {

    // если элемент имеет  отрицательные координаты  то он не отображается

               if (pos_x < 0 && pos_y < 0) return;

    // отображаем элемент

    DC->Rectangle(pos_x,pos_y,pos_x+BASE_ELEMENT_SIZE,pos_y+BASE_ELEMENT_SIZE);

    DC->FillSolidRect(pos_x+1,pos_y+1,BASE_ELEMENT_SIZE-2,BASE_ELEMENT_SIZE-2,clr);

         }

         void CElement::Clear(CDC * DC, COLORREF bg_clr)

         {

    // закрашиваем элемент

    DC->FillSolidRect(pos_x,pos_y,BASE_ELEMENT_SIZE,BASE_ELEMENT_SIZE,bg_clr);

         }

         #include "StdAfx.h"

         #include "Game.h"

         CGame::CGame(CString player_name, bool v_brd)

         {

    // инициализация переменных

               l_st = GAME_NOT_END;

               delay = GAME_MAX_DELAY;

               started = false;

               l_border = v_brd;

               l_num = 0;

               points = 0;

               pl_name = player_name;

         }

         CGame::~CGame(void)

         {

               if (started)

               {

                     Stop();

               }

         }

         int CGame::GetLevelNumber()

         {

               return l_num;

         }

         int CGame::GetDelay()

         {

               return delay;

         }

         int CGame::GetPoints()

         {

               return points;

         }

         int CGame::GetStatus()

         {

               return l_st;

         }

         CString CGame::GetPlayer()

         {

               return CString(pl_name);

         }

         bool CGame::IsStarted()

         {

               return started;

         }

         bool CGame::IsBorder()

         {

               return l_border;

         }

         void CGame::Start()

         {

    // присвоим флагу запуска значение true

               started = true; 

    // создадим уровень

               Level = new CLevel(l_num,1000,620,l_border);

    // присвоим статусу  игы состояние  "игра не окончена"

               l_st = GAME_NOT_END;

         }

         void CGame::StartNextLevel()

         {

    // увеличиваем номер уровня игры

               l_num = l_num + 1;

    // делем задержку  на 2 (скорость игры  увеличивается в  2 раза)

               delay = delay / 2;

    // запускаем игру

               Start();

         }

         void CGame::Stop()

         {

    // удаляем уровень

               delete Level;

      // присвоим флагу запуска значение false

               started = false;

         }

         void CGame::Pause()

         {

               l_st = GAME_PAUSE;

         }

         void CGame::UnPause()

         {

               l_st = GAME_NOT_END;

         }

         void CGame::DoMotion()

         {

    // если состояние  игры = "игра не  окончена"

               if (l_st == GAME_NOT_END)

               {

    // производим расчет логики

                     switch (Level->DoCalculation())

                     {

    // если игрок попал  на стену или  догнал сам себя

                           case LEVEL_MOVE_FALSE:

    // то присвоим статусу  игры значение "игрок  проиграл"

                                 l_st = GAME_PLAYER_LOST;

                                 break;

    // если игрок попал  на элемент

                           case LEVEL_ADD_ELEMENT:

    // то увеличим кол-во  очков

                                 points += GAME_POINT_COUNT;  

    //if (!Level->Snake->AddElement()) 

    // добавим элемент

                                 Level->Snake->AddElement();

    // если все элементы собраны

                           if (Level->Snake->GetCount() == Level->GetCountElements())

    // то присвоим статусу  игры значение "игрок  победил"

                                       l_st = GAME_PLAYER_WIN;   

    // генерируем новую позицию для элемента

                                 Level->GenerateNewPosForElement();

                                 break;

    // если игрок попал  на пустое место

                           default:

    // запускаем движение

                                 Level->Snake->Move();

                                 break;

                     }

               }

         }

    // InitDialog.cpp : implementation file

         #include "stdafx.h"

         #include "Snake.h"

         #include "InitDialog.h"

    // CInitDialog dialog

         IMPLEMENT_DYNAMIC(CInitDialog, CDialog)

         CInitDialog::CInitDialog(CWnd* pParent /*=NULL*/)

               : CDialog(CInitDialog::IDD, pParent)

               , txtName(_T("Player"))

               , chkBorder(FALSE)

         {

         }

         CInitDialog::~CInitDialog()

         {

         }

         void CInitDialog::DoDataExchange(CDataExchange* pDX)

         {

               CDialog::DoDataExchange(pDX);

               DDX_Text(pDX, IDC_EDIT1, txtName);

               DDX_Check(pDX, IDC_CHECK2, chkBorder);

         }

         BEGIN_MESSAGE_MAP(CInitDialog, CDialog)

               ON_BN_CLICKED(IDOK, &CInitDialog::OnBnClickedOk)

         END_MESSAGE_MAP()

    // CInitDialog message handlers

         void CInitDialog::OnBnClickedOk()

         {

    // TODO: Add your control notification handler code here

               OnOK();

         }

         #include "StdAfx.h"

         #include "Level.h"

         CLevel::CLevel(int ln, int sz_x, int sz_y, bool brd)

         

               srand((unsigned int)time(NULL)/2);

    // инициализируем переменные 

               w_cnt = LEVEL_WALL_COUNT + ln; 

               el_cnt = LEVEL_ELEMENT_COUNT + ln;

               width = sz_x;

               height = sz_y;

               GetLevelling(width,height);

               border = brd;

               int csz_x = sz_x / BASE_ELEMENT_SIZE;

               int csz_y = sz_y / BASE_ELEMENT_SIZE;

               int cx,cy,k;   

               bool flg = true; 

    // генерируем уровень

    // 800 и 600 это минимально  допустимые размеры  уровня иначе уровень  не генерируется

               if (sz_x < 800 || sz_y < 600)

               {

                     w_cnt = 0;

                     return;

               }

    // генерируем стены  (+ 4 т.к. возможен  вариант игры с  рамками)

               Walls = new CWall * [w_cnt+4];  

               for (k = 0; k < w_cnt; k++)

               

    // получим координаты стены

                     cx = Rnd(2*BASE_ELEMENT_SIZE,sz_x-LEVEL_MAX_WALL_LENGTH*BASE_ELEMENT_SIZE);

                     cy = Rnd(2*BASE_ELEMENT_SIZE,sz_y-LEVEL_MAX_WALL_LENGTH*BASE_ELEMENT_SIZE);  

    // выровняем их по  сетке

                     GetLevelling(cx,cy);

    /* создадим стену  с произвольным  расположением:

    если Rnd(0,10) дает четное число, то расположение будет  горизонтальное

    если Rnd(0,10) дает не четное число, то расположение будет  вертикальное

    длина стены принимает значения из диапазона от 3 до 6 */

                     Walls[k] = new CWall(cx,cy,Rnd(0,10)%2,Rnd(3,6));

               }

    // если игра создана  с рамками, то  создадим рамки  (путем создания 4 стен)

               if (brd)

               {

               Walls[w_cnt] = new CWall(0,0,0,csz_x+1);

               Walls[w_cnt+1] = new CWall(0,sz_y,0,csz_x+1);

               Walls[w_cnt+2] = new CWall(0,BASE_ELEMENT_SIZE,1,csz_y-1);

               Walls[w_cnt+3] = new CWall(sz_x,BASE_ELEMENT_SIZE,1,csz_y-1);

                     w_cnt += 4;

               

    // генерируем элемент 

               while (flg)

               {

    // получим координаты элемента

                     cx = Rnd(BASE_ELEMENT_SIZE,width);

                     cy = Rnd(BASE_ELEMENT_SIZE,height);

    // выровняем их по  сетке

                     GetLevelling(cx,cy);

    //проверим  не попали ли  координаты на  стену, если попали  то повторим генерацию

                     for (k = 0; k < w_cnt; k++)

                     {

                           flg = Walls[k]->IsWall(cx,cy);

                           if (flg) break;

                     }

               }

    // создадим элемент  с координатыми

               Element = new CElement(cx,cy);

               Element->SetColor(RGB(255,255,0));

    // генерируем змею

    // получим координаты для змейки

               GetPosSnake(cx,cy);

    // создадим змейку

               Snake = new CSnake(cx,cy,el_cnt, width,height);

         }

         CLevel::~CLevel(void)

         {

               int k;

               for (k = 0; k < w_cnt; k++)

               {

                     delete Walls[k];

               }

               delete [] Walls;

               delete Element;

               delete Snake;

         }

         int CLevel::Rnd(int a, int b)

         

               int r = a + (rand()%((b-a)+1));

               return r;

         }

         void CLevel::GenerateNewPosForElement()

         {

               bool flg = true;

    // присвоим старые  координаты элемента

               int nx = Element->GetX();

               int ny = Element->GetY();

               int rx,ry,k;

               while (flg)

               {

    // сгенерируем новые координаты элемента

                     rx = Rnd(BASE_ELEMENT_SIZE,width);

                     ry = Rnd(BASE_ELEMENT_SIZE,height);

    // выровняем из по сетке

                     GetLevelling(rx,ry);

    // проверим не попали  ли они на стену

                     for (k = 0; k < w_cnt; k++)

                     {

                           flg = Walls[k]->IsWall(rx,ry);

                           if (flg) break;

                     }

    // если они не  попали на стену

                     if (!flg)

                     {

    // то проверим попали  ли они на змейку

                           for (k = 0; k < Snake->GetCount(); k++)

                           {

         if (Snake->Body[k]->GetX() == rx && Snake->Body[k]->GetY() == ry)

                                       flg = true;

                           }

                           if (Snake->GetX() == rx && Snake->GetY() == ry)

                                       flg = true;

                     }

    // проверим не совпали  ли новые координаты  со старыми

                     if (rx == nx && ry == ny) flg = true;

               } 

    // если новые координаты  попали на свободное  место, то установим  их

               Element->SetX(rx);

               Element->SetY(ry);

         }

         void CLevel::GetPosSnake(int & sx, int & sy)

         {

               bool flg = true;

               int n,m;

    // начальное расположение  змейки (центр экрана)

               int xx = width / 2;

               int yy = height / 2;

               while (flg)

               {

    // выравниваем координаты  по сетке

                     GetLevelling(xx,yy);

    // проверяем не попали  ли координаты  на стенку

                     for (n = 0; n < w_cnt; n++)

                     {   

                           for (m=0; m < 4; m++)

                           {

                     flg = Walls[n]->IsWall(xx,yy+m*BASE_ELEMENT_SIZE);

                                 if (flg) break;

                           }

                           if (flg) break;

                     }

                     if (!flg) break;

    // если координаты  не попали на  свободное место,  то генерируем  новые

                     xx = Rnd(BASE_ELEMENT_SIZE,width);

                     yy = Rnd(BASE_ELEMENT_SIZE,height);

               }

    // если координаты  попали на свободное  место возвращаем  их

               sx = xx;

               sy = yy;

         }

         void CLevel::GetLevelling(int & lx, int & ly)

         {

               /*старый  вариант

    // получим целое  число элементов  в кординатах lx и  ly

               lx = lx / BASE_ELEMENT_SIZE;

               ly = ly / BASE_ELEMENT_SIZE;

    // получим выровняные  координаты

               lx = lx * BASE_ELEMENT_SIZE;

               ly = ly * BASE_ELEMENT_SIZE; 

               /* новый вариант  */

    // выравниваем координаты

               lx = lx - (lx % BASE_ELEMENT_SIZE);

               ly = ly - (ly % BASE_ELEMENT_SIZE);

         }

         int CLevel::GetWidth()

         {

               return width;

         }

         int CLevel::GetHeight()

         {

               return height;

         }

         int CLevel::GetCountElements()

         {

               return el_cnt;

         }

         int CLevel::DoCalculation()

         

               int nx,ny,k,dnx=0,dny=0;

    // получим координаты  точки для расчетов

               switch (Snake->GetMovement())

               {

                     case SNAKE_MOVE_LEFT:

                           dnx = - BASE_ELEMENT_SIZE;   

                           break;

                     case SNAKE_MOVE_UP:

                           dny = - BASE_ELEMENT_SIZE;   

                           break;

                     case SNAKE_MOVE_RIGHT:

                           dnx = BASE_ELEMENT_SIZE;   

                           break;

                     case SNAKE_MOVE_DOWN:

                           dny = BASE_ELEMENT_SIZE; 

                           break;

               }

               nx = Snake->GetX() + dnx;

               ny = Snake->GetY() + dny;

               if (!border)

               {

                     if (nx < 0) nx = width;

                     if (ny < 0) ny = height; 

                     if (nx > width) nx = 0;

                     if (ny > height) ny = 0;

               }

    // проверим столкновение  со стенками 

    // проверяем не попала  ли координаты  на элемент

               if (Element->GetX() == nx && Element->GetY() == ny)

               {

    // если попали, то  возвращаем статус "добавление  нового элемента"

                     return LEVEL_ADD_ELEMENT;

               }

    // проверяем не попали ли координаты на стенку

               for (k = 0; k < w_cnt; k++)

               {

    // если попали, то  возвращаем статус "нет  хода"

                     if (Walls[k]->IsWall(nx,ny))

                     {

    //l_st = LEVEL_PLAYER_BAD;

                           return LEVEL_MOVE_FALSE;

                     }

               }

    // проверяем не попала  ли змейка на  себя

               for (k = 0; k < Snake->GetCount(); k++)

               {

    // если попала, то  возвращаем статус "нет  хода"

               if (Snake->Body[k]->GetX() == nx && Snake->Body[k]->GetY() == ny)

                           return LEVEL_MOVE_FALSE;

               }

    // если координаты  совпали с пустым  местом, то возвращаем  статус "есть ход"

               return LEVEL_MOVE_TRUE;

         }

         void CLevel::Show(CDC * DC)

         {

               int k;

               for (k = 0; k < w_cnt; k++)

               {

                     Walls[k]->Show(DC);

               

               Element->Show(DC);

               Snake->Show(DC);

         }

         void CLevel::Clear(CDC * DC, COLORREF bg_clr)

         {

               int k;

               for (k = 0; k < w_cnt; k++)

               {

                     Walls[k]->Clear(DC,bg_clr);

               

               Element->Clear(DC,bg_clr);

               Snake->Clear(DC, bg_clr);

         }

    // MainFrm.cpp : implementation of the CMainFrame class

         #include "stdafx.h"

         #include "Snake.h"

         #include "MainFrm.h"

         #ifdef _DEBUG

         #define new DEBUG_NEW

         #endif

    // CMainFrame

         IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)

         BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)

               ON_WM_CREATE()

         END_MESSAGE_MAP()

         static UINT indicators[] =

         {

               ID_SEPARATOR,           // status line indicator

               ID_INDICATOR_CAPS,

               ID_INDICATOR_NUM,

               ID_INDICATOR_SCRL,

         };

    // CMainFrame construction/destruction

         CMainFrame::CMainFrame()

         {

    // TODO: add member initialization code here

         }

         CMainFrame::~CMainFrame()

         {

         }

         int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

         {

               if (CFrameWnd::OnCreate(lpCreateStruct) == -1)

                     return -1;

    /*if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

    if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC))

               {

                     TRACE0("Failed to create toolbar\n");

                     return -1;      // fail to create

               }

         */ if (!m_wndStatusBar.Create(this) ||  !m_wndStatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT)))

               {

                     TRACE0("Failed to create status bar\n");

                     return -1;      // fail to create

               }

    // TODO: Delete these three lines if you don't want the toolbar to be dockable

    //m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

               EnableDocking(CBRS_ALIGN_ANY);

    //DockControlBar(&m_wndToolBar);

               return 0;

         }

         BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

         {

               if( !CFrameWnd::PreCreateWindow(cs) )

                     return FALSE;

    // TODO: Modify the Window class or styles here by modifying

    //  the CREATESTRUCT cs

    cs.style = WS_OVERLAPPED|WS_CAPTION|FWS_ADDTOTITLE|WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_MAXIMIZE | WS_SYSMENU; 

               return TRUE;

         }

    // CMainFrame diagnostics

         #ifdef _DEBUG

         void CMainFrame::AssertValid() const

         {

               CFrameWnd::AssertValid();

         }

         void CMainFrame::Dump(CDumpContext& dc) const

         {

               CFrameWnd::Dump(dc);

         }

         #endif //_DEBUG

    // CMainFrame message handlers

    // Snake.cpp : Defines the class behaviors for the application.

         #include "stdafx.h"

         #include "Snake.h"

         #include "MainFrm.h"

         #include "SnakeDoc.h"

         #include "SnakeView.h"

         #ifdef _DEBUG

         #define new DEBUG_NEW

         #endif

    // CSnakeApp

         BEGIN_MESSAGE_MAP(CSnakeApp, CWinApp)

    // Standard file based document commands

               ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)

               ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)

    // Standard print setup command

               ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)

           END_MESSAGE_MAP()

    // CSnakeApp construction

         CSnakeApp::CSnakeApp()

         {

    // TODO: add construction code here,

    // Place all significant initialization in InitInstance

         }

    // The one and only CSnakeApp object

         CSnakeApp theApp;

    // CSnakeApp initialization

         BOOL CSnakeApp::InitInstance()

         {

    // InitCommonControlsEx() is required on Windows XP if an application

    // manifest specifies use of ComCtl32.dll version 6 or later to enable

    // visual styles.  Otherwise, any window creation will fail.

               INITCOMMONCONTROLSEX InitCtrls;

               InitCtrls.dwSize = sizeof(InitCtrls);

    // Set this to include all the common control classes you want to use

    // in your application.

               InitCtrls.dwICC = ICC_WIN95_CLASSES;

               InitCommonControlsEx(&InitCtrls);

               CWinApp::InitInstance();

    // Initialize OLE libraries

               if (!AfxOleInit())

               {

                     AfxMessageBox(_T(""));

                     return FALSE;

               }

               AfxEnableControlContainer();

    // Standard initialization

    // If you are not using these features and wish to reduce the size

    // of your final executable, you should remove from the following

    // the specific initialization routines you do not need

    // Change the registry key under which our settings are stored

    // TODO: You should modify this string to be something appropriate

    // such as the name of your company or organization

         SetRegistryKey(_T("Local AppWizard-Generated Applications"));

         LoadStdProfileSettings(4);  // Load standard INI file options (including MRU)

    // Register the application's document templates.  Document templates

    //  serve as the connection between documents, frame windows and views

               CSingleDocTemplate* pDocTemplate;

               pDocTemplate = new CSingleDocTemplate(

                     IDR_MAINFRAME,

                     RUNTIME_CLASS(CSnakeDoc),

                     RUNTIME_CLASS(CMainFrame),       // main SDI frame window

                     RUNTIME_CLASS(CSnakeView));

               if (!pDocTemplate)

                     return FALSE;

               AddDocTemplate(pDocTemplate);

    // Parse command line for standard shell commands, DDE, file open

               CCommandLineInfo cmdInfo;

               ParseCommandLine(cmdInfo);

    // Dispatch commands specified on the command line.  Will return FALSE if

    // app was launched with /RegServer, /Register, /Unregserver or /Unregister.

               if (!ProcessShellCommand(cmdInfo))

                     return FALSE;

    // The one and only window has been initialized, so show and update it

               m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);

               m_pMainWnd->UpdateWindow();

    // call DragAcceptFiles only if there's a suffix

    //  In an SDI app, this should occur after ProcessShellCommand

               return TRUE;

         }

         CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)

         

         }

         void CAboutDlg::DoDataExchange(CDataExchange* pDX)

         {

               CDialog::DoDataExchange(pDX); 

               DDX_Control(pDX, IDC_LIST5, lstColName);

               DDX_Control(pDX, IDC_LIST6, lstColPoint);

         }

         BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)

         ON_BN_CLICKED(IDOK, &CAboutDlg::OnBnClickedOk)

         END_MESSAGE_MAP()

    // App command to run the dialog

    // CSnakeApp message handlers

         void CAboutDlg::OnBnClickedOk()

         {

    // TODO: Add your control notification handler code here

               OnOK();

         }

         BOOL CAboutDlg::OnInitDialog()

         {

               CDialog::OnInitDialog(); 

               int k;

               CString str;

    // выведим таблицу  рекордов

               for (k = 0; k < RECORD_COUNT; k++)

               {   

    // добавляем в колнку  очков очки игрока

                     str.Format(_T("%d"),Rec->Arr[k].point_cnt);

                     lstColPoint.AddString(str);

    // добавляем в колонку  имен имя игрока

                     lstColName.AddString(Rec->Arr[k].name); 

               }

               return true;

         }

    // SnakeDoc.cpp : implementation of the CSnakeDoc class

         #include "stdafx.h"

         #include "Snake.h"

         #include "SnakeDoc.h"

         #ifdef _DEBUG

         #define new DEBUG_NEW

         #endif

    // CSnakeDoc

         IMPLEMENT_DYNCREATE(CSnakeDoc, CDocument)

         BEGIN_MESSAGE_MAP(CSnakeDoc, CDocument)

         END_MESSAGE_MAP()

    // CSnakeDoc construction/destruction

         CSnakeDoc::CSnakeDoc()

         {

    // TODO: add one-time construction code here

               Game = NULL;

         }

         CSnakeDoc::~CSnakeDoc()

         {

               if (Game != NULL) delete Game;

         }

         BOOL CSnakeDoc::OnNewDocument()

         {

               if (!CDocument::OnNewDocument())

                     return FALSE;

    // если игра создана

               if (Game != NULL)

               {

    // удалим ее

                     delete Game;

                     Game = NULL;

               }

    // отобразим меню игры

               CInitDialog InitDlg;

               InitDlg.DoModal();

    // создадим игру

               Game = new CGame(InitDlg.txtName, InitDlg.chkBorder); 

    // TODO: add reinitialization code here

    // (SDI documents will reuse this document)

               return TRUE;

         }

    // CSnakeDoc serialization

         void CSnakeDoc::Serialize(CArchive& ar)

         {

               if (ar.IsStoring())

               {

    // TODO: add storing code here

               }

               else

               {

    // TODO: add loading code here

               }

         }

    // CSnakeDoc diagnostics

         #ifdef _DEBUG

         void CSnakeDoc::AssertValid() const

         {

               CDocument::AssertValid();

         }

         void CSnakeDoc::Dump(CDumpContext& dc) const

         {

               CDocument::Dump(dc);

         }

         #endif //_DEBUG

    // CSnakeDoc commands

         #include "StdAfx.h"

         #include "SnakeObject.h"

         CSnake::CSnake(int hx, int hy, int max_cnt, int mx, int my)

         {

               int k;

               pos_x = hx;

               pos_y = hy;

               max_x = mx;

               max_y = my;

               clr = RGB(255,0,0);

               count = SNAKE_MIN_COUNT;

               max_count = max_cnt; 

               dx = 0; 

               dy = - BASE_ELEMENT_SIZE;

    // создаем тело змейки

               Body = new CElement * [max_cnt];

    // создаем начальное  тело змейки

               for (k = 0; k < count; k++)

               {

                     Body[k] = new CElement(hx,hy+(k+1)*BASE_ELEMENT_SIZE);   }  

         }

         CSnake::~CSnake(void)

         {

               int k;

               for (k = 0; k < count; k++)

               {

                     delete Body[k];

               }

               delete [] Body;

         }

         int CSnake::GetCount(void)

         {

               return count;

         }

         void CSnake::SetMovement(int v)

         {

    /* устанавливаем вид  движения змейки, но при этом проверяем чтоб направления новое направление было не симметрично старому */

               switch (v)

               {

                     case SNAKE_MOVE_LEFT:

                           if (dx != BASE_ELEMENT_SIZE)

                           dx = - BASE_ELEMENT_SIZE;

                           dy = 0;

                           break;

                     case SNAKE_MOVE_UP:

                           dx = 0;

                           if (dy != BASE_ELEMENT_SIZE)    

                           dy = - BASE_ELEMENT_SIZE;   

                           break;

                     case SNAKE_MOVE_RIGHT:

                           if (dx != - BASE_ELEMENT_SIZE)    

                           dx = BASE_ELEMENT_SIZE;

                           dy = 0;

                           break;

                     case SNAKE_MOVE_DOWN:

                           dx = 0;

                           if (dy != - BASE_ELEMENT_SIZE)

                           dy = BASE_ELEMENT_SIZE;

                           break;

               }

         }

         int CSnake::GetMovement()

         {

               if (dx < 0 && dy == 0) return SNAKE_MOVE_LEFT;

               if (dx == 0 && dy < 0) return SNAKE_MOVE_UP;

               if (dx > 0 && dy == 0) return SNAKE_MOVE_RIGHT;

               return SNAKE_MOVE_DOWN;

         }

         bool CSnake::AddElement()

         

    // если количество  элементов равно  максимально допустимому,  то не добавляем  элемент

               if (max_count == count) return false;

    // создаем новый  элемент

               Body[count] = new CElement();

               // присваиваем ему  значение последнего  элемента

               Body[count]->SetX(Body[count-1]->GetX());

               Body[count]->SetY(Body[count-1]->GetY());

    // выполняем один  ход змейки

               Move();

    // увеличиваем число  элементов тела  змейки на 1

               count++;

               return true; 

         }

         void CSnake::Move(void)

         

               int k, px,py;

    // перезапишем координаты  начиная с конца  по принципу:

    // последний = предпоследнему  и т.д.

               for (k = count-1; k > 0; k--)

               {

                     Body[k]->SetX(Body[k-1]->GetX());

                     Body[k]->SetY(Body[k-1]->GetY());

               }

    // для первого элемента  присвоим координаты  головы змейки

               Body[0]->SetX(pos_x);

               Body[0]->SetY(pos_y);

    // рассчитаем координаты  головы

               px = pos_x + dx;

               py = pos_y + dy;

               if (px < 0) px = max_x;

               if (py < 0) py = max_y;

               if (px > max_x) px = 0;

               if (py > max_y) py = 0;

    // значение новых  координат головы

               SetX(px);

               SetY(py);

         }

         void CSnake::Show(CDC * DC)

         {

    // если голова змейки  имеет отрицательные  координаты, то не  отображаем ее

               if (pos_x < 0 && pos_y < 0) return;

               int k;

    // отображаем голову  змейки

    DC->Rectangle(pos_x,pos_y,pos_x+BASE_ELEMENT_SIZE,pos_y+BASE_ELEMENT_SIZE);

    DC->FillSolidRect(pos_x+1,pos_y+1,BASE_ELEMENT_SIZE-2,BASE_ELEMENT_SIZE-2,clr);

    // отображаем тело

               for (k = 0; k < count; k++)

               {

                     Body[k]->Show(DC);

               }

         }

         void CSnake::Clear(CDC * DC, COLORREF bg_clr)

         {

               int k;

    // закрашиваем голову  змейки

    DC-FillSolidRect(pos_x,pos_y,BASE_ELEMENT_SIZE,BASE_ELEMENT_SIZE,bg_clr);

    // закрашиваем тело  змейки

               for (k = 0; k < count; k++)

               {

                     Body[k]->Clear(DC, bg_clr);

               }

         }

    // SnakeView.cpp : implementation of the CSnakeView class

         #include "stdafx.h"

         #include "Snake.h"

         #include "SnakeDoc.h"

         #include "SnakeView.h"

         #include "MainFrm.h"

         #ifdef _DEBUG

         #define new DEBUG_NEW

         #endif

    // CSnakeView

         IMPLEMENT_DYNCREATE(CSnakeView, CView)

         BEGIN_MESSAGE_MAP(CSnakeView, CView)

    // Standard printing commands

               ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)

               ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)

               ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)

               ON_WM_KEYDOWN()

               ON_COMMAND(ID_OPTIONS_PAUSE, &CSnakeView::OnOptionsPause)

               ON_COMMAND(ID_OPTIONS_SHOWRECORDS, &CSnakeView::OnOptionsShowrecords)

         ON_COMMAND(ID_APP_ABOUT, &CSnakeView::OnAppAbout)

         END_MESSAGE_MAP()

    // CSnakeView construction/destruction

         CSnakeView::CSnakeView()

         {

    // TODO: add construction code here

               Records = new CTableRecords();

               Records->LoadFromFile(_T("Records.dat"));

               Dlg = new CAboutDlg();

               Dlg->Rec = Records;

         }

         CSnakeView::~CSnakeView()

         {

               delete Records;

               delete Dlg;

         }

         BOOL CSnakeView::PreCreateWindow(CREATESTRUCT& cs)

         {

    // TODO: Modify the Window class or styles here by modifying

    //  the CREATESTRUCT cs 

               return CView::PreCreateWindow(cs);

         }

    // CSnakeView drawing

         void CSnakeView::OnDraw(CDC* pDC)

         

               CSnakeDoc* pDoc = GetDocument();

               ASSERT_VALID(pDoc);

               if (!pDoc)

                     return;

    // если игра не  создана

               if (pDoc->Game == NULL)

    // то выходим

                     return;

    // если игра создана  но не запущена и статус игры = "игра не окончена"

    if (!pDoc->Game->IsStarted() && pDoc->Game->GetStatus() == GAME_NOT_END)

    // то запускаем игру

                     pDoc->Game->Start();

               if (pDoc->Game->GetStatus() == GAME_PAUSE)

                     return;

    // если игра создана

               if (pDoc->Game->IsStarted())

               {    

    // выполняем ход  игры

                     pDoc->Game->DoMotion();

    // если статус игры = "игра  не окончена"

                     if (pDoc->Game->GetStatus() == GAME_NOT_END) 

                     {

    // то отображаем  уровень

                           pDoc->Game->Level->Show(pDC); 

    // производим расчет  региона который  меняется (регион движения змейки)

                           RECT rgn;

                           int cn = pDoc->Game->Level->Snake->GetCount()-1;

                           int x1 = pDoc->Game->Level->Snake->GetX();

                           int y1 = pDoc->Game->Level->Snake->GetY();

                           int x2 = pDoc->Game->Level->Snake->Body[cn]->GetX();

                           int y2 = pDoc->Game->Level->Snake->Body[cn]->GetY();

                           if (x1 <= x2)

                           {

                                 rgn.left = x1-BASE_ELEMENT_SIZE;

                                 rgn.right = x2+2*BASE_ELEMENT_SIZE;

                           }

                           else

                           {

                                 rgn.left = x2-BASE_ELEMENT_SIZE;

                                 rgn.right = x1+2*BASE_ELEMENT_SIZE;

                           }

                           if (y1 <= y2)

                           {

                                 rgn.top = y1-BASE_ELEMENT_SIZE;

                                 rgn.bottom = y2+2*BASE_ELEMENT_SIZE;

                           }

                           else

                           {

                                 rgn.top = y2-BASE_ELEMENT_SIZE;

                                 rgn.bottom = y1+2*BASE_ELEMENT_SIZE;

                           }

    // перерисовываем его

                           InvalidateRect(&rgn);

    // выводим в statusbar информацию о уровне

                           CMainFrame * M = (CMainFrame*) GetParent();

                           CString Str;

    Str.Format(_T("Кол-во  очков: %d. Собранно  элементов: %d из %d"),pDoc->Game->GetPoints(),pDoc->Game->Level->Snake->GetCount(),LEVEL_ELEMENT_COUNT + pDoc->Game->GetLevelNumber());

                           M->m_wndStatusBar.SetPaneText(0,Str);

    // рассчитываем регион для элемента

               rgn.left = pDoc->Game->Level->Element->GetX()-BASE_ELEMENT_SIZE;

               rgn.top = pDoc->Game->Level->Element->GetY()-BASE_ELEMENT_SIZE;

               rgn.right = rgn.left + 2*BASE_ELEMENT_SIZE;

               rgn.bottom = rgn.top + 2*BASE_ELEMENT_SIZE;  

    // перерисовываем элемент

                           InvalidateRect(&rgn);   

    // выполняем задержку

                           SleepEx(pDoc->Game->GetDelay(),false);

                     }

    // если статус игры  не = "игра не  окончена"

                     else

                     {  

    // остановить игру

                           pDoc->Game->Stop();

    // добавить рекорд в таблицу

         Records->AddRecord(pDoc->Game->GetPoints(),pDoc->Game->GetPlayer());

    // сохранить таблицу  рекордов

                           Records->SaveToFile(_T("Records.dat"));

    // если статус игры = "игрок  победил"

                           if (pDoc->Game->GetStatus() == GAME_PLAYER_WIN)

                           {

    // запуск следующего  уровня

                                 pDoc->Game->StartNextLevel();

                                 Invalidate(); 

                           }

    // если статус не = "игрок  победил"

                           else

                           {       

    // отобразим таблицу  рекордов

                                 Dlg->DoModal();

                           }   

                     }

               

    // TODO: add draw code for native data here

         }

    // CSnakeView printing 

         BOOL CSnakeView::OnPreparePrinting(CPrintInfo* pInfo)

         {

    // default preparation

               return DoPreparePrinting(pInfo);

         }

         void CSnakeView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

         {

    // TODO: add extra initialization before printing

         }

         void CSnakeView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

         {

    // TODO: add cleanup after printing

         }

         void CSnakeView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)

         {  

               CSnakeDoc* pDoc = GetDocument();

               ASSERT_VALID(pDoc);

               if (!pDoc)

                     return;

    // если нажат пробел

               if (nChar == 32)

               {

    // если статус игры  не = "пауза"

                     if (pDoc->Game->GetStatus() != GAME_PAUSE)

    // то делаем паузу

                           pDoc->Game->Pause();   

                     else

    // иначе отменяем  паузу

                           pDoc->Game->UnPause();

                     Invalidate();

               }

    // если игра запущена

               if (pDoc->Game->IsStarted())

               {

    // то если нажатая  клавиша это стрелка

         if (nChar >= SNAKE_MOVE_LEFT && nChar <= SNAKE_MOVE_DOWN)

                     {

    // то установим тип  движения

         pDoc->Game->Level->Snake->SetMovement(nChar);

                     }

               }

         }

    // CSnakeView diagnostics 

         #ifdef _DEBUG

         void CSnakeView::AssertValid() const

         {

               CView::AssertValid();

         }

         void CSnakeView::Dump(CDumpContext& dc) const

         {

               CView::Dump(dc);

         }

         CSnakeDoc* CSnakeView::GetDocument() const // non-debug version is inline

         {

               ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSnakeDoc)));

               return (CSnakeDoc*)m_pDocument;

         }

         #endif //_DEBUG

    // CSnakeView message handlers

         void CSnakeView::OnOptionsPause()

         {

    // TODO: Add your command handler code here

               CSnakeDoc* pDoc = GetDocument();

               ASSERT_VALID(pDoc);

               if (!pDoc)

                     return;

    // если статус игры  не = "пауза"

               if (pDoc->Game->GetStatus() != GAME_PAUSE)

    // то делаем паузу

                     pDoc->Game->Pause();   

               else

    // иначе отменяем  паузу

                     pDoc->Game->UnPause();

               Invalidate();  

         } 

         void CSnakeView::OnOptionsShowrecords()

         {

               CSnakeDoc* pDoc = GetDocument();

               ASSERT_VALID(pDoc);

               if (!pDoc)

                     return;

    // преостановим игру

               pDoc->Game->Pause();

    // отобразим таблицу  рекордов

               Dlg->DoModal();

    // запустим игру

               pDoc->Game->UnPause();

               Invalidate();

    // TODO: Add your command handler code here

         }

         void CSnakeView::OnAppAbout()

         {

               // TODO: Add your command handler code here

               CSnakeDoc* pDoc = GetDocument();

               ASSERT_VALID(pDoc);

               if (!pDoc)

                     return;

    // приостановим игру

               pDoc->Game->Pause()

    // отобразим файл  помощи

         ShellExecuteA(NULL,"open","Help.txt",NULL,NULL,SW_SHOWNORMAL); 

         }

         #include "StdAfx.h"

         #include "TableRecords.h"

         CRecord::CRecord()

         {

               point_cnt = 0; 

               name = _T("<name>\0"); 

         }

         CRecord::~CRecord()

         {

         }

         CTableRecords::CTableRecords()

         {

         }

         CTableRecords::~CTableRecords(void)

         {

         }

         bool CTableRecords::AddRecord(int v_point, CString v_name)

         {

               int ir=0,k;

    // попробуем найти  место для рекода  в таблице

               for (ir = 0; ir < RECORD_COUNT; ir++)

               {

                     if (Arr[ir].point_cnt <= v_point)

                           break;

               }

    // если место есть

               if (ir < RECORD_COUNT)

               {

    // то опустим все  рекорды которые  меньше текущего  на один ниже

                     for (k = RECORD_COUNT-1; k > ir; k--)

                     {

                           Arr[k].point_cnt = Arr[k-1].point_cnt;    

                           Arr[k].name = Arr[k-1].name;

                     

    // добавим новый рекорд

                     Arr[ir].point_cnt = v_point;  

                     Arr[ir].name = v_name;

                     return true;

               }

               return false;

         }

         bool CTableRecords::SaveToFile(TCHAR * filename)

         {

               CFile hFile;    

               int k,ibuf; 

               hFile.Open(filename,CFile::modeCreate | CFile::modeWrite); 

               for (k = 0; k < RECORD_COUNT; k++)

               {

                     ibuf = Arr[k].point_cnt;

                     hFile.Write(&ibuf, sizeof(ibuf));  

                     ibuf = 2*CString(Arr[k].name).GetLength();

                     ibuf += 2;

                     hFile.Write(&ibuf,sizeof(ibuf));  

                     hFile.Write(Arr[k].name,ibuf);

               }

               hFile.Flush();

               hFile.Close();

               return true;

         }

         bool CTableRecords::LoadFromFile(TCHAR * filename)

         {

               CFile hFile;

               int k,ibuf; 

               TCHAR cbuf[100];

               if (hFile.Open(filename,CFile::modeRead) == false)

                     return false;

               for (k = 0; k < RECORD_COUNT; k++)

               {  

                     hFile.Read(&ibuf, sizeof(ibuf));

                     Arr[k].point_cnt = ibuf;

                     hFile.Read(&ibuf,sizeof(ibuf));  

                     hFile.Read(&cbuf,ibuf);

                     Arr[k].name = cbuf;

               }

               hFile.Close();

               return true;

         }

         #include "StdAfx.h"

         #include "Wall.h"

         CWall::CWall(int vx, int vy, int vloc, int vlen)

         {

               pos_x = vx;

               pos_y = vy;

    // цвет стены по  стандарту

               clr = RGB(0,0,255); 

               loc = vloc;

               len = vlen;

         }

         CWall::~CWall(void)

         {

         }

         void CWall::SetLength(int w_len)

         {

    // если длина стены  меньше 0 то используем  длину по умолчанию

               if (w_len > 0)

                     len = w_len;

               else

                     len = WALL_MIN_LENGTH;

         }

         int CWall::GetLength(void)

         {

               return len;

         }

         void CWall::SetLocation(int w_loc)

         {

               loc = w_loc;

         }

         int CWall::GetLocation(void)

         {

               return loc;

         }

         bool CWall::IsHorizontal(void)

         {

               if (loc == 0) return true; 

               return false;

         }

         bool CWall::IsVertical(void)

         {

               if (loc != 0) return true; 

               return false;

         }

         bool CWall::IsWall(int x, int y)

         {

               int dl = (len-1) * BASE_ELEMENT_SIZE;

               if (loc == 0)

               {

                     if (y == pos_y)

                           if (x >= pos_x && x <= pos_x + dl)

                                 return true; 

               }

               else

               {

                     if (x == pos_x)

                           if (y >= pos_y && y <= pos_y + dl)  

                                 return true;

               }

               return false;

         }

         void CWall::Show(CDC * DC)

         {

    // вычислим длину  стены с учетом  размера элементов

               int dl = len * BASE_ELEMENT_SIZE;

               if (loc == 0)

               {

    // рисуем стену по горизонтали

    DC->Rectangle(pos_x, pos_y, pos_x + dl, pos_y + BASE_ELEMENT_SIZE);

    DC->FillSolidRect(pos_x + 1, pos_y + 1, dl-2, BASE_ELEMENT_SIZE-2, clr);

               }

               else

               {

    // рисуем стену по вертикали

    DC->Rectangle(pos_x, pos_y, pos_x + BASE_ELEMENT_SIZE, pos_y + dl);

    DC->FillSolidRect(pos_x + 1, pos_y + 1, BASE_ELEMENT_SIZE - 2, dl - 2, clr);

               }

         }

         void CWall::Clear(CDC * DC, COLORREF bg_clr)

         {

    // вычислим длину  стены с учетом  размера элементов

               int dl = len * BASE_ELEMENT_SIZE;

               if (loc == 0)  

    // закрашиваем стену  по горизонтали

         DC->FillSolidRect(pos_x, pos_y, dl, BASE_ELEMENT_SIZE, bg_clr);

               else 

    // закрашиваем стену по вертикали

    DC->FillSolidRect(pos_x, pos_y, BASE_ELEMENT_SIZE, dl, bg_clr);

         } 
     
     
     
     
     
     
     
     
     

         5.Тестирование  программы.

         Первоначальный  вид игры при запуске

           

         Змейка  ударилась об объект стенку

           

         Объект  ударился об объект

         

         6.Заключение. 

         В коде задачи указано максимально  допустимое количество квадратиков, поэтому  в игре предусмотрено данное ограничение. Ограничено количество игроков, ограничено количество квадратиков.

         Можно добавить озвучивание событий игры, уровень сложности игры и разные настройки параметров игры в коде программы. Это вызвало бы больший интерес к игре.

         Используемая  в программе структура файла  наиболее оптимально подходит для такого рода операций над файлом . Информация о игроке, указывается в меню справа.

         В целом приложение представляет собой  почти самый простой вариант  игры «Змейка » с набором самых  необходимых функций.

    7.Список литературы. 

    1. Начальный курс С и С++.: Учебник. /Б. И. Березин. Москва:"ДИАЛОГ-МИФИ",1999г. 
    2. Язык программирования С++. : Учебник. /. Страуструп. Киев:"ДиаСофт", 1993 г.

    3. Введение в  язык С++: Учебник. / Бьярн Страустрап.

    – СПб.: 1995.

    4. Структуры  и алгоритмы обработки данных: Учебник. / Матьяш В.А., Путилов В.А., Фильчаков В.В. , Щёкин С.В. - Апатиты,  КФ Петр ГУ, 2000

    5. С++ /Дэвис Стефан Р.,4-е издание : Пер. с англ.:- М.: Издательский дом «Вильямс»,2003

    6. Основы программирования: Учеб. Для сред. проф. образования  /И.Г.Семакин, А.П.Шестаков. – М., 2006.

    7. С++ экспресс  курс: Учебник. /Лаптев В.В. – СПб.: БХВ- Петербург 2004.

    8. С++ учебный  курс: Учебник. /Франка П. – СПб.: Питер 2005.

    9. МОДЕЛИ И CТРУКТУРЫ ДАННЫХ:/ Учебное пособие/ 
    Д.Далека, А.С. Деревянко, О.Г.Кравец, Л.Е. Тимановская -Харьков: ХГПУ, 2000

    10.Высшая математика  для экономистов: учебник для  студентов вузов/Н.Ш.Кремер,3-е издание.-М.:ЮНИТИ-ДАНА,2006

Информация о работе Разработка приложения, представляющего собой компьютерную игру «Змейка»