I have an ArrayList
which contains some Point
objects.
private List<Point> snakeXY = Arrays.asList(new Point(10,5), new Point(11,5), new Point(12,5),new Point(13,5) );
I want to generate a Point
object ( new Point(x, y)
) randomly with x and y between 1 and 30 (exclude) and that is different from any Point
object present in the snakeXY
ArrayList
. For example you can have a Point
object with the values (14,5) or (15,29) or (5,12) but not (12,5) or (13,5) because they are already present in snakeXY
.
I have the feeling that I have to use streams but I don't see how?
I don't really see an alternative to creating a pool of candidate points, which will hold all possible points on the 30x30
grid minus the points already in snakeXY
, and selecting a random point from this pool. You can minimize the cost by using the int
encoding of point position, rather than actually creating Point
objects.
We first build a Set
of point positions to exclude:
List<Point> snakeXY = Arrays.asList(new Point(10,5), new Point(11,5), new Point(12,5),new Point(13,5) );
int min = 2;
int max = 30;
int n = max - min;
Set<Integer> exclude = new HashSet<>();
for(Point p : snakeXY)
exclude.add((p.y-min)*n + (p.x-min));
We then use a list to hold a pool of possible point positions:
List<Integer> pool = new ArrayList<>();
for(int i=0; i<n*n; i++)
if(!exclude.contains(i)) pool.add(i);
Now we simply select a random position from our pool and create the corresponding Point
object:
Random rand = new Random();
int p = rand.nextInt(pool.size());
int pi = pool.get(p);
Point pt = new Point(min + (pi % n), min + (pi / n));
System.out.println(pt);
If we want to generate multiple points we need to remove the selected point position from the pool.
for(int i=0; i<5; i++)
{
int p = rand.nextInt(pool.size());
int pi = pool.remove(p);
Point pt = new Point(min + (pi % n), min + (pi / n));
System.out.println(pt);
}