- Home /
[Solved] How to get non repeating random positions?
[EDITED] Have to random 16 cubes and my concern is that each should be placed at a unique position.......means each cube should having (x,y,z) unique so no over placing on one position.......just the way the cards shuffled in the game of poker or cube shuffled in Sliding picture puzzle......sorry for the bad English......and Thanks in advance.....i am using c#,so help in C# will be much Helpful.....Thanks Again.....[Edited]....... recently my cube's position starts from (1,4,10),(2,4,10),(3,4,10),(4,4,10).....(1,3,10),(2,3,10),(3,3,10),(4,3,10).......so on.... and i have to make the position of cubes to random.....and not repeating.....
using UnityEngine;
using System.Collections;
public class Random_Object : MonoBehaviour
{
public GameObject cube1;
public GameObject cube2;
public GameObject cube3;
public GameObject cube4;
public GameObject cube5;
public GameObject cube6;
public GameObject cube7;
public GameObject cube8;
public GameObject cube9;
public GameObject cube10;
public GameObject cube11;
public GameObject cube12;
public GameObject cube13;
public GameObject cube14;
public GameObject cube15;
void Start ()
{
ChangePosition();
}
public void ChangePosition()
{
cube1.transform.position = new Vector3(Random.Range (1,4),Random.Range (1,4),10);
cube2.transform.position = new Vector3(Random.Range (1,4),Random.Range (1,4),10);
cube3.transform.position = new Vector3(Random.Range (1,4),Random.Range (1,4),10);
cube4.transform.position = new Vector3(Random.Range (1,4),Random.Range (1,4),10);
cube5.transform.position = new Vector3(Random.Range (1,4),Random.Range (1,4),10);
cube6.transform.position = new Vector3(Random.Range (1,4),Random.Range (1,4),10);
cube7.transform.position = new Vector3(Random.Range (1,4),Random.Range (1,4),10);
cube8.transform.position = new Vector3(Random.Range (1,4),Random.Range (1,4),10);
cube9.transform.position = new Vector3(Random.Range (1,4),Random.Range (1,4),10);
cube10.transform.position = new Vector3(Random.Range (1,4),Random.Range (1,4),10);
cube11.transform.position = new Vector3(Random.Range (1,4),Random.Range (1,4),10);
cube12.transform.position = new Vector3(Random.Range (1,4),Random.Range (1,4),10);
cube13.transform.position = new Vector3(Random.Range (1,4),Random.Range (1,4),10);
cube14.transform.position = new Vector3(Random.Range (1,4),Random.Range (1,4),10);
cube15.transform.position = new Vector3(Random.Range (1,4),Random.Range (1,4),10);
}
}
the answer here is unbelievably simple.
you just perform a SHUFFLE, just as you mention $$anonymous$$aul.
look anywhere on the internet for a million pages about algorithms for SHUFFLING in program$$anonymous$$g!
TBC, you either
(A) shuffle before hand, and then use them in that order, or,
if you want to do it "on the fly".
(B) simply pick a random position FRO$$anonymous$$ THE CURRENTLY E$$anonymous$$PTY ONES
there's no other way to do it
this question is an extremely general program$$anonymous$$g question and does not relate to Unity. For future reference, definitely go to somewhere like "stack exchange" to instantly get answers to such general program$$anonymous$$g questions.
Actually @Fattie got a point there and in the meanwhile a counter point. Shuffling the predefined array will guarantee a unique value. But in his case, he might want a more "random" value. If his space is 100*100*100 you are looking at a 1 000 000 large array to make sure any value can be picked.
right, but if they are DISCRETE POSITIONS...
so, there's a million total. how many will you need - say it's 5000. in that case you'd make a list of 5000, using the techniques described.**
(if, as it happens, for some bizarre reason you do need every position filled - the one and only way to do it is indeed shuffle the million points)
in fact, you would very likely break it down to a smaller grid, and then (if necessary) jiggle for more randomness. in realty you'd want "chunky randomness".
TBC, the various difficulties involved in getting the exact "randomness feel" you want utterly overwhelm the trivial beginners question at hand ("how do I random exclusively - oh it's called 'sorting' I didn't know that thanks")
$$anonymous$$ore on these issues here,
http://answers.unity3d.com/questions/296458/random-position-inside-mesh.html
(Please VOTE UP useful answers!)
if they are NOT discrete positions, i.e. you are dealing with getting randomness in floats, the whole issue is utterly and totally different, and depends entirely on what sort of result you want.
Answer by fafase · Nov 27, 2012 at 07:25 AM
Here is another way with old school goto method (@Fattie will be happy about this one :) )
Vector3[] cubes = new Vector3[16];
int index = 0;
void Update(){
if(Input.GetKeyDown(KeyCode.Space)){
RandomValue();
print(cubes[index-1]);
}
}
void RandomValue(){
Start:
Vector3 val;
while (true){
val = new Vector3(Random.Range(a,b),Random.Range(a,b),Random.Range(a,b));
for(int i = 0;i<cubes.Length;i++){
if(val == cubes[i])goto Start;
}goto Outer;
}
Outer:
cubes[index++]= val;
}
Hey...@Fattie and @fafase......Thanks for the help......
Answer by XienDev · Nov 27, 2012 at 07:01 AM
easy.. =)
public class tmp : MonoBehaviour {
public int randomLength = 10;
public float min = -10;
public float max = 10;
public float epsilon = 0.1f;
/// <summary>
/// OnStart funct.
/// </summary>
void Start ()
{
string tmp = "";
float[] randoms = new float[randomLength];
int i = 0;
while (i < randomLength)
{
float nextValue = Random.Range(min, max);
bool contains = false;
for (int j = 0; j < i; j++)
{
if (Mathf.Abs(randoms[j] - nextValue) < epsilon)
{
contains = true;
break;
}
}
if (!contains)
{
i++;
tmp += nextValue.ToString("g2") + "; ";
}
}
Debug.Log(tmp);
}
}
But for long range it's better to use HashSet.Contains avoid while loop, and at the end, HashSet.ToArray();
Answer by DeveshPandey · Nov 27, 2012 at 07:08 AM
You can't avoid the repetition of numbers, but you can minimize the probability of repetition. If you need Non-Repeating random number then you can use the following code:
using System.Collections;
using System.Collections.Generic;
public class Test : MonoBehaviour {
List<float> randomNumber = new List<float>();
float min = 10f;
float max = 11f;
void OnGUI()
{
if(GUI.Button(new Rect(10f,10f,150f,25f),"Get random number"))
{
float randomNo = getRandomNumber();
Debug.Log("---> "+randomNo);
}
}
float getRandomNumber()
{
float rndNo;
//int counter = 0;
while(true)
{
//counter++;
rndNo = Random.Range(min,max);
//print(counter);
if(!randomNumber.Contains(rndNo))
{
randomNumber.Add(rndNo);
break;
}
}
return rndNo;
}
}
Works for me Thank you DeveshPandey but it froze my unity when all random values are called
Answer by CodeMasterMike · Nov 27, 2012 at 06:37 AM
You can't get a "non-repeating" random, since its randomly generating your values for each time.
What you need to do, is to make a check on the random value you are recieving. If this value is already being used, then just do another random call until you get a valu that is not already being used.
$$anonymous$$ike, it's incredibly dangerous to program like that. It can end up hanging for ages looking for one.
Very simply, you pick a random one ..... FRO$$anonymous$$ .... THE E$$anonymous$$PTY ONES RE$$anonymous$$AINING.
it's just that simple.
Answer by zombie_psy · Oct 16, 2013 at 10:45 PM
I took the time to go through the various solutions and code for this issue and brainstormed a bit. This solution requires just one for loop and one nested for loop:
var ObjectToInstantiate : GameObject;
var ObjectToPlotOnGrid : GameObject[];
var pointThatHasBeenTaken : Vector2[];
for(var i=0;i<6;i++) {
ObjectToPlotOnGrid[i] = Instantiate(ObjectToInstantiate);
ObjectToPlotOnGrid[i].pixelInset.x = Screen.width/20*Random.Range(0,20);
ObjectToPlotOnGrid[i].pixelInset.y = Screen.width/20*Random.Range(0,20);
pointThatHasBeenTaken[i]= Vector2(ObjectToPlotOnGrid[i].pixelInset.x, ObjectToPlotOnGrid[i].pixelInset.y);
for(var ii = 0; ii < i; ii++) {
if(Vector2(ObjectToPlotOnGrid[i].pixelInset.x,ObjectToPlotOnGrid[i].pixelInset.y ) == pointThatHasBeenTaken[ii]) {
print("Rerolling spawn");
ObjectToPlotOnGrid[i].pixelInset.x = Screen.width/20*Random.Range(0,20);
ObjectToPlotOnGrid[i].pixelInset.y = Screen.width/20*Random.Range(0,20);
ii--;
}
}
}
In this script:
1) the screen is divided into a 20x20 grid
2) a for loop is iterated from 0-19 plotting random points in that 20x20 grid
3) within that for loop, the nested for loop re-iterates all points already taken before it is plotted
4) If the nested for loop finds that the point is already taken, it is re-rolled another random roll, and subtracts from the for's count
@ $$anonymous$$aulik2208 i am trying your code ..but facing the same problem how to remove the non repeating positions..,and how to assign these positions to cube..i am beginner please help me,how to do that..??