Время движения для змейки С++

232
26 ноября 2016, 19:03

Вот я написал:

#include <iostream>
#include <conio.h>
#include <cstdlib>
#include <Windows.h>
using namespace std;
char a[100][100];
//Початкові координати
int sx = 15, sy = 10;
//Напрям
int direct; 
void view();
void border();
//Напрямок
int direction(int direct) {
    if (direct == 0) return sy--;
    if (direct == 1) return sx++;
    if (direct == 2) return sy++;
    if (direct == 3) return sx--;
}
int main(){
    while (getch() != 27) {
        border();
        Sleep(500);
        switch (getch()) {
            case 72: direct = 0; break; //вгору
            case 77: direct = 1; break; //вправо
            case 80: direct = 2; break; //вниз
            case 75: direct = 3; break; //вліво
        }
        direction(direct);
        for (int i = 0; i < 20; i++)
            for (int j = 0; j < 60; j++) {
                a[sy][sx] = '0';
                if (sy >= 19 || sy <= 0 || sx >= 59 || sx <= 0) goto gameover;
            }
        system("cls");
        view();
    }
    gameover:
    cout << "Game over..." << endl;
    system("pause");
    return 0;
}
//Границі поля
void border() {
    for (int i = 0; i < 20; i++)
        for (int j = 0; j < 60; j++) {
            a[i][j] = ' ';
            a[0][j] = '#';
            a[i][0] = '#';
            a[19][j] = '#';
            a[i][59] = '#';
        }
}
//Малює поле
void view() {
    for (int i = 0; i < 20; i++) {
        for (int j = 0; j < 60; j++) {
            cout << a[i][j];
        }
        cout << endl;
    }
}

Вопрос: Мне не понятен момент с временем, по-этому у меня здесь не правильно фурычит. Помогите пожалуйста принять меры, чтобы при проходе каждой секунды элемент "0" сдвигался в нужном направлении.

Answer 1

Так не получится. Ты ожидаешь ввод - останавливая цикл, а вовремя Sleep(500); и ввод работать не будут.

Выход: нужен таймер, который будет проверятся в цикле, и когда пройдет секунда сдвинет "0" в указанном направлении. А если была нажата клавиша(изменено направление), то таймер сбрасываться. А также ожидание ввода, которое не останавливает цикл(перехват события, другой поток.... ).

Answer 2

Я привожу здесь простой ответ который решает поставленную задачу без излишних усложнений. То-есть без таймеров, много-поточности и асинхронности.

В общем случае мы имеем игровой цикл (while), который тикает так быстро как только может процессор. Следует учесть что на разных процессорах скорость будет разной, а по хорошему хотелось бы иметь одинаковую скорость на любом процессоре. Как же можно организовать движение змейки? Очевидно, есть два решения - либо на каждом тике сдвигать змейку на очень небольшое расстояние (что в терминологии использования текстового режима слегка неуместно), либо делать это не на каждом тике. Собственно ниже будет представлен пример как это делать не на каждом тике.

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

Следует перед основным циклом сохранить текущее время, и на каждой итерации замерять дельту - разницу между текущим временем и временем сохраненным ранее. Если дельта больше или равна необходимому интервалу (1 секунде) производим необходимые действия.

auto lastUpdate = std::chrono::steady_clock::now();
char ch = 0;
while (ch != 27) {
  auto now(std::chrono::steady_clock::now());
  auto dt = now - lastUpdate;
  if (dt >= std::chrono::seconds(1)) {
    lastUpdate = now;
    // здесь производим необходимые действия - тоесть сдвигаем змейку на 1 позициию
  }
  if (kbhit()) {
    // обработка ввода
    ch = getch();
  }
  std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
READ ALSO
Как удалить все под элементы tree view

Как удалить все под элементы tree view

Здравствуйте! Подскажите пожалуйста, как перебрать или удалить все под элементы выделенного элемента tree viewКод проверки на выделенность...

279
Существует ли Task-based Asynchronous Pattern (TAP) или его аналог в C++?

Существует ли Task-based Asynchronous Pattern (TAP) или его аналог в C++?

В средеNET есть замечательный асинхронный паттерн TAP, есть ли нечто подобное на C++ (не CLI)?

179
Работа с файлами С++

Работа с файлами С++

Потребовалось поработать с файлами в С++К моему удивлению, это оказалось не просто, в отличие от С#

186
Добавление в архив. POCO Zip

Добавление в архив. POCO Zip

Для работы с Zip выбрал POCO-библиотекиПытаюсь добавить элементы в архив, добавляется только последний

188