2012-04-02 11 views
5

कुछ घंटों के लिए डिबगिंग के बाद, एल्गोरिदम काम कर रहा प्रतीत होता है। यह जांचने के लिए कि यह काम करता है या नहीं, जब मैं लूप छोड़ता हूं तो मैं वर्तमान नोड स्थिति में एंड नोड स्थिति की जांच कर रहा हूं। अब तक मूल्य सही दिखते हैं। समस्या यह है कि, मैं एनपीसी से जितना दूर हूं, जो वर्तमान स्थिर है, प्रदर्शन खराब हो जाता है। यह उस बिंदु पर जाता है जहां गेम 10 एफपीएस से कम नामुमकिन है। मेरा वर्तमान पथग्राफ 2500 नोड्स है, जो मुझे विश्वास है कि बहुत छोटा है, है ना? प्रदर्शन में सुधार करने के तरीके पर कोई विचार?ए * पथदर्शी खराब प्रदर्शन

struct Node 
{ 
    bool walkable;  //Whether this node is blocked or open 
    vect2 position;  //The tile's position on the map in pixels 
    int xIndex, yIndex; //The index values of the tile in the array 
    Node*[4] connections; //An array of pointers to nodes this current node connects to 
    Node* parent; 
    int gScore; 
    int hScore; 
    int fScore; 
} 

class AStar 
{ 
    private: 
    SList!Node openList; //List of nodes who have been visited, with F scores but not processed 
    SList!Node closedList; //List of nodes who have had their connections processed 

    //Node*[4] connections;  //The connections of the current node; 

    Node currentNode;   //The current node being processed 

    Node[] Path;  //The path found; 

    const int connectionCost = 10; 

    Node start, end; 

////////////////////////////////////////////////////////// 

    void AddToList(ref SList!Node list, ref Node node) 
    { 
     list.insert(node); 
    } 

    void RemoveFrom(ref SList!Node list, ref Node node) 
    { 
     foreach(elem; list) 
     { 
      if(node.xIndex == elem.xIndex && node.yIndex == elem.yIndex) 
      { 
       auto a = find(list[] , elem); 
       list.linearRemove(take(a, 1)); 
      } 
     } 
    } 


    bool IsInList(SList!Node list, ref Node node) 
    { 
     foreach(elem; list) 
     { 
      if(node.xIndex == elem.xIndex && node.yIndex == elem.yIndex) 
       return true; 
     } 

     return false; 
    } 

    void ClearList(SList!Node list) 
    { 
     list.clear; 
    } 

    void SetParentNode(ref Node parent, ref Node child) 
    { 
     child.parent = &parent; 
    } 

    void SetStartAndEndNode(vect2 vStart, vect2 vEnd, Node[] PathGraph) 
    { 
     int startXIndex, startYIndex; 
     int endXIndex, endYIndex; 

     startXIndex = cast(int)(vStart.x/32); 
     startYIndex = cast(int)(vStart.y/32); 

     endXIndex = cast(int)(vEnd.x/32); 
     endYIndex = cast(int)(vEnd.y/32); 

     foreach(node; PathGraph) 
     { 
      if(node.xIndex == startXIndex && node.yIndex == startYIndex) 
      { 
       start = node; 
      } 
      if(node.xIndex == endXIndex && node.yIndex == endYIndex) 
      { 
       end = node; 
      } 
     } 
    } 

    void SetStartScores(ref Node start) 
    { 
     start.gScore = 0; 

     start.hScore = CalculateHScore(start, end); 

     start.fScore = CalculateFScore(start); 

    } 

    Node GetLowestFScore() 
    { 
     Node lowest; 

     lowest.fScore = 10000; 

     foreach(elem; openList) 
     { 
      if(elem.fScore < lowest.fScore) 
       lowest = elem; 
     } 

     return lowest; 
    } 

    //This function current sets the program into an infinite loop 
    //I still need to debug to figure out why the parent nodes aren't correct 
    void GeneratePath() 
    { 
     while(currentNode.position != start.position) 
     { 
      Path ~= currentNode; 
      currentNode = *currentNode.parent; 
     } 
    } 

    void ReversePath() 
    { 
     Node[] temp; 
     for(int i = Path.length - 1; i >= 0; i--) 
     { 
      temp ~= Path[i]; 
     } 
     Path = temp.dup; 
    } 

    public: 
    //@FIXME It seems to find the path, but now performance is terrible 
    void FindPath(vect2 vStart, vect2 vEnd, Node[] PathGraph) 
    { 
     openList.clear; 
     closedList.clear; 

     SetStartAndEndNode(vStart, vEnd, PathGraph); 
     SetStartScores(start); 
     AddToList(openList, start); 

     while(currentNode.position != end.position) 
     { 
      currentNode = GetLowestFScore(); 

      if(currentNode.position == end.position) 
       break; 
      else 
      { 
       RemoveFrom(openList, currentNode); 
       AddToList(closedList, currentNode); 

       for(int i = 0; i < currentNode.connections.length; i++) 
       { 
        if(currentNode.connections[i] is null) 
         continue; 
        else 
        { 
         if(IsInList(closedList, *currentNode.connections[i]) 
          && currentNode.gScore < currentNode.connections[i].gScore) 
         { 
          currentNode.connections[i].gScore = currentNode.gScore + connectionCost; 
           currentNode.connections[i].hScore = abs(currentNode.connections[i].xIndex - end.xIndex) 
          + abs( currentNode.connections[i].yIndex - end.yIndex); 
          currentNode.connections[i].fScore =  currentNode.connections[i].gScore + currentNode.connections[i].hScore; 
          currentNode.connections[i].parent = &currentNode; 
         } 
         else if(IsInList(openList, *currentNode.connections[i]) 
           && currentNode.gScore < currentNode.connections[i].gScore) 
         { 
          currentNode.connections[i].gScore = currentNode.gScore + connectionCost; 
          currentNode.connections[i].hScore = abs(currentNode.connections[i].xIndex - end.xIndex) 
          + abs( currentNode.connections[i].yIndex - end.yIndex); 
          currentNode.connections[i].fScore = currentNode.connections[i].gScore + currentNode.connections[i].hScore; 
          currentNode.connections[i].parent = &currentNode; 
         } 
         else 
         { 

          currentNode.connections[i].gScore = currentNode.gScore + connectionCost; 
          currentNode.connections[i].hScore = abs(currentNode.connections[i].xIndex - end.xIndex) 
          + abs(currentNode.connections[i].yIndex - end.yIndex); 
          currentNode.connections[i].fScore = currentNode.connections[i].gScore +  currentNode.connections[i].hScore; 
          currentNode.connections[i].parent = &currentNode; 
          AddToList(openList, *currentNode.connections[i]); 
         } 
        } 
       } 
      } 
     } 

     writeln("Current Node Position: ", currentNode.position); 
     writeln("End Node Position: ", end.position); 

     if(currentNode.position == end.position) 
     { 
      writeln("Current Node Parent: ", currentNode.parent); 
      //GeneratePath(); 
      //ReversePath(); 
     } 
    } 

    Node[] GetPath() 
    { 
     return Path; 
    } 
} 
+0

तुम क्यों नोड * के बजाय सूचियों के लिए नोड प्रयोग करते हैं? – Trass3r

उत्तर

7

आप दोनों "खुला सूची" और "बंद सूची" के लिए अकेले लिंक्ड सूचियों का उपयोग कर रहे हैं, अनावश्यक रैखिक समय संचालन के लिए अग्रणी।

पूर्व एक priority queue (heap) होना चाहिए, जबकि बाद सबसे अच्छा एक हैश तालिका के रूप में कार्यान्वित किया जाता है।

+0

ठीक है, मैंने बहुत कम पाया है कि एक मिनी-ढेर कैसे सेट अप करें, हालांकि, मुझे यकीन नहीं है कि हैश टेबल कैसे सेट करें। मुझे लगता है कि मेरा एकमात्र विकल्प एक सहयोगी सरणी है, और जिस से मैंने पढ़ा है, यही हैश है कि टेबल है। इस मामले में हैश/कुंजी मूल्य क्या होगा? – RedShft

+0

@RedShft: चूंकि आप एक सेट के रूप में एसोसिएटिव सरणी का उपयोग करने जा रहे हैं, केवल चाबियां हैं, कोई मान नहीं है। उन तत्वों का उपयोग करें जिन्हें आप अब अपनी सूची में कुंजी के रूप में संग्रहीत कर रहे हैं और एक डमी मान का उपयोग करें, उदा। 'TRUE'। –

2

शुरुआत

के लिए अपने डेटा संरचना के रूप में एक अवर्गीकृत लिंक्ड सूची का उपयोग कर

ए * एक लॉग (एन) यह एक min heap

पर ठीक से

जांच काम करने के लिए पॉप और अद्यतन नोड डालने पर निर्भर करता है

0

एरिक Lippert के ए को लागू करने में * एल्गोरिथ्म, मैं कोई प्रत्यक्ष समय अंतर को लागू करने के बीच पाया एक HashSet <> (साथ साथ बंद कर दिया हैश एल्गोरिथ्म retu आरएन एक्स < < 16^वाई) या बूल [चौड़ाई, ऊंचाई]

मैं ~ 40% एरिक के PrioirtyQueue <> एक हाथ से लुढ़का MinHeap <> साथ (SortedDIctionary <> का उपयोग करके लागू) की जगह प्रदर्शन में सुधार करने में सक्षम था। यह ~ 420x750 हेक्स के युद्ध-खेल मानचित्र के लिए था, जो नक्शे के कुछ लंबे विकर्ण पथों को मापता था।

संबंधित मुद्दे