2017-12-18 479 views
0

我正在製作一個遊戲,其中我有隨機生成的物體。我還有一個表格,其中包含哪些對象彼此接近的數據,比如在200px的範圍內 - 讓我們稱它們爲鄰居。我想要的是生成並分配所有可用對象的座標,以便反映這種關係。我想查看它們的結構。 我做了一個貪婪的算法。這工作非常緩慢。並有時會卡住。有沒有人有更好的方法呢? - 座標可以通過試驗和錯誤動態分配沒有問題。 下面是當前的代碼類。生成與鄰居有關的對象座標

/** 
    * biggest problem 
    * */ 
    public void assignInitialCoords(MyObject[] objects) 
    { 
     objects[0].setxCoor(rand.nextInt(1000)); 
     objects[0].setyCoor(rand.nextInt(1000)); 

     for(int i=0; i<objects.length; i++) 
     { 
      ArrayList<MyObject> neighs = objects[i].getNeighbours(); 
      System.out.println("Assigning " + objects[i].getId() + "'s coors"); 
      setNonNeighborCoords(objects, i); 
      setNeighborCoordinates(objects, i, neighs); 
      System.out.println(objects[i].getId() + "(" + objects[i].getxCoor() + ", " + objects[i].getyCoor() + ")\n"); 
     } 
    } 

的類

import java.util.ArrayList; 
import java.util.HashMap; 

public class MyObject 
{ 
    public ArrayList<MyObject> neighbours; 
    public ArrayList<MyObject> nonNeighbours; 
    public double fov = 360; 
    public double sRange = 100, xCoor, yCoor; 
    boolean isClustered = false; 
    public String id; 
    //Cluster[] clusters; 


    public MyObject() 
    { 
     neighbours = new ArrayList<MyObject>(); 
     nonNeighbours = new ArrayList<MyObject>(); 
    } 

    /** 
    * Find neighbours for this Object given a relations table 
    * example: if a MyObject has id A, and neighbor is B, then the key can be either: A_B or B_A 
    * Both represent the same relation, so we only need to check it once 
    * */ 
    public void findNeighbours(HashMap<String, Integer> table, MyObject[] objects) 
    { 
     for (int i = 0; i < objects.length; i++) 
     { 
      String key1 = getId() + "_" + objects[i].getId(), key2 = objects[i].getId() +"_" + getId(), key=""; 
      if(table.get(key1) != null) 
      { 
       key = key1; 
       if(table.get(key) <= getsRange()) 
        getNeighbours().add(objects[i]); 
      } 
      if(table.get(key2) != null) 
      { 
       key = key2; 
       if(table.get(key) <= getsRange()) 
        getNeighbours().add(objects[i]); 
      } 
     } 
    } 

    /** 
    * Check whether a given Object is the neighbour ArrayList of this object 
    * */ 
    public boolean isInNeighbours(MyObject n) 
    { 
     if(neighbours.equals(null)) { return false; } 
     for(int i=0; i<getNeighbours().size(); i++) 
      if(getNeighbours().get(i).getId().equals(n.getId())) { return true; } 
     return false; 
    } 

    /** 
    * Check whether a given Object is the noneighbour ArrayList of this object 
    * */ 
    public boolean isInNonNeighbours(MyObject n) 
    { 
     if(nonNeighbours.equals(null)) { return false; } 
     for(int i=0; i<getNonNeighbours().size(); i++) 
      if(getNonNeighbours().get(i).getId().equals(n.getId())) { return true; } 
     return false; 
    } 


    /** 
    * Check if given MyObject Can be a neighbour to this Object - for rand coord generation 
    * */ 
    public boolean canBeANeighbour(MyObject n) 
    { 
     return distanceTo(n) <= sRange; 
    } 

    // return Euclidean distance between this and p 
    public double distanceTo(MyObject p) { 
     double dx = this.xCoor - p.xCoor; 
     double dy = this.yCoor - p.yCoor; 
     return Math.sqrt(dx*dx + dy*dy); 
    } 

    //Setters And Getters 
    public ArrayList<MyObject> getNeighbours(){ return neighbours; } 

    public void setNeighbours(ArrayList<MyObject> neighbours) 
    { 
     this.neighbours = neighbours; 
    } 
    public double getFov() 
    { 
     return fov; 
    } 
    public void setFov(double fov) 
    { 
     this.fov = fov; 
    } 
    public double getsRange() 
    { 
     return sRange; 
    } 
    public void setsRange(double sRange) 
    { 
     this.sRange = sRange; 
    } 
    public double getxCoor() 
    { 
     return xCoor; 
    } 
    public void setxCoor(double xCoor) 
    { 
     this.xCoor = xCoor; 
    } 
    public double getyCoor() 
    { 
     return yCoor; 
    } 
    public void setyCoor(double yCoor) 
    { 
     this.yCoor = yCoor; 
    } 
    public boolean isClustered() 
    { 
     return isClustered; 
    } 
    public void setClustered(boolean isClustered) 
    { 
     this.isClustered = isClustered; 
    } 
    public String getId() 
    { 
     return id; 
    } 
    public void setId(String id) 
    { 
     this.id = id; 
    } 

    public ArrayList<MyObject> getNonNeighbours() 
    { 
     return nonNeighbours; 
    } 

    public void setNonNeighbours(ArrayList<MyObject> nonNeighbours) 
    { 
     this.nonNeighbours = nonNeighbours; 
    } 
} 

//樣品測試:

import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.Random; 

public class SampleField 
{ 
    Random rand = new Random(); 
    public int range = 100; 
    HashMap<String, Integer> table = new HashMap<String, Integer>(); 
    String[] nodeIds = {"A", "B", "C", "D", "E", "F"}; 
    public MyObject[] objects = new MyObject[nodeIds.length]; 

    public static void main(String[] args) 
    { 
     SampleField test = new SampleField(); 
     for(MyObject n: test.objects) 
     { 
      n.findNeighbours(test.table, test.objects); 
     } 
     test.populateNonNeighbours(test.objects); 
     System.out.println(test.table); 
     test.printRelationsTable( test.objects); 
     test.assignInitialCoords(test.objects); 
     System.out.println(test.table); 
     test.printRelationsTable( test.objects); 
    } 

    public SampleField() 
    { 
     initialiseNodes(); 
     generateTestTable(objects); 
    } 

    /** 
    * biggest problem 
    * */ 
    public void assignInitialCoords(MyObject[] objects) 
    { 
     objects[0].setxCoor(rand.nextInt(1000)); 
     objects[0].setyCoor(rand.nextInt(1000)); 

     for(int i=0; i<objects.length; i++) 
     { 
      ArrayList<MyObject> neighs = objects[i].getNeighbours(); 
      System.out.println("Assigning " + objects[i].getId() + "'s coors"); 
      setNonNeighborCoords(objects, i); 
      setNeighborCoordinates(objects, i, neighs); 
      System.out.println(objects[i].getId() + "(" + objects[i].getxCoor() + ", " + objects[i].getyCoor() + ")\n"); 
     } 
    } 

    /** 
    * if this object has neighbours, try to set their coordinates so that they do not conflict 
    * 
    * @param objects 
    * @param i 
    * @param neighs 
    */ 
    private void setNeighborCoordinates(MyObject[] objects, int i, ArrayList<MyObject> neighs) 
    { 
     //it should have at least one neighbour 
     if(neighs != null) 
      for(int j=0; j<neighs.size(); j++) 
      { 
       //Initial assignment to the first neighbor 
       neighs.get(j).setxCoor(rand.nextInt() + objects[i].getsRange()); 
       neighs.get(j).setyCoor(rand.nextInt() + objects[i].getsRange()); 
       //If not a neighbor keep generating coordinates until it keeps being a neighbor. 
       while(!objects[i].canBeANeighbour(neighs.get(j)) ) 
       { 
        //go deeper? - later 
        neighs.get(j).setxCoor(rand.nextInt(1000) - shootRange() - 5); 
        neighs.get(j).setyCoor(rand.nextInt(1000) - shootRange() - 5); 
       }        
      } 
    } 

    /** 
    * try to set the coordinates of each object here 
    * @param objects 
    * @param i 
    */ 
    private void setNonNeighborCoords(MyObject[] objects, int i) 
    { 
     for(MyObject n : objects[i].getNonNeighbours()) 
     { 
      n.setxCoor(rand.nextInt() + shootRange() - 5); 
      n.setyCoor(rand.nextInt() + shootRange() - 5); 
       //Make sure non neighbors remain non neighbors 
       while(objects[i].canBeANeighbour(n)) 
       { 
        n.setxCoor(rand.nextInt() + shootRange() - 5); 
        n.setyCoor(rand.nextInt() + shootRange() - 5); 
       } 

     } 
    } 

    /* populate nonNeighbours */ 
    public void populateNonNeighbours(MyObject[] objects) 
    { 
     for(int i=0; i<objects.length; i++) 
     { 
      for(int j=0; j<objects.length; j++) 
      { 
       if((objects[i].getId() != objects[j].getId()) && !objects[i].isInNeighbours(objects[j])) 
       { 
        objects[i].getNonNeighbours().add(objects[j]); 
       } 
      } 
     } 
    } 
    /* Show each object and its neighbors/nonneighbors - just for output */ 
    public void printRelationsTable(MyObject[] objects) 
    { 
     for(int i=0; i<objects.length; i++) 
     { 
      System.out.print("MyObject " + objects[i].getId() + "'s neighbours: "); 
      for(int j=0; j<objects[i].getNeighbours().size(); j++) 
      { 
       System.out.print(objects[i].getNeighbours().get(j).getId() + " "); 
      } 
      System.out.println(); 

      System.out.print("\t\t" +objects[i].getId()+ "' : "); 
      for(int j=0; j<objects[i].getNonNeighbours().size(); j++) 
      { 
       System.out.print(objects[i].getNonNeighbours().get(j).getId() + " "); 
      } 
      System.out.println(); 
     } 
    } 
    /* Initialise Objects here - give basic information */ 
    public void initialiseNodes() 
    { 
     for(int i=0; i<nodeIds.length; i++) 
     { 
      MyObject n = new MyObject(); 
      n.setId(nodeIds[i]); 
      n.setsRange(shootRange()); 
      objects[i] = n; 
     } 
    } 

    /* Generate a list of neighbors for testing */ 
    public void generateTestTable(MyObject[] objects) 
    { 
     for(int i=0; i<objects.length; i++) 
     { 
      /* Get two objects' ids and make them neighbors - ids must be unique */ 
      String firstId = objects[rand.nextInt(objects.length)].getId(); 
      String secondId = objects[rand.nextInt(objects.length)].getId(); 
      while(firstId.equals(secondId) || table.containsKey(firstId + "_" + secondId) || table.containsKey(secondId + "_" + firstId)) 
      { 
       firstId = objects[rand.nextInt(objects.length)].getId(); 
       secondId = objects[rand.nextInt(objects.length)].getId(); 
      } 
      table.put(firstId + "_" + secondId, shootRange()); 
     } 
    } 

    /* Range within which they are neighbors */ 
    public int shootRange() 
    { 
     return range; 
    } 

    public void setRange(int range) 
    { 
     this.range = range; 
    } 
} 
+0

如果您希望我們給您一個改進算法的建議,請在這裏將您的課程與解釋放在一起。剛纔的代碼是不可讀的。 – Gangnus

+0

@Gangnus我也添加了類。 – gordon

回答

0

如果你想比較的距離(如果你正在談論的鄰居,似乎這樣),那麼你根本不需要數數。取而代之的

range = sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)) 
if (range >d)... 

使用

sqrange(a,b) = sqr(a.x-b.x)+sqr(a.y-b.y) 
if (range> d_sqr) ... 

這意味着,你不使用的範圍,但它們的平方。這加快了比較約50倍(雙倍)。所以,你可以使用更簡單的結構。

+0

是的,我在談論鄰居,但在分配座標時,我不想讓一個鄰居給定對象的對象在過程中成爲鄰居。好的。我會很快發佈整個課程。 – gordon

+0

好的,我試過了,但性能仍然沒有明顯改變。 – gordon

+0

你已經停止使用sqrt並且沒有發現變化?對不起,那是不可能的。或者你在其他地方遇到了很多問題。 – Gangnus