top of page

Сейчас вы можете видеть пример простейшей игры, которую я написал на языке C++. Кто-то мог уже понять, что это просто змейка. Да, та самая игра, где вы просто управляете змейкой и кушаете фрукты, чтоб увеличить ее хвост, ну а выглядит это так:

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

А теперь кратко разберем, как же работает эта игра. Она использует 2 библиотеки iostream и conio.h. Первая библиотека контролирует запуск и корректность, а вторая является input и output консоли, то есть контролирует нажатия игрока, проверяя – выполняется ли бинд движения или нет.

Далее идут краткие “настройки”, размер карты, запись окончания игры, координаты фрукта и змеи. Ах да, я совсем забыл сказать, работает данная игра по принципу координатной прямой. Мы задаем символьный размер карты, который будет играть роль x и y. У них есть центр, есть плюс и есть минус. После координатной прямой идет размер хвоста, который в нашем случае максимум 100. Ну и в конце указание, что начальная координата 0 и что мы можем двигаться вниз, вверх, влево и вправо.

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

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

Следующий пункт Input. Это то место, которое отвечает за движения, но не полностью! Оно лишь задает движение клавишами, то есть, у нас есть назначения клавиш wasd (вверх, влево, вниз, вправо), но это пока не значит, что змея будет двигаться, это только бинд кнопок. Также там указано, что при нажатии кнопки X игра будет остановлена, точнее говоря закрыта.

А вот наконец мозг данной игры, функция Logic. Она уже отвечает за “логику”, говоря проще, за все то, что происходит. Именно тут задано появление фрукта, движение змейки после нажатия клавиши, проигрыш в случае, если вы врезались в хвост (можно также в стену, но в данном случае я отключил эту функцию), также эта функция отвечает за получение +10 очков за каждый фрукт.

И оставшаяся функция Main. Это можно назвать сердцем игры, пока оно “бьется” (работает), консоль будет выполнять все пункты, указанные в ней. В данном случае там 3 (draw, input, logic) пункта и setup (запуск). Это значит, что каждый запуск игры, будут обязательно проверяться эти пункты и проигрываться каждую секунду. Игра всегда будет проверять, чтоб идеально работали draw, input и logic. Только в случае, если все корректно работает, консоль будет запускаться и вы сможете поиграть в игру.

Вот сам код этой игры.

#include <iostream>

#include <conio.h> // Это console input|output, оно будет отслеживать, что было нажато

 

using namespace std;

 

bool gameover;

const int width = 50;

const int height = 20;

int x, y, fruitX, fruitY, score;

int tailX[100], tailY[100];

int nTail;

enum eDirection { STOP = 0, LEFT, RIGHT, UP, DOWN };

eDirection dir;

 

void setup() {

gameover = false;

dir = STOP;

x = width / 2 - 1;

y = height / 2 - 1;

fruitX = rand() % width;

fruitY = rand() % height;

score = 0;

}

 

void Draw() {

system("cls"); // system ("clear"); - если вы используете Linux

for (int i = 0; i < width + 1; i++)

cout << "#";

cout << endl;

 

for (int i = 0; i < height; i++) {

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

if (j == 0 || j == width - 1)

cout << "#";

if (i == y && j == x)

cout << "0";

else if (i == fruitY && j == fruitX)

cout << "F";

else {

bool print = false;

for (int k = 0; k < nTail; k++) {

if (tailX[k] == j && tailY[k] == i) {

print = true;

cout << "o";

}

}

if (!print)

cout << " ";

}

}

cout << endl;

}

 

for (int i = 0; i < width + 1; i++)

cout << "#";

cout << endl;

cout << "SCORE: " << score << endl;

}

 

void Input() {

if (_kbhit()) {

switch (_getch ())

{

case 'a':

dir = LEFT;

break;

case 'd':

dir = RIGHT;

break;

case 'w':

dir = UP;

break;

case 's':

dir = DOWN;

break;

case 'x':

gameover = true;

break;

}

}

}

 

void Logic() {

int prevX = tailX[0];

int prevY = tailY[0];

int prev2X, prev2Y;

tailX[0] = x;

tailY[0] = y;

for (int i = 1; i < nTail; i++) {

prev2X = tailX[i];

prev2Y = tailY[i];

tailX[i] = prevX;

tailY[i] = prevY;

prevX = prev2X;

prevY = prev2Y;

}

switch (dir)

{

case LEFT:

x--;

break;

case RIGHT:

x++;

break;

case UP:

y--;

break;

case DOWN:

y++;

break;

}

 

//if (x > width || x < 0 || y > height || y < 0) - врезаясь игра заканчивается, но это можно отключить.

// gameover = true; - это отключено, чтоб змейка не просто врезалась, а выходила с другой стороны карты.

if (x >= width - 1)

x = 0;

else if (x < 0)

x = width - 2;

 

if (y >= height)

y = 0;

else if (y < 0)

y = height - 1;

 

for (int i = 0; i < nTail; i++) {

if (tailX[i] == x && tailY[i] == y)

gameover = true;

}

 

if (x == fruitX && y == fruitY) {

score += 10;

fruitX = rand() % width;

fruitY = rand() % height;

nTail++;

}

}

 

int main() {

setup();

while (!gameover) {

Draw();

Input();

Logic();

}

return 0;

}

Рисунок4.png
Рисунок5.png
bottom of page