Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

Choose item from array and remove item from array

Discussion in 'Scripting' started by Northrop, Jun 11, 2015.

  1. Northrop

    Northrop

    Joined:
    May 22, 2015
    Posts:
    14
    Hi,
    I have 24 game objects, stored in an array.
    I need to choose 6 and instantiate them.
    Instantiating is not the problem (solved)

    How to choose randomly 6 objects to be assigned to 6 position, that not repeat them selves?

    I thought something like
    - My array of possible objects
    - Make a copy of the array
    - I choose the first object and I remove it from the array (the copy)
    I don't know how to remove the object from the array
    - I choose the second and I remove it again from the array (the copy)
    Code (JavaScript):
    1.     var remaining : Array = new array;
    2.                  
    3.             for    (var i=0; i< PotentialObjects.Count; i++){
    4.          
    5.             //copy contents from original array
    6.             remainingnArray.push.apply(remainingArray, AllObjects);
    7.             /print(" copy AllObjects in remainingArray : " + remainingnArray.Count);
    8.      
    9.             PotentialObjects[0] = remainingArray[Random.Range(0, remaining.Length)];
    10.                 /print(" copy AllObjects in remainingArray : " + remainingnArray.Count);
    11.          
    12.          
    13.             //remove PotentialObjects[0] from remainingArray
    14.             //No idea hou to do that!!
    15.  
    16.          
    17.          
    18.             PotentialObjects[1] = remainingArray[Random.Range(0, remaining.Length)];
    19.                 /print(" copy AllObjects in remainingArray : " + remainingnArray.Count);
    20.          
    21.             PotentialObjects[2] = remainingArray[Random.Range(0, remaining.Length)];
    22.                 /print(" copy AllObjects in remainingArray : " + remainingnArray.Count);
    23.          
    24.             PotentialObjects[3] = remainingArray[Random.Range(0, remaining.Length)];
    25.                 /print(" copy AllObjects in remainingArray : " + remainingnArray.Count);
    26.          
    27.             PotentialObjects[4] = remainingArray[Random.Range(0, remaining.Length)];
    28.                 /print(" copy AllObjects in remainingArray : " + remainingnArray.Count);
    29.          
    30.             PotentialObjects[5] = remainingArray[Random.Range(0, remaining.Length)];
    31.                 /print(" copy AllObjects in remainingArray : " + remainingnArray.Count);
    32.  
     
    Last edited: Jun 11, 2015
  2. Limeoats

    Limeoats

    Joined:
    Aug 6, 2014
    Posts:
    104
    Unless I'm mis-interpreting your question, why not just something like this?

    Code (JavaScript):
    1. //Keep a running list of indices used
    2. var usedList = ["-1"];
    3.  
    4. for (var i = 0; i < 6; i++) {
    5.     //Pick a random number between 0 and 23
    6.     var index = -1;
    7.     while (usedList.indexOf(index) != -1) {
    8.         index = Math.random() * (23 - 0) + 0; //Of course the 0 for the min does not need to be there, but I included it so you understand the algorithm being used.
    9.     }
    10.     //Choose an item from your original array using this index
    11.     var itemToInstantiate = PotentialObjects[index];
    12.     //Add the used index to the list
    13.     usedList.push(index);
    14. }
    I didn't test this at all and there might be some logic error somewhere, but this is the general idea.
     
  3. Northrop

    Northrop

    Joined:
    May 22, 2015
    Posts:
    14
    Hi,
    thanks very much for you help. But I am not following as I am very new to SJ.
    Let say I have a pool of 24 objects, from which I choose 6.
    With this you create a list that will contain the objects I used,
    Code (JavaScript):
    1. //Keep a running list of indices used
    2. var usedList = ["-1"];
    Here you say for i equal to 0 and smaller that 6, make i+1
    Code (JavaScript):
    1. for (var i = 0; i < 6; i++) {
    The you create index and set it to -1?
    Code (JavaScript):
    1. var index = -1;
    and that is the part I am not quite following
    Code (JavaScript):
    1. while (usedList.indexOf(index) != -1)
    2. {
    3.         index = Math.random() * (23 - 0) + 0;
    4.     }
    ...
     
  4. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    812
    Another option is to shuffle your array and then take the first 6 items. For a small list you can get pretty good results doing this:

    Code (csharp):
    1. // assuming your list of items is in a variable called array
    2. var randomizer = new System.Random();
    3. var shuffleOrder = new byte[array.length];
    4. randomizer.NextBytes(shuffleOrder);
    5. System.Array.Sort(shuffleOrder, array);
    Your array of items will now be in a random order, so you can just take the top 6 items.
     
    Last edited: Jun 11, 2015
  5. Northrop

    Northrop

    Joined:
    May 22, 2015
    Posts:
    14
    that was nice. Let me ask you something else.
    I have a deck of cards.
    I have for players who hold 3 cards each.
    It is a matching card game. When a players ask for a matching card to an opponent who has it, matching cards disappear and are replaced by new ones until the deck is done.
    But when cards are replaced, you don't want to give a matching card again but you want to control that pairs are being formed in the table.

    How would you approach the probable?
     
    Last edited: Jun 11, 2015
  6. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    812
    Sorry, I don't get this part.
     
  7. Northrop

    Northrop

    Joined:
    May 22, 2015
    Posts:
    14
    sorry. That was not clear at all.
    4 players.
    Player1 ask to Player3 if he has "a card with an apple". Player3 has it, and hand it over. Matched cards disappear.

    Then I can randomized the deck to provided cards in the two empty positions.
    The risk: providing cards that will not make pairs with the ones in the table. Then the game is impossible.

    It is for a language learning game, so ideally my game will have lots of cards. But I need to make sure are potential matching cards on the table.
     
  8. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    812
    When you say "matching cards on the table" do you mean another player has a card that matches, so that eventually someone will make another match?

    I think the best solution to this is to simply allow players to draw new cards. This is how the game "Go Fish" works.. In real life you can't anticipate which cards players will have, so you need to have a mechanism to change the cards. In programming, we could "stack the deck" so that we are guaranteed some players will have matching cards but it's a harder problem to solve and I feel like it's cheating anyways.

    As a player, I would know I have a better chance of getting a match if I ask someone who just received cards, since the computer will stack their hand if necessary.
     
  9. Northrop

    Northrop

    Joined:
    May 22, 2015
    Posts:
    14
    yes. My current deck is made of 60 objects and a copy of them (120 cards).
    Game starts with 3 cards x player from the 120.
    When 2 disappear from the table, are replaced by 2 more.
    Indeed what I want to do is to "stack the deck", so my students don't get bored if they don't make any pairs.
    If it were a small deck, I would no worry. But since I am planing to have a huge deck, I think we may end up with single no paired cards on the table....

    I have a system now, but I think it is super complicated for what I am trying to do, which is having at least 66% of the cards with a matching one.
     
  10. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    812
    Okay, I understand your problem but it really is a dilemma. If you have too few matches, the students get bored with no success. However, if you stack the draw then they will get bored anyways because they can guess that the new cards will match.

    I can think of three alternatives.

    1.
    During the initial shuffle, break the cards into groups of 12. Each 12 will be made up of 6 pairs. Shuffle the groups of 12 and then combine into one big deck without additional shuffling.

    2.
    When replacing the two cards, search through the deck until a card which is held by another player is found.

    3.
    Use a deck with no duplicates. When two cards are needed, get the top card and duplicate it. Give one to each player needing a card. Finally, each player gives one random card to the player on their left and right.
     
  11. Northrop

    Northrop

    Joined:
    May 22, 2015
    Posts:
    14
    Thanks a lot! That logic is way simpler that the one I was trying to implement.
     
  12. JakeBilbe

    JakeBilbe

    Joined:
    Jun 10, 2015
    Posts:
    57
    Since you cannot change an Arrays length after it's created you could either create a method that creates a temporary Array, copies your actual array but changes the length and then replaces your actual array. Or you could set the Array Object to empty by doing:
    Code (csharp):
    1. GameObject[] obj; //Pretend this has 5 objects and you want to remove obj 3
    2.  
    3. void Update() {
    4. obj[2] = new GameObject; //Not 100% sure about this but I remember doing something similar before when I was doing inventories
    5. }
    6.  
     
  13. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,454
    Use a List.
    It allows for additions and removals at any position with in the list.
    It its like an array, but better!!!