x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

How to shuffle a TArray?

So I have a deck of cards I need to shuffle. I tried implementing this code: http://stackoverflow.com/a/12646864

like this:

 void ACardsGameMode::Shuffle()
 {
     for (int32 i = Deck.Num() - 1; i > 0; i--) {
         int32 j = FMath::Floor(FMath::Rand() * (i + 1));
         ASCard* temp = Deck[i];
         Deck[i] = Deck[j];
         Deck[j] = temp;
     }
 }

The code compiles, but it crashes every time. Anyone know why?

Product Version: Not Selected
Tags:
more ▼

asked Jun 18 '14 at 09:46 PM in C++ Programming

avatar image

Kochab
486 58 159 118

(comments are locked)
10|2000 characters needed characters left

4 answers: sort voted first

Well, FMath::Rand returns an int between 0 and RAND_MAX. So your j index is invalid. And when you use that j to look up into your Deck (whatever container that is), you are hitting an out of bounds error.

more ▼

answered Jun 18 '14 at 10:55 PM

avatar image

ttvd
333 20 24 34

avatar image Kochab Jun 19 '14 at 11:26 AM

Thanks, that was it. JavaScript's Math.random is 0-1 inclusive so I needed to use FRand instead.

avatar image Kochab Jul 27 '15 at 04:20 PM

I just found that in a packaged game, it will generate the same sequence of random numbers every time. This is different from playing in the editor, which will generate a different sequence every time. I solved this by using a RandomStream and seeding it with the current UnixTimestamp.

  int64 DateInSeconds = FDateTime::Now().ToUnixTimestamp();
  FRandomStream SRand = FRandomStream();
  SRand.Initialize(DateInSeconds);

So instead of using FMath::FRand(), I use SRand.FRand().

(comments are locked)
10|2000 characters needed characters left

Try this:

 void ACardsGameMode::Shuffle()
 {
     for (int32 i = Deck.Num() - 1; i > 0; i--) {
        int32 j = FMath::Floor(FMath::Rand() * (i + 1)) % Deck.Num();
        ASCard* temp = Deck[i];
        Deck[i] = Deck[j];
        Deck[j] = temp;
     }
 }


Or something along those lines

more ▼

answered Jun 18 '14 at 10:57 PM

avatar image

RuBa1987
474 24 21 50

(comments are locked)
10|2000 characters needed characters left

When I need to shuffle an array I usually do something like this

 MyArray.Sort([this](const int Item1, const int Item2) {
     return FMath::FRand() < 0.5f;
 });


It's nice and compact and no extra functions need to be defined.

more ▼

answered Jun 18 '14 at 11:31 PM

avatar image

Alderbit
851 36 14 58

avatar image Omberone Jan 26 '15 at 11:53 AM

Doesn't this mean that each time the sort makes a comparison it generates a new random number? Which means that when it does the final check it re-randomizes everything?

avatar image elisamuelps Jan 21 '18 at 02:42 PM

Sorry for necroposting, I've tried this implementation and it works but I don't quite understand what's going on behind the scenes, why the function that takes a predicate can take extra parameters?

(comments are locked)
10|2000 characters needed characters left

I tried your Shuffle( ) and came up with this solution. Include Math Utilities at the top of your file

 #include "UnrealMathUtility.h"

The SRandInit seeds the SRand to produce new numbers, even in a packaged game. Put it somewhere before the Shuffle gets used (for example inside BeginPlay)

 FGenericPlatformMath::SRandInit(time(0));

And the Shuffle( ) function with an updated Floor call

 void ACardsGameMode::Shuffle()
 {
     for (int32 i = Deck.Num() - 1; i > 0; i--) {
         int32 j = FMath::FloorToInt(FMath::SRand() * (i + 1)) % Deck.Num();
         ASCard* temp = Deck[i];
         Deck[i] = Deck[j];
         Deck[j] = temp;
     }
 }
more ▼

answered Jul 28 '15 at 12:57 AM

avatar image

CoffeeCala
6 1 3

(comments are locked)
10|2000 characters needed characters left
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question