repeat number problem

Hi.

I wrote this code and i want this code don’t repeat number for make coin. this code only work correctly when CurrentCoinNumber <= 3 but when it’s great than 3, i wrote another code for reset it to 1 and compared RandCoin with LastCoin value in While loop for to avoid duplicate value but it make my code don’t work correctly. Does anyone know where the problem is?

This is my code:

int CurrentCoinNumber = 1;
int LastCoin;
List<int> RandCoinList = new List<int> { 10, 10, 10 };

void Awake()
{               
    for (int j = 0; j < 8; j++)
    {
        // Create Coin
        int RandCoin = Random.Range(0, 3);

        if (CurrentCoinNumber <= 3)
        {
            while (RandCoinList.Contains(RandCoin))
            {
                RandCoin = Random.Range(0, 3);
            }
            LastCoin = RandCoinList[RandCoin];
        }
        else
        {               
            // reset all RandCoinList index value to 10
            for (int k = 0; k < RandCoinList.Count; k++)
            {
                RandCoinList[k] = 10;
            }

            while (RandCoin == LastCoin)
            {
                RandCoin = Random.Range(0, 3);
            }

            CurrentCoinNumber = 1;
        }

        RandCoinList[RandCoin] = RandCoin;

        GameObject coinObj = Instantiate(Coin[RandCoin], GameObject.Find("Coins").transform);

        CurrentCoinNumber += 1;
    }
}

Why’d you create a new thread?

Furthermore, what exactly are you trying to accomplish here?

Your loop goes 8 times, but you’re generating values 0,1,2. That’s 3 distinct values… there’s no way to NOT repeat if you select 8 values from a set of 3.

Also you do this:

RandCoinList[RandCoin] = RandCoin;

What? You put the value into the slot at index of itself. What’s the point of generating the value if slot 2 has the value 2 in it? What’s the point!?

What is your end goal here?

1 Like

I want create 8 coin at first running the game. i have 3 kind of coin and i want create each coin without repeating.

What solution do you suggest? really i confused.

What do you mean without repeating?

There’s no duplicates at all, which is impossible when you have a set of 3, and select 8. It’s just you can’t do it. It’s literally impossible.
A,C,B,? - how could you have a 4th entry, it HAS to be one of the existing 3.

Do you mean that it never matches the coin just before it?
A,C,B,C,A,B,C,C! - nope, C,C is a repeat

That’s fairly simple, your code implies something more like 1 though. But not 1… I don’t get it.

Some other idea of ‘repeating’.

In which case, you need to define what you mean by “without repeating”.

I’m assuming this is what you’re talking about… but I have no idea what you want.

Is it that you want it to be sets of 3, where each set of 3 repeats. But within the set of 3 it doesn’t? Like:

A,C,B - C,B,A - B,A

?

What about from set to set, is this allowed?

B,A,C - C,B,A - A,B

???

Please, define what you mean. You can’t come up with the algorithm until we know what the algorithm is attempting to do.

answer of your questions:

1- yes.we can’t has 4th entry, but for do this i tried to reset RandCoinList values to 10.

2- i don’t want last value match with new value after each three values. like this: A,C,B, C,A,B, C,B,A, …

3-

yes, i mean without repeating.

yes.

after generate first 3 values without repeating, next 3 values are with repeating. like: A,C,B, C,B,B, A,C,C, …

no, it should be three not two.

Note, my question wasn’t about the length, it was about the fact that C - C existed from set 1 to set 2. And A - A existed from set 2 to set 3.

Also…

Your code was:

for (int j = 0; j < 8; j++)

That’s going to create 8 entries, not 9. Hence I demonstrated sets of 3, 3, then 2.

3 + 3 + 2 = 8

i can set it to 9 it’s not problem.

for (int j = 0; j < 9; j++)

then result is 3 + 3 + 3 = 9.

now, is there any way to fix this problem?

Answer my question!

I don’t understand your mean.

EDIT:
actually i want it generate something like this: B,C,A, C,A,B, A,C,B.

mean, don’t generate Repeating number, and last number of set 1 don’t match with first number in set 2 and so on.

You notice how in my example for that question I say:

B,A,C - C,B,A - A,B

Not how C repeats from set of 3 to set of 3?

You get a B,A,C,C,B,A,A,B

Is that valid or not?

It’s a repeat, but it’s not a repeat within a given set of 3.

Note, this is what programming is about. Being able to define what it is exactly you need in as explicit of terms possible.

no, is not valid.

You really have to learn to describe your problem more accurately. That’s the first step to craft custom algorithms (or find existing ones). I’m not saying you must be super-exact, but at least some effort to make people understand what you’re asking for.

From your example it looks like you’re just looking for a sequence of triples:

Tripleₓ: (Aₓ, Bₓ, Cₓ)
Tripleₓ₊₁: (Aₓ₊₁, Bₓ₊₁, Cₓ₊₁)
where Cₓ != Aₓ₊₁

If that’s your only requirement, try the following.

[SerializeField]
private GameObject[] _coinPrefabs;

[SerializeField]
private Transform _coinParent;

[SerializeField]
private int _iterations = 8;

private void Awake()
{
    int lastRandom = -1;

    for (int i = 0; i < _iterations; ++i)
    {
        int next;
        // if you happen to have an array of length < 2, this will freeze
        while (lastRandom == (next = Random.Range(0, _coinPrefabs.Length))) { /* do nothing */};

        lastRandom = next;
        Instantiate(_coinPrefabs[next], _coinParent);
    }
}

Now be aware though. If your array contains 0 or 1 elements, you need to handle the situation, as the application would freeze (Use an if for that).
If it contains just 2 elements, you could just avoid this and instantiate them alternating instead.

Also, the lower the number of elements in the array (in your case 3), the higher is the probability to encounter some sort of blocking behaviour.

1 Like

OK.

So as I have it.

You need to create a list of length X, where X is the total number of coins generated.
Where the list is segmented into groups of length Y, where Y is the total number of available coins.
The list must be distinct in the segmented groups (no duplicates across the entire segment).
This list must not repeat from element to element (no duplicate one after the other).

If I had to do this, I’d avoid this random selection and then throwing it out if it doesn’t meet our needs. That’s a lot of extra unnecessary work.

Instead I’d do exactly what I described in the requirements. Generate segments, shuffle them, ensure no repeat on ends of segments.

///coins - the list of available coins, its length is the segment length
///totalCount - the number of coins to generate
void GenerateCoins(List<GameObject> coins, int totalCount)
{
    if(coins.Count <= 1)
    {
        throw new System.Exception("NOPE!");
    }
 
 
    //cache our parent container for reuse, this could be passed as a parameter as well
    var container = GameObject.Find("Coins").transform;
    //first lets create a temp list to randomly pull from
    var temp = new List<GameObject>(coins.Length);
    //a reference to the last object that was selected
    GameObject selection;
 
    //now lets start our loop
    for(int i = 0; i < totalCount; i++)
    {
        //when the list is empty repopulate with our segments worth of entries and shuffle
        if(temp.Count == 0)
        {
            //fill for this segment
            temp.AddRange(coins);
            //shuffle this segment
            for(int j = 0; j < temp.Count; j++)
            {
                int k = Random.Range(0, temp.Count);
                var t = temp[k];
                temp[k] = temp[j];
                temp[j] = t;
            }
            //make sure this segment doesn't repeat from last segment's end
            //if last value is the last selection then move out of the way
            if(temp[temp.Count - 1] == last)
            {
                int k = Random.Range(0, temp.Count - 1);
                var t = temp[k];
                temp[k] = temp[temp.Count - 1];
                temp[temp.Count - 1] = t;
            }
        }
     
        //now grab the last shuffled instance, and remove it from the list
        //note that as we select, we remove it, so it can't be selected again
        //we use the last because the RemoveAt method is faster this way
        selection = temp[temp.Count - 1];
        temp.RemoveAt(temp.Count - 1);
     
        //instantiate our selection
        var coinObj = Instantiate(selection, container);
    }
}
1 Like

Thanks @lordofduct :slight_smile:

Thanks @Suddoha :slight_smile: