2012-06-23 3 views
0

ОК Я пытаюсь создать динамическую систему движения, чтобы игрок мог перемещаться из точки A в точку B без предопределенных путей. Обратите внимание, что эта игра не содержит графики на графике. Игрок может двигаться в 10 направлениях: вверх, вниз, n, e, s, w, sw, se, nw и ne.Проблемы с поиском

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

Map Number, Room Number, Direction_N, Direction_S, Direction_E, Direction_W, etc. 
    1   1   1/3   1/100  1/1381  1/101 

Direction_N указывает, что он идет к карте 1 номер 3, Direction_S Карта 1 номер 100, и т.д ...

Ok, я переработал код с предложениями (спасибо вам, ребята, кстати !) здесь переработан код. Кажется, теперь они находят комнаты, даже огромные расстояния! Но теперь проблема заключается в нахождении кратчайшего пути к месту назначения, я пробовал обход коллекции, но путь не выходит правильно ...

На картинке ниже, у меня есть начальная точка на красной площади в центре и остановка на красном квадрате в верхнем левом углу. Это возвращает visitStartRooms = 103 и visitStopRooms = 86, когда это всего лишь 16 номеров. Окунитесь в мою недостающую часть головоломки, я не уверен, как разобраться в комнатах в этой коллекции, чтобы получить истинный самый короткий маршрут.

Example of map

Вот новый код

 public void findRoute(ROOM_INFO startRoom, ROOM_INFO destinationRoom) 
    { 
     Dictionary<ROOM_INFO, bool> visitedStartRooms = new Dictionary<ROOM_INFO, bool>(); 
     Dictionary<ROOM_INFO, bool> visitedStopRooms = new Dictionary<ROOM_INFO, bool>(); 

     List<string> directions = new List<string>(); 


     startQueue.Enqueue(startRoom); // Queue up the initial room 
     destinationQueue.Enqueue(destinationRoom); 

     visitedStartRooms.Add(startRoom, true);// say we have been there, done that 
     visitedStopRooms.Add(destinationRoom, true); 

     string direction = ""; 
     bool foundRoom = false; 

     while (startQueue.Count != 0 || destinationQueue.Count != 0) 
     { 

      ROOM_INFO currentStartRoom = startQueue.Dequeue(); // remove room from queue to check out. 
      ROOM_INFO currentDestinationRoom = destinationQueue.Dequeue(); 

      ROOM_INFO startNextRoom = new ROOM_INFO(); 
      ROOM_INFO stopNextRoom = new ROOM_INFO(); 

      if (currentStartRoom.Equals(destinationRoom)) 
      { 
       break; 
      } 
      else 
      { 
       // Start from destination and work to Start Point. 
       foreach (string exit in currentDestinationRoom.exitData) 
       { 

        stopNextRoom = extractMapRoom(exit); // get adjacent room 
        if (stopNextRoom.Equals(startRoom)) 
        { 
         visitedStopRooms.Add(stopNextRoom, true); 
         foundRoom = true; 
         break; 
        } 

        if (stopNextRoom.mapNumber != 0 && stopNextRoom.roomNumber != 0) 
        { 
         if (!visitedStopRooms.ContainsKey(stopNextRoom)) 
         { 
          if (visitedStartRooms.ContainsKey(stopNextRoom)) 
          { 
           foundRoom = true; 
          } 
          else 
          { 
           destinationQueue.Enqueue(stopNextRoom); 
           visitedStopRooms.Add(stopNextRoom, true); 
          } 
         } 
        } 
       } 

       if (foundRoom) 
       { 
        break; 
       } 
      } 

      // start from the start and work way to destination point 
      foreach (string exit in currentStartRoom.exitData) 
      { 

       startNextRoom = extractMapRoom(exit); // get adjacent room 
       if (startNextRoom.Equals(destinationRoom)) 
       { 
        visitedStartRooms.Add(startNextRoom, true); 
        foundRoom = true; 
        break; 
       } 
       if (startNextRoom.mapNumber != 0 && startNextRoom.roomNumber != 0) 
       { 
        if (!visitedStartRooms.ContainsKey(startNextRoom)) 
        { 
         if (visitedStopRooms.ContainsKey(startNextRoom)) 
         { 
          foundRoom = true; 
          break; 
         } 
         else 
         { 

          startQueue.Enqueue(startNextRoom); 
          visitedStartRooms.Add(startNextRoom, true); 
         } 

        } 
       } 
      } 


      if (foundRoom) 
      { 
       break; 
      } 
     } 

    } 
+0

Проблема в вашем алгоритме заключается в том, что вы используете очередь, чтобы увидеть, посетили ли вы комнату. Но если вы посетили комнату, которая была удалена, вы подумаете, что еще не посетили ее, и поэтому вы потратите много времени на повторную поиск уже пройденных путей. Это может быть связано с тем, что производительность настолько быстро ухудшается для больших расстояний. – hatchet

ответ

1

У вас есть хороший старт. Есть несколько основных улучшений, которые помогут. Во-первых, чтобы восстановить свой путь, вы должны создать новую структуру данных для хранения посещенных комнат. Но для каждой записи вы хотите сохранить комнату, а также предыдущую комнату на пути назад к начальной точке. Хорошей структурой данных для этого будет словарь, в котором ключ является идентификатором комнаты, а значением является предыдущий идентификатор комнаты. Чтобы узнать, посетили ли вы комнату, вы посмотрите, существует ли она в этой структуре данных, а не в вашей очереди openList. С помощью этой новой структуры вы можете правильно проверить, посетили ли вы комнату, и вы можете восстановить путь назад, повторно просматривая предыдущую комнату в той же структуре, пока не дойдете до источника.

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

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

Shortest path (fewest nodes) for unweighted graph

http://en.wikipedia.org/wiki/Shortest_path_problem

Вы также можете быть заинтересованы в A * алгоритм, который использует другой подход. Он использует hueristic подход для сосредоточения поиска в подмножестве пространства решений, более вероятно, содержит кратчайший путь. http://en.wikipedia.org/wiki/A%2a_search_algorithm Но A *, вероятно, будет излишним в вашем случае, так как вес всех краев одинаковый между всеми комнатами.

Смежные вопросы