11 Replies Latest reply on Feb 28, 2008 6:06 PM by Rothrock

    Shuffling arrays

    Rectallinear Level 1
      I've got an array of objects which I'm able to shuffle into random order and then step through. When each object has been used, the array re-shuffles and the process begins again. I got some help with this last year on this forum, and everything works great.

      I've noticed, however, that if my array only contains three or four objects, often the last object displayed in one array will end up randomly being chosen as the first object in the next array, resulting in the same object displaying consecutively.

      I'll include the actionscript I'm using below. If anyone has an idea of what I could add to this to prevent the first object in a shuffled array from matching the last object in the previous array, I would really appreciate it.

        • 1. Re: Shuffling arrays
          sneakyimp Level 2
          This code could form an infinite loop under certain conditions (like when the array has length=1) but it might just work?

          • 2. Re: Shuffling arrays
            rlc5611 Level 1
            Do a search on the keyword shuffle and look for kglad posts. He has a very efficient shuffle algorithm.
            • 3. Re: Shuffling arrays
              Rothrock Level 5
              The algorithm is better and I highly recommend it, but it still has the same problem: it doesn't control whether the last element of a shuffle will be different than the first element of the next shuffle.

              I usually use a do loop to ensure no repeats from one cycle to the next.
              • 4. Re: Shuffling arrays
                Rectallinear Level 1
                Rothrock's method seems to work well. The only problem is, I'm not sure how exactly to draw from it. In my original example, I was creating a function called getRandomLabel() which was shuffling the array and then stepping through it. As a result, I could use commands elsewhere in the Flash piece like gotoAndStop(getRandomLabel()) or attachMovie(getRandomLabel()) to get single random values from the shuffled array. Once every value had been drawn from the array, the array reshuffles.

                How would I splice and step through the Rothrock code, and then how would I refer to it elsewhere with a gotoAndStop command?
                • 5. Re: Shuffling arrays
                  Rothrock Level 5
                  Everytime you shuffle it, also initialize a counter to zero.

                  deckCount=0

                  Then every time you need something, you just get it:

                  myVariable=myArray[deckCount]
                  deckCount++

                  You can increment the count anytime you need to -- before you take an element, as you take an element, at the end of a round, whatever. The nice thing about this is that your array isn't "destroyed" in the process. If you need to look back at the values they are all there, if you need to peek ahead, again they are all there.
                  • 6. Re: Shuffling arrays
                    Rectallinear Level 1
                    This system works, but it doesn't seem to totally solve the problem of preventing the last element of a shuffle from being repeated as the first element of the next. Or at least the way I'm using it. Here's what I've got on the main timeline:

                    Array.prototype.shuffle = function() {
                    for (var ivar = this.length-1; ivar>=0; ivar--) {
                    var p = random(ivar+1);
                    var t = this[ivar];
                    this[ivar] = this[p];
                    this[p] = t;
                    }
                    };
                    //Hide the shuffle prototype from the tyranny of the for…in loop
                    ASSetPropFlags(Array.prototype,["shuffle"],1,1);

                    var myArray = ["mc1", "mc2", "mc3", "mc4", "mc5"];

                    for (var i = 0; i<3; i++) {
                    var last = myArray[2];
                    do {
                    myArray.shuffle();
                    } while (myArray[0] == last);
                    trace(myArray);
                    }

                    deckCount=0;


                    Then I have five movie clips on the main timeline. Each contain the following:


                    arrayPick=_root.myArray[_root.deckCount];
                    attachMovie(arrayPick, 1, {_x: 0, _y: 0});
                    _root.deckCount++;

                    trace(arrayPick);


                    You'll notice that I'm tracing the value of the array each time it's reshuffled, and then the value of the array element that's being drawn into each of my five movie clips. Below is the output that I'm getting. The array seems to be shuffled three times every time the shuffle command is called, and then the final order is used. In the sample output below, there are instances of the last element in an array being repeated in the first element of the next array in all three shuffles. See where I've highlighted. Am I just doing something wrong?


                    Flash1mc,Flash2mc,Flash4mc,Flash5mc,Flash3mc
                    Flash3mc,Flash5mc,Flash4mc,Flash1mc,Flash2mc
                    Flash5mc,Flash1mc,Flash3mc,Flash2mc,Flash4mc
                    Flash5mc
                    Flash1mc
                    Flash3mc
                    Flash2mc
                    Flash4mc
                    Flash4mc,Flash3mc,Flash2mc,Flash1mc,Flash5mc

                    Flash5mc,Flash4mc,Flash1mc,Flash3mc,Flash2mc
                    Flash5mc,Flash1mc,Flash4mc,Flash2mc,Flash3mc
                    Flash5mc
                    Flash1mc
                    Flash4mc
                    Flash2mc
                    Flash3mc
                    Flash2mc,Flash1mc,Flash5mc,Flash3mc,Flash4mc
                    Flash2mc,Flash1mc,Flash4mc,Flash3mc,Flash5mc
                    Flash1mc,Flash2mc,Flash5mc,Flash3mc,Flash4mc
                    Flash1mc
                    Flash2mc
                    Flash5mc
                    Flash3mc
                    Flash4mc
                    Flash1mc,Flash3mc,Flash4mc,Flash5mc,Flash2mc
                    Flash5mc,Flash1mc,Flash4mc,Flash2mc,Flash3mc
                    Flash2mc,Flash3mc,Flash4mc,Flash5mc,Flash1mc
                    Flash2mc
                    Flash3mc
                    Flash4mc
                    Flash5mc
                    Flash1mc
                    Flash1mc,Flash4mc,Flash3mc,Flash5mc,Flash2mc
                    Flash1mc,Flash4mc,Flash5mc,Flash3mc,Flash2mc

                    Flash2mc,Flash3mc,Flash1mc,Flash4mc,Flash5mc
                    Flash2mc
                    Flash3mc
                    Flash1mc
                    Flash4mc
                    Flash5mc
                    Flash4mc,Flash2mc,Flash5mc,Flash1mc,Flash3mc
                    Flash2mc,Flash3mc,Flash1mc,Flash5mc,Flash4mc
                    Flash5mc,Flash4mc,Flash3mc,Flash1mc,Flash2mc
                    Flash5mc

                    Flash4mc
                    Flash3mc
                    Flash1mc
                    Flash2mc
                    • 7. Re: Shuffling arrays
                      Rothrock Level 5
                      The problem is the line:

                      var last = myArray[2];

                      I had used 2 in the example because my example had three things in the array. (Remember the first one is zero!) You will find that the third element of the previous round is never the same as the first element of the next round! To make that more bullet proof probably this line should be:

                      var last = myArray[myArray.length-1];

                      Or something like that. A good way you could have tested this for yourself was to trace out last and see what it was getting.
                      • 8. Re: Shuffling arrays
                        Rectallinear Level 1
                        Rothrock, I really appreciate your help with this. Unfortunately, changing that line doesn't seem to fix the problem.

                        Since I'm using five variables, I changed it to this:

                        var last = myArray[4];

                        As you can see in the output below, I'm still getting repeats between the last value of one array and the first value of the next. (I'm also now tracing the value of the 'last' variable as you suggested.)

                        I also tried var last = myArray[myArray.length-1]; and the result was the same.

                        I was wondering if maybe the issue had to do with this section:

                        for (var i = 0; i<3; i++) {
                        var last = myArray[4];

                        I see that the i<3 value is controlling the number of shuffles that happen each time the function is called. The function is then assigning the value of the fifth element (thanks to the [4]) in the second-to-last shuffle to the 'last' variable. No matter how many shuffles I set the function to perform, it's always grabbing from the second-to-last one. Unless I go with i<1 and then it seems to select an element from the array at random. Therefore, the value of 'last' seems to be arbitrary to the function. Am I just missing something else that's painfully obvious?

                        Also, I was curious about the for (var i = 0; i<3; i++) line. What's the advantage of having the array shuffle three times rather than just once?


                        mc4,mc3,mc1,mc2,mc5
                        mc3,mc2,mc5,mc4,mc1
                        mc3,mc4,mc1,mc2,mc5
                        Last = mc1
                        mc3
                        mc4
                        mc1
                        mc2
                        mc5

                        mc2,mc1,mc3,mc5,mc4
                        mc2,mc1,mc3,mc4,mc5
                        mc1,mc4,mc2,mc3,mc5
                        Last = mc5
                        mc1
                        mc4
                        mc2
                        mc3
                        mc5

                        mc1,mc3,mc5,mc4,mc2
                        mc3,mc1,mc4,mc5,mc2
                        mc5,mc3,mc1,mc4,mc2
                        Last = mc2
                        mc5
                        mc3
                        mc1
                        mc4
                        mc2

                        mc4,mc1,mc5,mc2,mc3
                        mc2,mc4,mc5,mc3,mc1
                        mc4,mc3,mc1,mc5,mc2
                        Last = mc1
                        mc4
                        mc3
                        mc1
                        mc5
                        mc2

                        mc3,mc2,mc1,mc5,mc4
                        mc2,mc4,mc5,mc1,mc3
                        mc4,mc1,mc5,mc3,mc2
                        Last = mc3
                        mc4
                        mc1
                        mc5
                        mc3
                        mc2
                        • 9. Re: Shuffling arrays
                          Rothrock Level 5
                          I was only using that for loop to show the result of repeated shufflings -- or as it were to simulate 3 trips through your swf. Sorry about not being clear. (I do think you understand this better that you give yourself credit for!)

                          There is no benefit to shuffling more than once. And that is why you are seeing repeats from (what you are thinking of as) one cycle to the next. You will notice that if you just take all those long lines the end of a line is never the same as the start of the line below it.

                          That is also why you are seeing that "last" is coming from the middle shuffle, because that is the last element of the last shuffle you performed.

                          So don't have the array shuffle mroe than once -- of course it might shuffle more than once inside that do-loop, but that is what you want.

                          And PS, I wouldn't hard code that last=myArray[4]. That is just the kind of thing that you will come back to next month, add a clip to the array and then wonder why it isn't working. I really recommend using the code I gave you earlier.
                          • 10. Shuffling arrays
                            Rectallinear Level 1
                            Alright, I think I'm now finally smellin' what the (roth)Rock is cookin'.

                            I made a couple modifications to the code and it now seems to work exactly as I need it to.

                            I finally realized that what I really needed was to define "last" as the final element in the last shuffled array to be used (ie, the last clip that the viewer saw). So I moved the line where we define "last" down so that it happens after the shuffle. That way, once we step through the array and come back to the function, the "while" statement is comparing the first item in the newly shuffled array with the last item in the previous array. That seemed to do the trick.

                            I know a lot of people use this forum as a reference and learning tool, so I'll attach the final working code below in case anyone else finds themselves facing this same dilemma. The first hunk of code goes in frame 1 of your main timeline. It shuffles the array and ensures there are no repeats. Below that I'll include the code to place throughout your movie to draw elements from your shuffled array.

                            Thanks again to Rothrock for all the help.

                            • 11. Re: Shuffling arrays
                              Rothrock Level 5
                              Great. Glad that worked out for you. There is still one little change you should make. Since you are only shuffling once per pass, you don't need the for loop at all. So you can remove that.