Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate a random CGPoint which does not touch a UIView

This is an example view:

enter image description here

I want to calculate a frame with a CGPoint where I can spawn another card(UIView) without touching any existing card. Ofcourse it is optional since the view can be full of cards, therefore there is no free spot.

This is how I can see any card on the screen and my function how it is now:

func freeSpotCalculator() -> CGPoint?{
    var takenSpots = [CGPoint]()
    for card in playableCards{
        takenSpots.append(card.center)
    }

}

I have no idea where to start and how to calculate a random CGPoint on the screen. The random frame has the same width and height as a card in on the screen.

like image 910
J. Doe Avatar asked Aug 09 '17 14:08

J. Doe


1 Answers

The naive approach to this is very simple, but could be problematic once the screen fills up. Generate a random CGPoint with x coordinate between 0 and the screen width and a y coordinate between 0 and the screen height. Check if a rectangle with a center at that point intersects any existing view. If it does not, you have your random position.

Where this gets problematic is when the screen starts to fill up. At that point you could be trying many many random points before finding a place to put the card. You could also reach a situation where no more cards will fit. How do you know that you have reached that? Will your loop generating the random points just run forever?

A smarter solution is to keep track of the free spaces on the screen. Always generate your random points roughly within these free spaces. You could do this using a grid if approximate is close enough. Is there a card occupying each grid location? Then when the largest free space is smaller than the size of your card rectangle, you know you're done. It's a lot more work than the naive approach, but it's faster when the screen starts to fill up and you'll know for sure when you're done.

If you know that you will always have more screen space than the cards can possibly take up, the naive approach is fine.

like image 107
davecom Avatar answered Oct 02 '22 01:10

davecom