c# - Randomly generate blocks on a flat map -


i'm trying randomly generate blocks on flat map , make don't overlap each other. have made matrix (c# array) of size of map (500x500), blocks have scale between 1 , 5. code works if generated block overlaps one, destroyed , not regenerated somewhere else.

only around 80 of 1000 blocks try generate don't overlap block.

here picture of map around 80 blocks generated, green squares blocks

map

void generateelement(int ratio, int minscale, int maxscale, gameobject g) {     bool elementfound = false;     (int = 0; < ratio * generationdefault; i++) {         gameobject el;         // randomly generate block size , position         int size = random.range(minscale, maxscale + 1);         int x = random.range(0, mapsizex + 1 - size);         int y = random.range(0, mapsizey + 1 - size);          // check if there element          (int j = x; j < x + size; j++)             (int k = y; k < y + size; k++)                 if (map[j][k] != null)                     elementfound = true;         if (elementfound)             continue;         else {             el = (gameobject)instantiate(g, new vector3(x + (float)size / 2, (float)size / 2, y + (float)size / 2), quaternion.euler(0, 0, 0));             el.transform.localscale *= size;         }         // create element on map array         (int j = x; j < x + size; j++)             (int k = y; k < y + size; k++)                   if (map[j][k] == null) {                     map[j][k] = el.getcomponent<objectinterface>();                 }     } } 

i thought of 3 possible fixes

  • i should set size of block depending of place has.
  • i should use randomization algorithm.
  • i'm not doing right.

what think best idea ?


update

i got code working better. try instantiate blocks multiple times if needed (maximum 5 moment) , fixed bugs. if there many elements on map, not instantiated , that's wanted, have find right amount of times try instantiate block.

i tried instantiating 1280 elements on 500x500 map. takes 1.5 second , instantiated 1278/1280 blocks (99.843%).

enter image description here

void generateelement(int ratio, int minscale, int maxscale, gameobject g) { bool elementfound = false; int cnt = 0; // generate every block (int = 0; < ratio * generationdefault; i++) {     gameobject el = null;     // randomly generate block size , position     int size, x, y, trycnt = 0;      // try maximum 5 times generate block     {         elementfound = false;         // randomly set block size , position         size = random.range(minscale, maxscale + 1);         x = random.range(0, mapsizex + 1 - size);         y = random.range(0, mapsizey + 1 - size);          // check if there element          (int j = x; j < x + size; j++)             (int k = y; k < y + size; k++)                 if (map[j][k] != null)                     elementfound = true;         trycnt++;     } while (elementfound && trycnt < 5);     if (trycnt >= 5 && elementfound) continue;      // instantiate block     el = (gameobject)instantiate(g, new vector3(x + (float)size / 2, (float)size / 2, y + (float)size / 2), quaternion.euler(0, 0, 0));     el.transform.localscale *= size;     // create element on map array     (int j = x; j < x + size; j++)         (int k = y; k < y + size; k++)               if (map[j][k] == null) {                 map[j][k] = el.getcomponent<objectinterface>();             }     cnt++; } print("instantiated " + cnt + "/" + ratio * generationdefault); 

}

this incredibly difficult well.

here's quick solution you'll maybe ... depending on scene.

actualwidth = 500 //or whatever. assume here square // blocks 5 size chunkwidth = actualwidth / 5 // goes without saying, here int kchunks = chunkwidth*chunkwidth list<int> shuf = enumerable.range(1,kchunks).orderby(r=>random.value).tolist(); howmanywanted = 1000 shuf = shuf.take(howmanywanted) foreach( in shuf )    x = % actualwidth    y = / actualwidth    make block @ x y    put block in list allblocks 

however ............


...... you'll see looks kind of "regular", this:

just randomly perturb blocks. remember, video game programming clever tricks!

ideally, have start middle , work way out; in event can't them in line. shuffling ok. so, ..

   harmonic = 3  //for example. try different values     function rh = random.range(1,harmonic) (that's 1 not 0)     function rhposneg        n = rh        n = either +n or -n        return n     function oneperturbation    {    allblocks = allblocks.orderby(r => random.value) //essential    foreach b in allblocks       newpotentialposition = vector2(rhposneg,rhposneg)       possible = function check if possible            have block @ newpotentialposition,            careful not check "yourself"       if possible, move block newpotentialposition    } 

the simplest approach run oneperturbation, say, 3 times. have @ between each run. try different values of harmonic tuning factor.

there many ways perturb fields of differently-sized blocks, above kiss solution looks situation.


coding note...

how sets of unique random numbers.

just explain line of code...

list<int> shuf = enumerable.range(1,kchunks).orderby(r=>random.value).tolist(); 

if new coding: want this: "get hundred random numbers, 1 million, no repeats".

fortunately, very known problem very simple solution.

the way numbers no repeats, shuffle numbers, , take how many want off top.

for example, need random couple of numbers 1-10 no repeats.

so, here's numbers 1-10 shuffled: 3,8,6,1,2,7,10,9,4,5

simply take need off front: so, 3, 8, 6 etc.

so make example let's want twelve numbers, no repeats, 1 through 75. first problem is, want list numbers 75, shuffled. in fact ..

list<int> shuf = enumerable.range(1,75).orderby(r=>random.value).tolist(); 

so list 75 items long. can check saying foreach(int r in shuf) debug.log(r);. next in example want 12 of numbers. fortunately there's list call this:

shuf = shuf.take(12) 

so, that's - have 12 numbers, no repeats, random between 1 , 75. again can check foreach(int r in shuf) debug.log(r);

in short, when want "n" numbers, no repeats, between 1 , max, have this:

list<int> shuf = enumerable.range(1,max).orderby(r=>random.value).tolist(); shuf = shuf.take(n); 

et voilĂ , can check result foreach(int r in shuf) debug.log(r);

i explain @ length because question asked "how random numbers unique". "age-old" programming trick , answer shuffle array of integers involved.

interestingly, if google question ("how random numbers unique") it's 1 of rare occasions google not help, because: whenever question asked, plethora of keen new programmers (who have not heard simple trick properly!!) writing out huge long complicated ideas, leading further confusion , complication.

so that's how make random numbers no repeats, fortunately trivial.


Comments

Popular posts from this blog

sublimetext3 - what keyboard shortcut is to comment/uncomment for this script tag in sublime -

java - No use of nillable="0" in SOAP Webservice -

ubuntu - Laravel 5.2 quickstart guide gives Not Found Error -