Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Поиск пути для игры Lines, помогите написать алгоритм на С 
V
    Опции темы
Sergio
  Дата 7.12.2008, 16:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 843
Регистрация: 28.7.2006
Где: Solar System-> Earth

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



Всем привет. 
Нужно алгоритм поиск пути в двовхмерном массыве(игровое поле). Вот игровое поле:
user posted image

playfield[10][10] - структура, где есть поле TYPE.
В этом поле содержиться инфа о даной клетке:
RECT_NONE - невидимая клетка. неиспользуется в игре 
RECT_EMPTY - пустая клетка. 
RECT_BALL - занятая клетка. находиться какой-то объэкт

Интерфейс функции:
Код

// false is no possible to move ball
bool MoveTo(int fromX, int fromY, int toX, int toY);

Помогите плз написать алгоритм поиска пути на С/С++. Прочитал алгоритмы здесь: http://pmg.org.ru/ai/stout.htm мало что понял  smile
Заранее спасибо.



Это сообщение отредактировал(а) Sergio - 7.12.2008, 16:19
PM MAIL ICQ   Вверх
maxim1000
Дата 7.12.2008, 19:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



алгоритм поиска в ширину можно представить так:
вместо того, чтобы находить сразу все доступные точки, найти сначала точки, в которые можно добраться за 0 шагов, потом за 1 шаг, потом за 2, потом за 3 и т.д.
если до точки можно добраться, значит рано или поздно мы её встретим

за 0 шагов, естественно, можно добраться только в стартовую точку
за 1 - во всех её соседей (кроме тех, через которые нельзя ходить)
чтобы найти все точки, доступные за 2 шага, пробегаемся по точкам, доступным за 1 шаг и помечаем всех её соседей (кроме тех, по которым нельзя ходить), как доступные за 2 шага
и так продолжаем, пока не встретим искомую точку

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

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

Это сообщение отредактировал(а) maxim1000 - 7.12.2008, 19:05


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


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


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

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



Мм, может я не в тему, но разве элементарный алгоритм волны не подойдет?
Вроде он ищет оптимальнейший путь и только надо обработать случай, когда до клетки не добраться.


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


Эксперт
****


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

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



честно говоря, в своём владении терминологией не уверен, но, по-моему, в данном случае (т.е. невзвешенном графе) волнойов лагоритм, поиск в ширину и алгоритм Дейкстры совпадают


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


Опытный
**


Профиль
Группа: Участник
Сообщений: 843
Регистрация: 28.7.2006
Где: Solar System-> Earth

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



Я так понял что алгоритм поиска в ширину реализуется с помощью рекурсии.. 
Вот что примерно такого(поправьте если неправильно)
По диагонали проходить путь нельзя:
Код

bool MoveTo(int fromX, int fromY, int toX, int toY)
{
  // checking for destination point
  if(fromX+1 == toX && fromY == toY) {return true;}
  else if(fromX-1 == toX && fromY == toY) {return true;}
  else if(fromX == toX && fromY+1 == toY) {return true;}
  else if(fromX-1 == toX && fromY-1 == toY) {return true;}

  // checking for free way
  if(playfield[fromX+1][fromY].TYPE == RECT_EMPTY)
    MoveTo(fromX+1, fromY, toX, toY);

  if(playfield[fromX-1][fromY].TYPE == RECT_EMPTY)
    MoveTo(fromX-1, fromY, toX, toY);

  if(playfield[fromX][fromY+1].TYPE == RECT_EMPTY)
    MoveTo(fromX, fromY+1, toX, toY);

  if(playfield[fromX][fromY-1].TYPE == RECT_EMPTY)
    MoveTo(fromX, fromY-1, toX, toY);
}

спасибо.
PM MAIL ICQ   Вверх
ksnk
Дата 7.12.2008, 23:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


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

Репутация: 7
Всего: 386



Sergio, И что, он даже не циклится? smile


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
Sergio
Дата 8.12.2008, 00:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 843
Регистрация: 28.7.2006
Где: Solar System-> Earth

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



ksnk, а какправильно? помоги плз с реализацией
PM MAIL ICQ   Вверх
ksnk
Дата 8.12.2008, 00:46 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


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

Репутация: 7
Всего: 386



Перебор в ширину:

Перед расчетом заводим новый массив 10x10. Прочищаем его нулями.
Занятые и невидимые точки заполняем -1.
Начало помечаем 1
Конец = 1000.

Цикл по N++, от 1-го. {
  Для каждой точки, помеченной N проверяем соседей. {
    Если сосед ==1000 - Нашли.
    Если сосед ==0 - помечаем его N+1
  }
}
Все. В результате 

Можно составлять список из N+1-х элементов для пущей оптимальности. 

Это сообщение отредактировал(а) ksnk - 8.12.2008, 00:53


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
Sergio
  Дата 8.12.2008, 17:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 843
Регистрация: 28.7.2006
Где: Solar System-> Earth

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



ksnk, а можно побробней что это значит?
Цитата

Для каждой точки, помеченной N проверяем соседей

Вот что у меня пока вышло:
Код

bool MoveTo(int fromX, int fromY, int toX, int toY)
{
  int N = 0;
  while(N != 1000)
  {
    //Для каждой точки, помеченной N проверяем соседей.
    {
      if(playfield[fromX+1][fromY].TYPE == 1000) {return true;}
      if(playfield[fromX-1][fromY].TYPE == 1000) {return true;}
      if(playfield[fromX][fromY+1].TYPE == 1000) {return true;}
      if(playfield[fromX][fromY-1].TYPE == 1000) {return true;}

      if(playfield[fromX+1][fromY].TYPE == 0) {N+=1;}
      if(playfield[fromX-1][fromY].TYPE == 0) {N+=1;}
      if(playfield[fromX][fromY+1].TYPE == 0) {N+=1;}
      if(playfield[fromX][fromY-1].TYPE == 0) {N+=1;}
    }
  }
}

Не очень понимаю как это всё должно работать.

Это сообщение отредактировал(а) Sergio - 8.12.2008, 17:32
PM MAIL ICQ   Вверх
maxim1000
Дата 8.12.2008, 18:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Sergio @  8.12.2008,  17:27 Найти цитируемый пост)
playfield[fromX+1][fromY].TYPE

имя TYPE здесь не стоит использовать
лучше что-то типа distance - чтобы понятнее было

я бы посоветовал нарисовать на бумаге в клеточку какое-то поле (с препятствиями) и последовательно найти точки, до которых можно добраться за 1, 2, 3 и т.д. шагов


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


Опытный
**


Профиль
Группа: Участник
Сообщений: 843
Регистрация: 28.7.2006
Где: Solar System-> Earth

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



maxim1000, хорошо учту.
PM MAIL ICQ   Вверх
ksnk
Дата 8.12.2008, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


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

Репутация: 7
Всего: 386



Чего-то типа такого. На С писал давненько, проверить не на чем, может и ашипка-другая попасть...
Чтобы не сочинять массив, можно добавить в основной массив поле TMP, в котором и будем уже рисоваться...

Код

/**
 *  проверить поле.
 *  результат 
 *  -1 можно ходить
 *  0 занята клетка
 *  1000 нашли.     
 */
int chkNeighbour(x,y,N){
  int result =-1;
  if (playfield[x][y].TYPE==1000))
      return 1000 ;
  if (playfield[x][y].TYPE==0) && playfield[x][y].TMP==0) {
      playfield[x][y].TMP=N+1;
      return -1;
  }
  return 0;
}

bool MoveTo(int fromX, int fromY, int toX, int toY)
{
  int x,y;
  // Чистимся
  for (x=0;x<10;x++)  for (y=0;y<10;x++){
    playfield[x][y].TMP =0;  
  };
  
  // А вот тут проставляем стартовую - финишную позицию
  playfield[fromX][fromY].TMP =1;
  playfield[toX][toY].TMP =1000;

  // цикл, для простоты - будем все поле просматривать
  int N = 1;
  int result, minresult=-1;
  while(minresult <0){
      minresult=0;
      for (x=0;x<10;x++)  for (y=0;y<10;x++){
        if (playfield[x][y].TMP==N){
          result =
              chkNeighbour(x+1,y,N)+
              chkNeighbour(x,y+1,N)+
              chkNeighbour(x-1,y,N)+
              chkNeighbour(x,y-1,N) ;
          if(result>0)    
          {  
            // тут надо бы вернутся и сбросить найденную трассу движения
            return true;
          };
          if (result<minresult)
             minresult=result;
        }
      }
      N++;   
  }
  return false;         
}


Неоптимально, понятно, но зато должно работать smile
Чтобы сэкономить на многократном просмотре поля - можно сочинять список клеток, которые помечены N+1 и просматривать уже только его.  

Это сообщение отредактировал(а) ksnk - 8.12.2008, 19:59


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
FinShark
Дата 18.12.2008, 21:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 18.12.2008

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



А зачем вам собственно он нужен, что вы уже задумали?
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

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


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

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


 




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


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

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