2016-12-23 5 views
1

Unter Code generiert und speichern Position x y HashMap und überprüfen Sie die Kollision zwei Kreise;Android-Leinwand. Wie setze ich Kreise auf zufällige Position?

 HashMap<Integer, Float> posX = new HashMap<>(); 
     HashMap<Integer, Float> posY = new HashMap<>(); 

     int numberOfCircle = 8; 

     for(int i=0; i < numberOfCircle; i ++){ 

      // boolean flag = false; 
      while (true){ 

       float x =random.nextInt(width - raduis/2) + raduis/2f; 
       float y =random.nextInt(height - raduis/2) + raduis/2f; 

       if(!posX.containsValue(x) && !posY.containsValue(y)){ 

        if(i == 0){ 

         posX.put(i, x); 
         posY.put(i, y); 
         break; 
        } 
        if(i > 0){ 

         double distance = Math.sqrt(((posX.get(i - 1) - x) * (posX.get(i - 1) - x)) + ((posY.get(i - 1) - y) * (posY.get(i - 1) - y))); 

         if (distance > raduis+raduis) { 

          posX.put(i, x); 
          posY.put(i, y); 
          Log.d(TAG, i + " xPos=" + posX.get(i) + " yPos=" + posY.get(i) + " distance=" + distance); 
          break; 
         } 

         if(numberOfCircle == posX.size()) break; 
        } 

       } 
      } 

     } 

Dieser Code funktioniert nur, wenn Kreisanzahl = 2; Aber wenn ein Kreis> 2 zählt, habe ich eine Kollision; Wie kann ich die aktuelle Position in HashMap überprüfen?

Zum Beispiel: xPos = {5, 10, 3} yPos = {10, 33, 5}

erzeugt Position x = 6, y = 10; Berechnen Sie den Abstand zwischen x = 6, y = 10 mit allen Positionen in Map. Wenn der Abstand < Radius + Radius eine neue Position erzeugt, während die Entfernung> Radius + Radius ist;

aktualisieren ========================>

Mein Code Arbeit wie enter image description here

Ich möchte ähnliche

enter image description here

Ausgabe: Abstand zwischen aktuell erzeugter Position (X, Y) und vorheriger Position (X, Y). Ich möchte prüfen, ob die generierten x, y mit allen hinzugefügten Positionen in HashMap generiert wurden.

D/DEBUG DATA ===>: 1 xPos=432.0 yPos=411.0 distance=390.6430595825299 
D/DEBUG DATA ===>: 2 xPos=316.0 yPos=666.0 distance=280.1446055165082 
D/DEBUG DATA ===>: 3 xPos=244.0 yPos=83.0 distance=587.4291446634223 
D/DEBUG DATA ===>: 4 xPos=214.0 yPos=551.0 distance=468.96055271205915 
D/DEBUG DATA ===>: 5 xPos=76.0 yPos=1011.0 distance=480.2540994098853 
D/DEBUG DATA ===>: 6 xPos=289.0 yPos=868.0 distance=256.55019002136794 
D/DEBUG DATA ===>: 7 xPos=494.0 yPos=988.0 distance=237.53947040439405 

P. Sorry, so schlecht Englisch.

+0

Warum sind x/y 'float', wenn sie als' int' berechnet werden zunächst (durch gelegentliches)? Und Sie schneiden das auf seltsame Weise ab, Sie können im Extremfall mit 'x' ein kleines bisschen hinter" width "enden. ('width: 400, raduis: 1 -> nextInt (400) -> 399 -> 399 + 0.5f = 399.5f' ist außerhalb von [r/2, 399] range) ... Ich denke du wolltest' x = nextInt (Breite - Radius) + Radius * 0.5f', die im Bereich [r/2, Breite-r/2] Zufallszahlen erzeugt. Kannst du auch erklären warum 'if (! PosX.containsValue (x) &&! PosY.containsValue (y)) {'? Also kann kein Kreis eine identische x- oder y-Position zu irgendeinem anderen Kreis haben? – Ped7g

+0

Also hast du versucht, meine Antwort zu verwenden, oder was ist der Status dieses Q? – Ped7g

Antwort

0

Vielleicht etwas näher daran wird funktionieren? Ich bin mir nicht ganz sicher, ob es das ist, was du willst oder ob es helfen wird, aber ich habe es aus Gründen der Klarheit umgeschrieben.

HashMap<Integer, Integer> posX = new HashMap<>(); 
HashMap<Integer, Integer> posY = new HashMap<>(); 

final int circlesToPlace = 8; 

for(int i = 0 ; i < circlesToPlace ; i++){ 

    // boolean flag = false; 
    while (true){ 
     final int x = ThreadLocalRandom.current().nextInt((radius/2f), width + 1); 
     final int y = ThreadLocalRandom.current().nextInt((radius/2f), height + 1); 

     // Iterate over all other positions to ensure no circle intersects with 
     // the new circle. 
     for (int index = 0 ; index < posX.size() ; index++) { 
      // Calculate distance where d = sqrt((x2 - x1)^2 + (y2 - y1)^2) 
      final int otherX = posX.get(index); 
      final int otherY = posY.get(index); 

      int differenceX = otherX - x; 
      differenceX *= differenceX; 

      int differenceY = otherY - y; 
      differenceY *= differenceY; 

      final double distance = Math.sqrt(differenceX + differenceY); 


      if (distance > (radius * 2)) { 
       posX.put(i, x); 
       posY.put(i, y); 
       Log.d(TAG, i + " xPos=" + posX.get(i) + " yPos=" + posY.get(i) + " distance=" + distance); 
       break; 
      } 
     } 
    } 
} 
+0

Ty für die Wiedergabe. Während nie enden. –

0

Meine Variante. Sie müssen nicht sqrt tun, um die Entfernung zu vergleichen, stattdessen können Sie die Konstante quadrieren (d2 in meinem Fall).

Random random = new Random(); 
    int numberOfCircle = 8, width = 400, height = 300; 
    int diameter = 51; 
    final float radius = diameter * 0.5f; 
    final float d2 = diameter * diameter; 

    List<Float> posX = new ArrayList<>(numberOfCircle); 
    List<Float> posY = new ArrayList<>(numberOfCircle); 

    while (posX.size() < numberOfCircle) { // till enough generated 

     // generate new coordinates 
     float x = random.nextInt(width - diameter) + radius; 
     float y = random.nextInt(height - diameter) + radius; 

     System.out.printf("Generated [%3.3f, %3.3f] ... ", x, y); 

     // verify it does not overlap/touch with previous circles 
     int j = 0; 
     while (j < posX.size()) { 
      float dx = posX.get(j) - x, dy = posY.get(j) - y; 
      float diffSquare = (dx * dx) + (dy * dy); 
      if (diffSquare <= d2) break; 
      ++j; 
     } 

     // generate another pair of coordinates, if it does touch previous 
     if (j != posX.size()) { 
      System.out.println("collided."); 
      continue; 
     } 
     System.out.println("added."); 

     // not overlapping/touch, add as new circle 
     posX.add(x); 
     posY.add(y); 
    } // while (posX.size() < numberOfCircle) 
0

Ich nehme mir vor, wie dieses

private class MyView extends View implements View.OnTouchListener{ 

    List<Circle> randomCircles = new ArrayList<>(); 
    int radius = new Circle().getRadius(); 
    int randomCircleCount = 3; 
    Random random = new Random(); 

    public MyView(Context context) { 
     super(context); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 

     //Integer width = canvas.getWidth(); 
     Integer width = canvas.getWidth(); 
     Integer height = canvas.getHeight() - (radius); 
     // Integer height = canvas.getHeight()/2 + canvas.getHeight(); 

     ///randomCircles.clear(); 

     Paint paint = new Paint(); 
     paint.setStyle(Paint.Style.FILL); 
     paint.setColor(Color.BLACK); 
     canvas.drawPaint(paint); 

     Paint paintT = new Paint(); 
     paintT.setTextSize(18f); 
     paintT.setAntiAlias(true); 
     paintT.setTextAlign(Paint.Align.CENTER); 

     while(randomCircles.size() < randomCircleCount){ 
      randomCircle(width, height); 
     } 

     for(int i=0; i < randomCircleCount; i ++){ 

      Circle circle = randomCircles.get(i); 

      float curPosX = randomCircles.get(i).getCx().floatValue(); 
      float curPosY = randomCircles.get(i).getCy().floatValue(); 

      int r = random.nextInt(256); 
      int g = random.nextInt(256); 
      int b = random.nextInt(256); 

      paint.setARGB(175, 77, 2, 200); 
      //if(r != 0 && g != 0 && b != 0) paint.setARGB(255, r, g, b); 


      canvas.drawCircle(curPosX, curPosY, radius, paint); 
      Rect bounds = new Rect(); 
      String text = "" +i; 
      paintT.getTextBounds(text, 0, text.length(), bounds); 

      paint.setAntiAlias(true); 
      canvas.drawText(text, curPosX, curPosY, paintT); 

      circle.update(width, height); 
      //Log.d(TAG, "REDRAW"); 
     } 

     ///invalidate(); 
     postInvalidateDelayed(100); 

    } 

    private void randomCircle(int width, int height) { 

     double x = getPosX(width, radius); 
     double y = getPosY(height,radius); 


     boolean hit = false; 
     for (int i = 0; i < randomCircles.size(); i++) { 

      Circle circle = randomCircles.get(i); 

      double dx = circle.getCx() - x; 
      double dy = circle.getCy() - y; 

      int r = circle.getRadius() + radius; 
      if (dx * dx + dy * dy <= r * r) { 
       Log.d(TAG, "dx=" + dx + " dy=" + dy); 
       hit = true; 
      } 
     } 

     if (!hit) { 

      Log.d(TAG, "Here!!!!!"); 
      randomCircles.add(new Circle(x, y)); 
     } 

    } 

private Float getPosX(Integer width, Integer radius){ 
     return random.nextInt(width - radius/2) + radius/2f; 
    } 
    private Float getPosY(Integer height, Integer radius){ 
     return random.nextInt(height - radius/2) + radius/2f; 
    } 
+0

'random.nextInt (width - radius/2) + radius/2f;', zum Beispiel mit 'width = 1000, radius = 99', ergibt Werte von' 49.5' bis '999.5' (also wenn Bildschirmkoordinaten von "0" bis "999", Sie können die Kreismitte außerhalb des Bildschirmbereichs erhalten. – Ped7g

Verwandte Themen