C++ Змейка: Урок 2 — Рисуем змейку и фрукт

Доработка функции Draw

Функция Draw, созданная в предыдущем уроке, нуждается в доработке для отображения змейки и фрукта на игровом поле. Добавим условные операторы if:

if (i == snakeY && j == snakeX) {
    std::cout << "0"; // Символ змейки
} else if (i == fruitY && j == fruitX) {
    std::cout << "F"; // Символ фрукта
} else {
    std::cout << " "; // Пробел для пустого пространства
}

Этот код проверяет координаты i и j текущей клетки поля. Если они совпадают с координатами змейки (snakeY, snakeX), выводится символ «0»; если с координатами фрукта (fruitY, fruitX), выводится «F»; в остальных случаях — пробел. Небольшое смещение змейки относительно нужной позиции связано с добавлением +1 к координатам при рисовании поля в предыдущем уроке. Для исправления этого, нужно отнять -1 из начальных координат x и y змейки.

Обработка ввода с клавиатуры

Для обработки нажатий клавиш используем библиотеку conio.h и функцию _kbhit(). Эта функция возвращает true, если нажата клавиша, и позволяет отслеживать нажатия без блокировки терминала.

#include <conio.h>

// ...

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;
    }
}

Этот код проверяет, нажата ли клавиша. Если да, то с помощью _getch() определяется нажатая клавиша, и в зависимости от неё изменяется направление движения змейки (dir) или завершается игра (gameOver = true).

Логика движения и обработка столкновений

Функция Logic содержит логику движения змейки. Используем switch для обработки направления движения:

switch (dir) {
    case Left:  snakeX--; break;
    case Right: snakeX++; break;
    case Up:    snakeY--; break;
    case Down:  snakeY++; break;
}

Добавим проверку на выход за границы игрового поля:

if (snakeX >= width || snakeX < 0 || snakeY >= height || snakeY < 0) {
    gameOver = true;
}

Этот код проверяет координаты змейки, и если она выходит за пределы поля, устанавливает gameOver в true, завершая игру.

Поедание фрукта и счёт

Добавим логику поедания фрукта и начисления очков:

if (snakeX == fruitX && snakeY == fruitY) {
    score += 10;
    // Генерация новых координат для фрукта (код аналогичен генерации начальных координат)
}

При совпадении координат змейки и фрукта, к счету добавляется 10 очков, а фрукт перемещается в случайное место на поле. В функции Draw добавляем вывод текущего счёта:

std::cout << "Score: " << score << std::endl;

Что будем искать? Например,программа