2016-12-23 11 views
1

Ниже код сгенерировал и сохранил позицию x y в HashMap и проверил столкновение двух кругов;Холст Android. Как установить круги в случайном положении?

 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; 
        } 

       } 
      } 

     } 

Этот код работает только в том случае, если количество циклов = 2; Но когда число круга> 2 i имеет столкновение; Как проверить текущую сгенерированную позицию для каждого в HashMap?

Например: XPOS = {5, 10, 3} YPOS = {10, 33, 5}

генерируется положение х = 6, у = 10; вычислить расстояние между x = 6, y = 10 со всеми позициями в Map. Если расстояние < радиус + радиус создает новое положение при расстоянии радиуса + радиуса;

Update ========================>

Мой код работать как enter image description here

Я хочу, как этот

enter image description here

выход: расстояние между текущей сгенерированной позицией (X, Y) и предыдущей позицией (X, Y). Я хочу проверить между текущими генерируемыми x, y со всеми добавленными позициями в HashMap.

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.s Извините, что плохой английский.

+0

Почему х/у 'float', когда они рассчитываются как' int' первоначально (случайным)? И вы усекаете это странным образом, в крайнем случае вы можете положить «x» в крошечный бит за пределы «width». ('width: 400, raduis: 1 -> nextInt (400) -> 399 -> 399 + 0.5f = 399.5f' выходит из диапазона [r/2, 399]) ... Я думаю, вы действительно хотели' x = nextInt (ширина - радиус) + радиус * 0,5f', который будет производить случайные числа в диапазоне [r/2, width-r/2]. Также вы можете объяснить, почему 'if (! PosX.containsValue (x) &&! PosY.containsValue (y)) {'? Таким образом, ни один круг не может иметь одинаковое положение x или y в любом круге? – Ped7g

+0

Итак, вы пытались использовать мой ответ, или что такое статус этого Q? – Ped7g

ответ

0

Возможно, что-то ближе к этому будет работать? Я не совсем уверен, что это то, что вы хотите, или если это поможет, но я быстро переписал для ясности.

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

Тай для повтора. Хотя никогда не заканчивается. –

0

Мой вариант. Вам не нужно делать sqrt для сравнения расстояния, вместо этого вы можете скомпоновать константу (d2 в моем случае).

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

Я решаю, как этот

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;', например с 'width = 1000, radius = 99', будет выдавать значения от' 49,5' до '999,5' (так что если координаты экрана от '0' до' 999', вы можете получить центр круга вне пространства экрана). – Ped7g