Код марио, музыка и взаимодействие с врагами



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

Все необходимые файлы ты можешь скачать тут: https://yadi.sk/d/dj0sHQi63Mm45U

КОД НИЖЕ
#include <SFML/Graphics.hpp>

#include <SFML/Audio.hpp> // библиотека для работы со звуком

using namespace sf;

float offsetX=0, offsetY=0; // смещения карты

 

// сама карта

const int H = 17;

const int W = 150;

String TileMap[H] = {

"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",

"0                                                                                                                                               0",

"0                                                                               w                                                          0",

"0              w                             w              w                                                                    0",

"0                                 w                                  kk                                                               0",

"0                                                                        k k k k                                                    0",

"0                 c                                                 k kkk kkk w                                                0",

"0                                                                  r k  k k                                                    0",

"0                                                                 rr k k                                                              0",

"0                                                                rrr kk                                                               0",

"0          c kckck                                      rrrr                                                                       0",

"0                                 t0                      rrrrr                                                                       0",

"0G                                00         t0     rrrrrr       G                                                          0",

"0      d g  d        00         00    rrrrrrr                                                                       0",

"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",

"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",

"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",

};

 

// класс игрока, всё как в предыдущей игре

class PLAYER {

public:

           float dx,dy;

           FloatRect rect;

           bool onGround;

           Sprite sprite;

           float currentFrame;

 

           // конструктор класса (начальные данные)

  PLAYER(Texture &image) {

                           sprite.setTexture(image);

                           rect = FloatRect(100,180,16,16);

                           dx=dy=0.1;

                           currentFrame = 0;

    }

 

           // перемещение персонажа

    void update(float time) {

                           rect.left += dx * time;   

               Collision(0);

 

                     if (!onGround) dy=dy+0.0005*time;       

                     rect.top += dy*time;

                       onGround=false;

               Collision(1);

               

               currentFrame += time * 0.005;

                  if (currentFrame > 3) currentFrame -= 3;

 

                  if (dx>0) sprite.setTextureRect(IntRect(112+31*int(currentFrame),144,16,16));

                      if (dx<0) sprite.setTextureRect(IntRect(112+31*int(currentFrame)+16,144,-16,16));

 

                     sprite.setPosition(rect.left - offsetX, rect.top - offsetY);

                     dx=0;

           }

               

           // обработка столкновений

           void Collision(int num) {

               

                           for (int i = rect.top/16 ; i<(rect.top+rect.height)/16; i++)

                           for (int j = rect.left/16; j<(rect.left+rect.width)/16; j++) {

                                                            if ((TileMap[i][j]=='P') || (TileMap[i][j]=='k') || (TileMap[i][j]=='0') || (TileMap[i][j]=='r') || (TileMap[i][j]=='t')) {

                                                                                                                                                                                               if (dy>0 && num==1) { rect.top = i*16 - rect.height; dy=0; onGround=true; }

           if (dy<0 && num==1) { rect.top = i*16 + 16; dy=0;}

           if (dx>0 && num==0) { rect.left = j*16 - rect.width; }                                                                                      if (dx<0 && num==0) { rect.left = j*16 +16;}

 }

           if (TileMap[i][j]=='c') { // TileMap[i][j]=' '; }

}

}

};

 

// класс для учёта врага (он похож на класс игрока)

class ENEMY {

public:

           float dx,dy;

           FloatRect rect;

           Sprite sprite;

           float currentFrame;

           bool life; // жив или мёртв

 

           // конструктор (начальные значения)

    void set(Texture &image, int x, int y) {

                           sprite.setTexture(image);

                           rect = FloatRect(x,y,16,16);

                  dx=0.05;

                           currentFrame = 0;

                           life=true;

    }

               

           // простейший интеллект врага- будет двигаться только по иксу, а при столкновении двигаться в обратную сторону

       void update(float time) {           

                     rect.left += dx * time;

               Collision();

 

                  currentFrame += time * 0.005;

               if (currentFrame > 2) currentFrame -= 2;

 

                  sprite.setTextureRect(IntRect(18*int(currentFrame), 0, 16,16));

                  if (!life) sprite.setTextureRect(IntRect(58, 0, 16,16));

                           sprite.setPosition(rect.left - offsetX, rect.top - offsetY);

}

 

    void Collision() {

                           for (int i = rect.top/16 ; i<(rect.top+rect.height)/16; i++)

                                           for (int j = rect.left/16; j<(rect.left+rect.width)/16; j++)

                                                            if ((TileMap[i][j]=='P') || (TileMap[i][j]=='0')) {

                                                          if (dx>0) { rect.left = j*16 - rect.width; dx*=-1; }                                                                                                      else if (dx<0) { rect.left = j*16 + 16; dx*=-1; }

                                                           }

          }

};

 

int main() { 

    RenderWindow window(VideoMode(400, 250), "Mario");

 

           Texture tileSet; tileSet.loadFromFile("Mario_Tileset.png");

 

           PLAYER Mario(tileSet);

           ENEMY enemy;

           enemy.set(tileSet,48*16,13*16);

 

           Sprite tile(tileSet);

           SoundBuffer buffer; // переменная для работы со звуком

           buffer.loadFromFile("Jump.ogg"); // загрузка звука (будет запускаться при прыжке)

           Sound sound(buffer); // помещение в буфер- будем проигрывать только при прыжке (это далее прописывается при нажатии клавиши вверх)

 

  Music music; // фоновая музыка

  music.openFromFile("Mario_Theme.ogg"); // загрузка из файла

  music.play(); // проигрывание музыки

 

           Clock clock;

               

           // главный цикл игры

  while (window.isOpen()) {

                           float time = clock.getElapsedTime().asMicroseconds();

                           clock.restart();

                           time = time/500; // здесь регулируем скорость игры

                           if (time > 20) time = 20;

 

                           Event event;

                           while (window.pollEvent(event)) {

                                      if (event.type == Event::Closed) window.close();

                           }

                               

                           // что происходит при нажатии клавиш

                           if (Keyboard::isKeyPressed(Keyboard::Left)) Mario.dx=-0.1;

             if (Keyboard::isKeyPressed(Keyboard::Right)) Mario.dx=0.1;

             if (Keyboard::isKeyPressed(Keyboard::Up))   if (Mario.onGround) { Mario.dy=-0.27; Mario.onGround=false; sound.play();}

 

                            Mario.update(time);

                            enemy.update(time);

 

                           // пересечение прямоугольников игрока и врага- при пересечении закрасимся красным, а убивание- если мы на врага падаем

                            if (Mario.rect.intersects( enemy.rect ) ) {

                                            if (enemy.life) {

                                                     if (Mario.dy>0) { enemy.dx=0; Mario.dy=-0.2; enemy.life=false;}

                                                     else Mario.sprite.setColor(Color::Red);

                                            }

                            }

                               

                           // задаём какое должно быть смещение карты

                            if (Mario.rect.left>200) offsetX = Mario.rect.left-200;

 

                           // отрисовка карты

                            window.clear(Color(107,140,255));

                            for (int i=0; i<H; i++)

                                            for (int j=0; j<W; j++) {

                                                           if (TileMap[i][j]=='P') tile.setTextureRect( IntRect(143-16*3,112,16,16) );

                                                           if (TileMap[i][j]=='k') tile.setTextureRect( IntRect(143,112,16,16) );

                                          if (TileMap[i][j]=='c') tile.setTextureRect( IntRect(143-16,112,16,16) );

                                                           if (TileMap[i][j]=='t') tile.setTextureRect( IntRect(0,47,32,95-47) );

                                                           if (TileMap[i][j]=='g') tile.setTextureRect( IntRect(0,16*9-5,3*16,16*2+5) );

                                                           if (TileMap[i][j]=='G') tile.setTextureRect( IntRect(145,222,222-145,255-222) );

                                               if (TileMap[i][j]=='d') tile.setTextureRect( IntRect(0,106,74,127-106) );

                                                      if (TileMap[i][j]=='w') tile.setTextureRect( IntRect(99,224,140-99,255-224) );

                                                           if (TileMap[i][j]=='r') tile.setTextureRect( IntRect(143-32,112,16,16) );

                                                           if ((TileMap[i][j]==' ') || (TileMap[i][j]=='0')) continue;

                                            tile.setPosition(j*16-offsetX,i*16 - offsetY) ;

                                                      window.draw(tile);

                           }

                               

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

                           window.draw(Mario.sprite);

             window.draw(enemy.sprite);

                               

                           // вывод всего на экран

                           window.display();

}

// завершение программы

return 0;

}

 

Коротко об OpenGL

OpenGL- это Open Graphic Library или открытая графическая библиотека. В отличие от SFML, это более низкоуровневая и универсальная библиотека графики. Но при этом она более сложная в освоении, на ней нужно писать больше кода. Также она работает с 3d объектами, а SFML поддерживает только 2d, т.е. плоские вещи. Многие современные игры используют OpenGL. Поэтому мы обязательно хотя бы кратко рассмотрим эту вещь ниже.

Для того чтобы в devcpp использовать OpenGL, не нужно каких-то специальных ухищрений. Заходим создать проект, выбираем вкладку Multimedia и там выбираем тип проекта OpenGL. Всё. Создастся файл со следующим содержанием (это тестовый код)

/**************************

 * Includes

 *

 **************************/

#include <windows.h>

#include <gl/gl.h>

 

/**************************

 * Function Declarations

 *

 **************************/

LRESULT CALLBACK WndProc (HWND hWnd, UINT message,

WPARAM wParam, LPARAM lParam);

void EnableOpenGL (HWND hWnd, HDC *hDC, HGLRC *hRC);

void DisableOpenGL (HWND hWnd, HDC hDC, HGLRC hRC);

 

/**************************

 * WinMain

 *

 **************************/

int WINAPI WinMain (HINSTANCE hInstance,

               HINSTANCE hPrevInstance,

               LPSTR lpCmdLine,

               int iCmdShow)

{

WNDCLASS wc;

HWND hWnd;

HDC hDC;

HGLRC hRC;       

MSG msg;

BOOL bQuit = FALSE;

float theta = 0.0f;

 

/* register window class */

wc.style = CS_OWNDC;

wc.lpfnWndProc = WndProc;

wc.cbClsExtra = 0;

wc.cbWndExtra = 0;

wc.hInstance = hInstance;

wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);

wc.hCursor = LoadCursor (NULL, IDC_ARROW);

wc.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);

wc.lpszMenuName = NULL;

wc.lpszClassName = "GLSample";

RegisterClass (&wc);

 

/* create main window */

hWnd = CreateWindow (

"GLSample", "OpenGL Sample",

WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE,

0, 0, 256, 256,

NULL, NULL, hInstance, NULL);

 

/* enable OpenGL for the window */

EnableOpenGL (hWnd, &hDC, &hRC);

 

/* program main loop */

while (!bQuit)

{

   /* check for messages */

   if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))

   {

       /* handle or dispatch messages */

       if (msg.message == WM_QUIT)

       {

           bQuit = TRUE;

       }

       else

       {

           TranslateMessage (&msg);

           DispatchMessage (&msg);

       }

   }

   else

   {

       /* OpenGL animation code goes here */

 

       glClearColor (0.0f, 0.0f, 0.0f, 0.0f);

       glClear (GL_COLOR_BUFFER_BIT);

 

       glPushMatrix ();

       glRotatef (theta, 0.0f, 0.0f, 1.0f);

       glBegin (GL_TRIANGLES);

       glColor3f (1.0f, 0.0f, 0.0f); glVertex2f (0.0f, 1.0f);

       glColor3f (0.0f, 1.0f, 0.0f); glVertex2f (0.87f, -0.5f);

       glColor3f (0.0f, 0.0f, 1.0f); glVertex2f (-0.87f, -0.5f);

       glEnd ();

       glPopMatrix ();

 

       SwapBuffers (hDC);

 

       theta += 1.0f;

       Sleep (1);

   }

}

 

/* shutdown OpenGL */

DisableOpenGL (hWnd, hDC, hRC);

 

  /* destroy the window explicitly */

DestroyWindow (hWnd);

 

return msg.wParam;

}

/********************

 * Window Procedure

 *

 ********************/

LRESULT CALLBACK WndProc (HWND hWnd, UINT message,

                     WPARAM wParam, LPARAM lParam)

{

 

switch (message)

{

case WM_CREATE:

   return 0;

case WM_CLOSE:

   PostQuitMessage (0);

   return 0;

 

case WM_DESTROY:

   return 0;

 

case WM_KEYDOWN:

    switch (wParam)

   {

   case VK_ESCAPE:

       PostQuitMessage(0);

       return 0;

   }

   return 0;

 

default:

   return DefWindowProc (hWnd, message, wParam, lParam);

}

}

/*******************

 * Enable OpenGL

 *

 *******************/

 

void EnableOpenGL (HWND hWnd, HDC *hDC, HGLRC *hRC)

{

PIXELFORMATDESCRIPTOR pfd;

int iFormat;

 

/* get the device context (DC) */

*hDC = GetDC (hWnd);

 

/* set the pixel format for the DC */

ZeroMemory (&pfd, sizeof (pfd));

pfd.nSize = sizeof (pfd);

pfd.nVersion = 1;

pfd.dwFlags = PFD_DRAW_TO_WINDOW |

PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;

pfd.iPixelType = PFD_TYPE_RGBA;

pfd.cColorBits = 24;

pfd.cDepthBits = 16;

pfd.iLayerType = PFD_MAIN_PLANE;

iFormat = ChoosePixelFormat (*hDC, &pfd);

SetPixelFormat (*hDC, iFormat, &pfd);

 

/* create and enable the render context (RC) */

*hRC = wglCreateContext( *hDC );

wglMakeCurrent( *hDC, *hRC );

 

}

/******************

 * Disable OpenGL

 *

 ******************/

void DisableOpenGL (HWND hWnd, HDC hDC, HGLRC hRC)

{

wglMakeCurrent (NULL, NULL);

wglDeleteContext (hRC);

ReleaseDC (hWnd, hDC);

}

Скомпилировав этот код, получим треугольник с цветными краями, который вращается.

...

Научимся теперь делать рисовать простые плоские статичные фигуры. Для этого нам нужно найти код:

 

       /* OpenGL animation code goes here */

 

       glClearColor (0.0f, 0.0f, 0.0f, 0.0f);

       glClear (GL_COLOR_BUFFER_BIT);

 

       glPushMatrix ();

       glRotatef (theta, 0.0f, 0.0f, 1.0f);

       glBegin (GL_TRIANGLES);

       glColor3f (1.0f, 0.0f, 0.0f); glVertex2f (0.0f, 1.0f);

       glColor3f (0.0f, 1.0f, 0.0f); glVertex2f (0.87f, -0.5f);

       glColor3f (0.0f, 0.0f, 1.0f); glVertex2f (-0.87f, -0.5f);

       glEnd ();

       glPopMatrix ();

 

       SwapBuffers (hDC);

 

       theta += 1.0f;

         Sleep (1);

 

В нём мы убираем theta и sleep (задержку) в конце, далее убираем glRotatef- т.е. вращаться ничего не будет. В начале объявление theta тоже можно убрать (float theta = 0.0f; вот эту строку)

Остаётся вот такой сырой код:

       glClearColor (0.0f, 0.0f, 0.0f, 0.0f);

       glClear (GL_COLOR_BUFFER_BIT);

 

       glPushMatrix ();

       glRotatef (theta, 0.0f, 0.0f, 1.0f);

       glBegin (GL_TRIANGLES);

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

       glEnd ();

       glPopMatrix ();

 

       SwapBuffers (hDC);

Первая строчка glClearColor отвечает за заливаемый фон. Цвета тут устроены по системе RGB- Red Green Blue или красный зелёный голубой. Нули дают нам чёрный цвет (отсутствие), а единицы- белый (смешение всех цветов). Используя эти 3 параметра в разных комбинациях, мы получаем разные цвета. Чтобы найти нужный цвет, нужно узнать его код в RGB (интернет и всякие пипетки в помощь)- например в 24-битной это выглядит так (по 8 бит или 256 кодов на каждый компонент) - 97, 126, 28. Теперь нам нужно это в долях выразить и записать: 97/255, 126/255, 28/255. Если код указан в 16-ричной системе счисления типа 9FA235, то нужно разбить по 2 цифры: 9F A2 35 и далее перевести в десятичную систему: 9*16+15, 10*16+2, 3*16+5 и опять выразить это в долях, можно даже самому не считать, а прям так выражениями и записывать. Т.е. аргументы будут такие: (9*16+15)/255, (10*16+2)/255, (3*16+5)/255. Можно даже изощриться и написать функции, которые тебе будут переводить из одного формата в другой, их для удобства можно писать даже в отдельном заголовочном файле.

Вторая строчка чистит экран, её мы не трогаем.

Далее- всё рисуемое заключается между glPushMatrix и glPopMatrix, это мы тоже не трогаем.

glBegin (GL_TRIANGLES); // здесь мы указываем- что именно будем рисовать. У нас указано по умолчанию GL_TRIANGLES, это значит что будет треугольник- он рисуется по 3 точкам.

Сначала научимся ставить точку. Чтобы ставить чисто точки, надо поменять GL_TRIANGLES на GL_POINTS. И далее до glEnd мы эти точки сколько нам надо ставим.

Для постановки точки мы указываем 2 вещи- цвет точки и её позицию. Сначала цвет, потом позиция.

glColor3f (0,1,0); glVertex2f (0,0);

 Здесь у нас будет зелёная точка в позиции 0,0. Это значит центр координат, он у нас находится в центре графического окошка. Единица- это края окна. Как в декартовой системе. Например, -1,1 это будет влево по горизонтали до конца (-1) и вверх по вертикали до конца (1), т.е. левый верхний угол. Если мы поставим 0.5, то это будет посередине от центра до края. Т.е. положение точки тоже выражается в долях, как мы это делаем с цветами.

Чтобы поставить линию, нам нужно в glBegin указать GL_LINES. И отрезок ставится по 2 точкам. Например, если нам нужен чёрный отрезок с левого нижнего угла (но не впритык, а близко к нему) до правого верхнего, можно сделать так:

glColor3f (0,0,0); glVertex2f (-0.9,-0.8);

glColor3f (0,0,0); glVertex2f (0.9,0.8);

Можно поставить ещё одну линию, написав дальше код ещё 2 следующих точек, по которым построится вторая линия.

Если мы поставим цвета 2 точек, по которым строится линия, разными, то цвет будет в виде градиента- переливаться с одного до другого.

Аналогично мы можем треугольник сделать по 3 точкам.

Размер окна можно поменять вот в этой строчке: WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE,

0, 0, 256, 256,

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

Для построения непрерывных графиков используем:

glBegin (GL_LINE_LOOP);

Тут конечная точка предыдущей линии будет начальной линией следующей.

Например, вот так мы можем нарисовать окружность на весь экран:

for(double a=0; a < 2*M_PI; a+=0.01) glVertex2f (cos(a),sin(a));

Главное не забыть подключить cmath для синуса и косинуса. Окружность рисуется по принципам полярных координат. M_PI это чисто пи, константа, она прописана в том же cmath.

Чтобы сплющить окружность в эллипс по горизонтали, мы домножаем синус на небольшой коэффициент, например 1.3. Если мы будем прибавлять или отнимать что-то с синусом, то круг будет двигаться вверх или вниз. Если же мы уже аргумент будем менять, то тут интереснее: если прибавить единицу к аргументу, то круг как бы наклонится на 45 градусов. Откуда именно так, полагаю что это из-за того что тангенс 45 градусов равен единице. Ты можешь со всем этим поэкспериментировать.

Ты можешь открыть справочник по высшей математике и посмотреть параметрически заданные графики- и далее реализовать их в OpenGL по полярной системе координат.

Вот этот код нарисует красивый листик конопли:

for(double a=0; a < 2*M_PI; a+=0.01) {

           double r= 0.3*(1+sin(a))*(1+0.9*cos(8*a))*(1+0.1*cos(24*a));

           glVertex2f (r*cos(a),r*sin(a)-0.5);

}

 

________________________________________________

РАЗДЕЛ 5

Практические Полезности

 

Программа с выбором действий

Часто встречается такой тип программы, в котором нам надо выбрать одно из действий. Иногда таких выборов в большой программе бывает несколько. Рассмотрим на примере вывода с комиссией с электронных кошельков.

Программа даёт нам 3 варианта, откуда вывести: с киви, с яндекс денег или ввести свою комиссию. Для киви и яндекса комиссия фиксирована.

Для подобных выборов уже разработано стандартное решение, я это делаю через специальную функцию:

int Select() {

           cout << "Калькулятор вывода с комиссией" << endl;

           _(); // это cout<<endl;

           cout << "(0) Назначить свои комиссии" << endl;

           cout << "(1) Яндекс деньги" << endl;

           cout << "(2) Киви кошелёк" << endl;

           int x; cin>>x; _(); return x;

}

Если у нас всего 2 варианта на выбор, можно использовать тип данных bool и вводить 0 или 1. В случае bool возвращать можно и противоположное. Вот пример с булевым значением функции:

bool NewGame() {

           __(0); // это зачистка экрана system("CLS");

           cout << "(0) Новый учёт\n(1) Продолжаем\n";

           bool res; cin>>res; __(0); return !res;

}

Теперь вернёмся к калькулятору выбора с комиссией. Как используется эта функция выбора:

int k= Select();

if(k==0) {

// делаем что-то там своё

}

if(k==1) { опять что-то делаем уже другое }

И т.д. и т.п.

...

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

#include <iostream>

using namespace std;

void _() { cout << endl; }

void __(int k) {

           if(k==0) system("CLS");

           if(k==1) { _(); system("pause"); }

           if(k==2) { __(1); __(0); }

}

 

int Select() {

           cout << "Калькулятор вывода с комиссией" << endl;

           _();

           cout << "(0) Назначить свои комиссии" << endl;

           cout << "(1) Яндекс деньги" << endl;

           cout << "(2) Киви кошелёк" << endl;

           int x; cin>>x; _(); return x;

}

 

int main() {

           setlocale(0,"");

           int k; double proc, stat; double $, _$;

           while(1) {

                           k= Select();

                           if(k==0) {

                                           cout << "Введите процент комиссии при выводе: "; cin>>proc; proc/=100;

                                           cout << "Беспроцентная комиссия в денежных у.е: "; cin>>stat;

                           }

                           if(k==1) { proc= 0.03; stat= 45; }

                           if(k==2) { proc= 0.02; stat= 50; }

                           _();

                           bool povtor= true;

                           do {

                                           cout << "Сколько денег на счету: "; cin>>$;

                                           _$= ($-stat)/(1+proc);

                                           if((k==1)&&(_$<500)) cout << "Минимальная сумма вывода с яндекса равна 500" << endl;

                                           else {

                                                           cout << "Можно вывести: " << _$ << endl;

                                                           _();

                                                           cout << "(0) Выход\n(1) Ещё раз" << endl; cin>>povtor;

                                           }

                           } while (povtor);

                           __(2);

           }

}

 

Программа с учётом величин

Следующий тип программ это когда у нас учитываются какие-то величины. Это могут быть виртуальные валюты и очки опыта в игре или доходы и расходы в бюджетной программе. И эти величины у нас выводятся постоянно наверх программы. Посмотрим на простейшем примере учёта каких-то виртуальных баллов:

#include <iostream>

#include <string>

using namespace std;

 

// функция вывода величин наверх- сначала делается зачистка экрана, затем вывод

void info (string name, double money) {

           system("CLS");

           cout << name << " ($ " << money << ")";

           cout << endl << endl; // разделение рабочей части программы от выводных полей

}

 

int main() {

           setlocale(0,"");

           string name; double money, saldo; // переменные для хранения данных лучше объявлять вне основного цикла программы чтобы они сотни раз не переобъявлялись с расходом памяти

               

           // вводим начальные данные

           cout << "Ваше имя: "; cin >> name;

           cout << "Ваши деньги: "; cin >> money;

 

           // учитываем эти данные в бесконечном цикле

           while(true) {

                           info(name,money); // вывод того что у нас уже есть

 

                           // изменение учитываемой величины

                           cout << "! Вводить расход с минусом" << endl;

                           cout << "Приход/расход: "; cin >> saldo;

                           money+=saldo;

           }

}

 

Программа с обработкой строк

Ещё один тип программ- мы вводим строку, а программе нужно из неё вычленить какие-то нужные данные, как-то их обработать и вывести нам результат. Такое случается чем дальше, тем чаще- это сильно расширяет возможности программирования. Ниже будет рассмотрен пример с учётом времени.

Я ввожу например 7:12 - 7:24 делал зарядку +

И программа должна понять, сколько минут я делал зарядку. Данные вводятся как строка. А потом она с этими минутами может что-то делать, например посчитать процент от всех деятельностей вообще.

Для хранения времени у нас будет специальный класс:

class vakit {

public:

           int hours; int minutes;

};

А так мы будем переводить строковые данные во временные:

vakit ToVakit (string x) {

           string Hours= "", Minutes= ""; // сначала строки пустые

           int i= 0; // итератор для пробега по строке

           while (x[i]!=':') Hours+=x[i++]; // пока не наткнулись на двоеточие, добавлять эту часть строки в часы

           i++; // пропустить двоеточие

           while (x[i]!='\0') Minutes+=x[i++]; // пока не достигли конца строки, добавлять оставшееся в минуты

           vakit t; // создаём наш экземпляр временного типа данных

           t.hours= StringToInt(Hours); // перевод из строки в число

           t.minutes= StringToInt(Minutes);

           return t;

}

А вот уже класс для хранения всей строки, которую мы и вводим:

class geler {

public:

           // хранится начальное время, конечное, само название процесса и его знак- насколько процесс желательный

            vakit start, finish; string process; int sign;

           // вычисление этих самых минут

            int TimeDist () {

                            return finish.minutes - start.minutes + (finish.hours - start.hours)*60 + 1 ;

            }

};

И теперь функция перевода из строки в экземпляр класса geler. Делается всё аналогично как перевод в формат времени, только более сложно, т.к. нужно больше разных типов символов обработать:

geler ToGeler (string s) {

           geler g;

           string Time1= "", Time2= "", Process= "";

           int i= 0;

           while (s[i]!=' ') Time1+=s[i++];

           i+=3;

           while (s[i]!=' ') Time2+=s[i++];

           i++;

           while ((int)s[i+1]!=0) Process+=s[i++];

           if(s[i]=='!') g.sign= 3;

           if(s[i]=='+') g.sign= 2;

           if(s[i]=='*') g.sign= 1;

           if(s[i]=='-') g.sign= 0;

           g.process= Process;

           g.start= ToVakit(Time1);

           g.finish= ToVakit(Time2);

           return g;

}

 


Дата добавления: 2018-09-22; просмотров: 472; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!