If you really want to be βas far apart as possible,β then (1) I bet you're out of luck, and (2) if that were possible, it would probably not produce very random results. But if all you need is βsomewhat far apart,β thatβs not so bad. Here are a few things you can do.
(1) Classify the grid positions according to the parity of their x, y coordinates: that is, whether they are odd and even. Divide the photos into four batches of approximately equal size. Now select from different parties according to the parity of the coordinates. The following code (which is too smart, sorry) does this, modulates errors and typos.
System.Random rng = new System.Random(); for (int x=0; x<nx; ++x) { for (int y=0; y<ny; ++y) { k = ((x&1)<<1) + (y&1); // 0..3 int n_photos_in_batch = (n_photos+3-k) >> 2; int photo_number = (rng.Next(0,n_photos_in_batch-1) << 2) + k; // use this photo } }
Disadvantages: It does nothing to move copies of the photo farther apart than one step. It slightly reduces randomness, since all copies of any photo will be in a fixed subset of positions; in some contexts, it can be visible and look pretty dumb.
Variations: we mainly cover a grid of 2x2 tiles and limit the range of photos allowed for each tile. You could use larger tiles or tiles differently or arrange them differently. For example, if you say k = ((x&1)<<1) ^ (y&3) , you will get 2x2 tiles arranged in a hexagonal pattern, which is actually probably better than the version above.
(2) Move the positions in your grid (a raster order is performed, although there may be better alternatives), and for each choose a photo that (a) is not too close to the position you are looking for at and (b) randomly. The following code (again, modulo errors and typos) does something like this, although for large grids you can make it more efficient.
System.Random rng = new System.Random(); radius = MAX_RADIUS;
Notes: This is much more expensive than option 1. Of course, validation on x1, y1 is useless ineffective here. That is, the choice of radius. The obvious more effective versions of these, however, may break if you accept some of the options that I am going to list. This code, in its current form, will not do anything to save photos from each other if there are less than 9. The choice of radius is actually completely fictitious, for the grid tracing method I use, because no more than 2r ^ 2 + 2r " Excluded "line items again, this may change if you cross the grid in a different order. Etc.
Variations: There is no real reason why the region you are viewing should be square. For example, a circuit might be better. You could, with some extra work, create an area in which there are always as many points as you have photos (although if you do, you will get a mostly periodic picture of the photos, so itβs better to be a little less aggressive). It might be better to process the grid entries in a different position β for example, twisting out of the center.
(3) Option 2 above will keep the photos unique in a certain range (roughly as it may indicate how many different photos you have), but do not care about saving copies further. Instead, you could decide how badly he has two identical photos at any given distance, and then selects the photos to minimize the overall bad state. It will be even more expensive than option 2. I will not write sample code; you can probably decide how to do it.
[EDITED added ...]
(4) Here is a nice variation on the theme of (1). It will work best when the grid is square and its size is 2, but you can adapt it to work more generally. It takes time proportional to the size of your grid, however you have a lot of photos. For each position (x, y): drop everything except the bottom k bits of the coordinates for some k. Bit-reverse them and alternate the bits, giving the number m from 0 to 2 ^ (2k) -1. Choose k so that it is somewhere of the order of, say, n_photos / 4. Now, at position (x, y), you put the photo number in a round (n_photos * m / 2 ^ (2k) + smallish_random_number). There are a few details that I will leave for you to fill out :-).