Home > Mobile >  C# Shifting items in an array down and skip spaces
C# Shifting items in an array down and skip spaces

Time:12-28

I am trying to work out a method by which I can shift items in an array of objects, but keep some items in the array exactly where they are, having all items above dropping bellow the fixed items. Think in terms of a Gem Matching game, where gems can be matched. Here are the rules:

  1. Board can be of any X,Y size
  2. Board is filled with Gems (that can break and therefore be destroyed) and Rocks that cannot break (and therefore cannot be destroyed)
  3. Rocks are stationary in their position and cannot move.
  4. When user matches gems, they get destroyed and all the remaining gems drop down to the next available space.
  5. If gems that are matched are below a Rock, then gems above the rock should skip the rock position and fill the bottom most open position.
  6. Rocks can be stacked n deep, vertically or horizontally.

My code works, but only if there is one rock. Please note, this is written in C# for Unity, but the solution is not Unity specific (or even c#). If there are two Rocks stacked on top each other, like this:

[Gem_1]
[Rock_1]
[Rock_2]
[Gem_2]
[Gem_3]
[Gem_4]

And Gems 2,3 and 4 are destroyed, then the gems should all fall and look like this:

[Gem_7]
[Rock_1]
[Rock_2]
[Gem_6]
[Gem_5]
[Gem_1]

But, with my code, when they fall, they look like this:

[Gem_7]
[Rock_1]
[Rock_2]
[Gem_1]
[Gem_6]
[Gem_5]

Here is my Updated code:

private gem_script NextGem(Vector2Int currentGem)
{
  for (int y = 0; y < board_height; y   )
  {
     if(allGems[currentGem.x, y] != null && isGem(layoutStore[currentGem.x, y]) && y > 0){
         return allGems[currentGem.x, y].GetComponent<gem_script>();
     }
  }
  return null;
}

private IEnumerator ScrollNewGems()
{
    for (int x = 0; x < board_width; x  )
    {
       for (int y =  0; y < board_height; y  )
        {
          if (layoutStore[x, y] != Gem_Type.empty)
          {
            if (allGems[x, y] == null)
            {
               Vector2Int current_gem_pos = new Vector2Int(x, y);
               gem_script next_gem = NextGem(current_gem_pos);
                            
               if(next_gem != null)
               {
                  Vector2Int next_gem_pos = next_gem.GetGemPos();
                  next_gem.SetGemXYPos(new Vector2Int(current_gem_pos.x, current_gem_pos.y));
                  allGems[x, y] = allGems[next_gem_pos.x, next_gem_pos.y];
                 allGems[next_gem_pos.x, next_gem_pos.y] = null;
               }                       
          }
       }
     }
 }           
}

Edit I updated my code, but this only works if there is one Gem to drop down. If there are more than one gems, then they stay on the top

CodePudding user response:

There was a typo in my edited script. The nextGem function should not start a y=0 but instead at currentGem.y. Otherwise, it starts from the beginning. Complete working code is:

    private gem_script NextGem(Vector2Int currentGem)
    {
        for (int y = currentGem.y; y < board_height; y   )
        {
            if(allGems[currentGem.x, y] != null && isGem(layoutStore[currentGem.x, y])){
                return allGems[currentGem.x, y].GetComponent<gem_script>();
            }
        }
        return null;
    }
 private IEnumerator ScrollNewGems()
    {
        gameState = GameState.Wait;
        yield return new WaitForSeconds(.2f);
        for (int x = 0; x < board_width; x  )
        {
            for (int y =  0; y < board_height; y  )
            {
                if (layoutStore[x, y] != Gem_Type.empty)
                {
                    if (allGems[x, y] == null)
                    {
                        Vector2Int current_gem_pos = new Vector2Int(x, y);
                        gem_script next_gem = NextGem(current_gem_pos);
                        
                        if(next_gem != null)
                        {
                            Vector2Int next_gem_pos = next_gem.GetGemPos();
                            next_gem.SetGemXYPos(new Vector2Int(current_gem_pos.x, current_gem_pos.y));
                            allGems[x, y] = allGems[next_gem_pos.x, next_gem_pos.y];
                            allGems[next_gem_pos.x, next_gem_pos.y] = null;
                        }                       
                    }
                }
            }
        }       
    }
  • Related