[Solved-ish -- Efficiency Advice Requested] Grid Iteration

Heya :slight_smile: I’m no great shakes at programming (yet anyway) but am quite happily learning enough to be dangerous of late. Currently I’m having issues retooling the Shuffle function of a Match 3 game I’ve been working on. In preliminary runs, I’ve just had it destroy all of the pieces and recreate them, but I’d prefer it to actually shuffle the existing pieces instead of completely resetting the game board. While I’ve been successful with locating and counting the various types of pieces on the board, I’m having trouble respawning them appropriately.

What I intend is for each square of the grid to be iterated through and a valid piece assigned from the array of collected pieces. I’ve managed, at one point, to get a single piece to spawn, but then it stops iterating through the rest of the grid, which is no good. I’ve switched things up a bit in hopes of forcing it to move through the grid, but now it’s only freezing the Unity editor (which is the same issue I had when I tried using a While loop to check the validity of the pieces). I think I almost had it working at one point, and managed to populate over half of the grid before it errored out, but further attempts to fine tune it have only led to Editor freezes.

I figure there’s a high likelihood that I’m going about this bass ackwards… :stuck_out_tongue: In any case, please have a look at the following example code and let me know if you’ve any suggestions, advice, or educational insight you can share. All assistance is most greatly appreciated. Thanks!

(This is just an example, retooled from my actual code to give you the gist)

void Shuffle()
{
    int pieceTotal = 36; // total number of pieces on the grid (calculated by totaling the numbers in pieceTypes array which is created in another bit of code)
    int rnd = 0; // a random number
    bool valid = false; // can we use the selected piece?
    int gridWidth = 6; // how wide the grid is (x)
    int gridHeight = 6; // how tall the grid is (y)
   
    for( int x = 0; x < gridWidth; x++)
    {
        for( int y = 0; y < gridHeight; y++)
        {
            valid = false; // reset valid to false on each pass
            for(int p = 0; p < pieceTotal; p++)
            {
                if(valid == false) // valid is False by default, so this executes
                {
                    rnd = Random.Range(0,pieceTypes.Length); // get a random number between 0 and the length of our array
                    if(pieceTypes[rnd] == 0) // if there is no piece stored
                    {
                        valid = false; // then it is not valid
                        // check our position on the grid
                        if(y == 0 && x > 0) // if we're at the bottom of a new column
                        {
                            y = gm.boardHeight; // go back to the top
                            x--; // of the last column
                        }
                        else if(y > 0) // otherwise
                        {
                            y--; // go down one in this column
                        }
                        p--; // reset the value of the piece counter since this one doesn't count yet
                    }
                    else // if there is a piece of this type left to be used
                    {
                        valid  = true; // set valid to true
                        pieceTypes[rnd] = pieceTypes[rnd] - 1; // subract one from the pieceTypes total for this type of piece
                        gamePiece.reset(rnd); // reset the current piece to the new piece type
                    }
                }
            }
        }
    }
}

Woohoo! Well, my brain hurts now, lol, but through trial and mad amounts of error, I finally got it to work the way I wanted it to. Now I just to make it check in front, behind, above and below each piece to make sure it’s not generating auto-matches when it shuffles. Should be easy-ish by comparison :wink:

Here’s a revamped code example for anyone interested:

void Shuffle()
{
    for( int x = 0; x < gridWidth; x++)
    {
        for( int y = 0; y < gridHeight; y++)
        {
            rnd = Random.Range(0,pieceTypes.Length);
            if(pieceTypes[rnd] <= 0)
            {
                valid = false;                          
            }
          
            if(pieceTypes[rnd] > 0)
            {
                valid  = true;
            }
          
            if(valid == true)
            {
                gamePiece.Reset(rnd);
                pieceTypes[rnd] = pieceTypes[rnd] - 1;
            }
            if(valid == false)
            {
                if(y == 0 && x > 0)
                {
                    y = gridHeight; // go back to the top
                    x--; // of the last column
                }
                else if(y > 0) // otherwise
                {
                    y--; // go down one in this column
                }
            }                  
        }
    }
    Debug.Log("EVERYDAY I'M SHUFFLING...");
}

If anyone can suggest a more elegant way of doing all of this, I’d still love to hear it. In the meantime, at least it’s functioning :slight_smile:

Alright, after testing it over and over again in an attempt to break it as much as possible, it seems to work pretty well for the most part. It’s still freezing up on occasion, which leads me to believe that it could be approached in a more efficient manner. For now, I’ve sectioned the code into three parts; one to initialize the script and it’s variables, one to count the pieces, and a coroutine to handle the shuffling. I’ve managed to get it to check for matches, too, so I no longer have to worry about them auto-generating.

The hangups seem to be coming from the Shuffle section (now a coroutine, but otherwise still similar to the code in the previous post). I moved it into a coroutine in hopes that it would be less likely to slow down the rest of the game, but it’s still taking a good while to iterate through the 36 pieces and generate appropriate replacements.

As before, any and all additional input would most certainly be appreciated. If you’d like to see more of the code, just let me know. Thanks!