Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Алгоритм змейки. 
:(
    Опции темы
Innuendo
Дата 24.2.2006, 22:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 745
Регистрация: 24.12.2005
Где: Молдова

Репутация: нет
Всего: 6



Здравствуйте.
Все знают стандартную игру - змейку... Помогите пожалуйста с алгоритмом- как запоминать изгибы змейки?
ну там всё ясно, при кушании длина возрастает, она всегда идет, при клавиша поворачивается, но вот как изгибы сохранять? smile


--------------------
=)
PM MAIL ICQ Jabber   Вверх
maxim1000
Дата 25.2.2006, 02:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



а не проще ли запоминать вообще все сегменты?
впрочем, если все-таки сохранять изгибы, то непонятно, в чем проблема:
храним направление поворота (вправо/влево) и расстояние до следующего изгиба...



--------------------
qqq
PM WWW   Вверх
Бегемот
Дата 25.2.2006, 02:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 219
Регистрация: 26.1.2005
Где: На границе Европы и Азии

Репутация: нет
Всего: 3



Innuendo, вот что первое пришло в голову!
Допустим, каждая "часть тела" нашей змейки - это квадрат! Вся наша змейка перерисовывается через определённый промежуток времени, при этом она совершает движение в определённом направлении. Т.е. в один момент времени каждый квадрат змейки совершает движение, причём направление квадратов может быть и будет разным! Так вот для каждого квадрата змейки можно хранить определённую информацию. Эта информация, в самом простом случае, будет включать в себя координаты его верхнего угла, которые нам необходимы для отрисовки змейки, а также направление движения квадрата! Все квадраты змейки должны быть связаны между собой! Для примера, на языке C всё это можно реализовать с помощью двусвязного линейного списка!
Код

   enum MoveSnake {LEFT, RIGHT, UP, DOWN};
   const WidthSnak = 10;
   struct DataSnake
   {
      int Top;
      int Left;
      MoveSnake move;
   };

   struct ListSnake
   {
      DataSnake Data;
      ListSnake* next;
      ListSnake* prev;
   };

Как видишь, элемент списка содержит в себе указатели на предыдущий и последующий элементы, а также структуру Data, описаную выше! Структура Data содержит как раз то, очём я уже говорил - координаты и направление движения!
Изначально, мы имеем небольшую змейку(3-5 звеньев), все звенья которой совершают движение в одном направлении! Вероятно, у нас существует какой-то таймер, который через определённый интервал времени, перерисовывает наше пресмыкающееся. Так же у нас есть какая-то функция, которая обрабатывает нажатие клавиш! Так вот в этой самой функции, в случае нажатия клавиш, определяющих движение змейки, мы присваеваем определённому нами флагу нажатой клавиши нужное значение!
Код

MoveSnake FlagKeyPress;
void KeyPress()
{
   .........
   switch(d)
   {
      case 1:  FlagKeyPress = LEFT;    break;
      case 2:  FlagKeyPress = RIGHT;   break;
      case 3:  FlagKeyPress = UP;      break;
      case 4:  FlagKeyPress = DOWN;    break;
      default: FlagKeyPress = -1;
   }
}

Всё нажатую клавишу мы знаем! Теперь таймер! В таймере мы просматриваем с конца(т.е с хвоста нашей змейки) весь наш список и....первое: присваиваем каждому звену в поле move значение предыдущего звена поля move! Т.е. определяем направление его последующего перемещения! После чего перерисовываем звено на новом месте. Когда мы проходим весь список, т.е добираемся до головы змеи, проверяем состояние флага FlagKeyPress. Если его значение равно -1(в моём примере), то направление движения головы мы оставляем преждним, в противном же случае в поле move первого элемента списка записываем значение флага FlagKeyPress.
Ну, а вычисление координат одного звена и его отрисовка может выглядить так!
Код

   switch(list->Data.move)
   {
      case LEFT:  list->Data.Left -= WidthSnak; break;
      case RIGHT: list->Data.Left += WidthSnak; break;
      case UP:    list->Data.Top -= WidthSnak;  break;
      case DOWN:  list->Data.Top += WidthSnak;  break;
   }
   DrawSnak(list->Data.Left, list->Data.Top);


PM MAIL   Вверх
SoWa
Дата 25.2.2006, 07:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Харекришна
****


Профиль
Группа: Комодератор
Сообщений: 2422
Регистрация: 18.10.2004

Репутация: 6
Всего: 74



Смотри исходник на Дельфи.


Присоединённый файл ( Кол-во скачиваний: 24 )
Присоединённый файл  Snake.zip 30,77 Kb


--------------------
Всем добра smile
PM MAIL ICQ   Вверх
maxim1000
Дата 25.2.2006, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



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


--------------------
qqq
PM WWW   Вверх
SoWa
Дата 25.2.2006, 20:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Харекришна
****


Профиль
Группа: Комодератор
Сообщений: 2422
Регистрация: 18.10.2004

Репутация: 6
Всего: 74



А разве в примере который я выложил не так?


--------------------
Всем добра smile
PM MAIL ICQ   Вверх
maxim1000
Дата 25.2.2006, 22:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 33
Всего: 110



Цитата(SoWa @ 25.2.2006, 19:17 Найти цитируемый пост)
А разве в примере который я выложил не так?

когда смотрел первый раз (и когда писал), показалось, что не так
посмотрел во второй раз
оказалось, меня сбили с толку строчки:
Код

   for i:=0 to Max do
        if i < Max then Parts[i]:=Parts[i + 1]
                else Parts[i]:=LastSnake;

думал, тут идет приравнивание на уровне структур
а потом вспомнил, что на самом деле все это - указатели

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


--------------------
qqq
PM WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Алгоритмы | Следующая тема »


 




[ Время генерации скрипта: 0.0487 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.