Search code examples
javaloopsmultidimensional-array2048

Making a java 2048 game, upon sliding it goes through the loop more times than it should and hits tests/alters numbers already altered


So I have a solid slide function, the problem is (which is very hard to explain!) it goes through all the possibilities including spaces in the 2d array that have already been added together: say there is a setup like this: 4,4,8,2 ---after one swipe to the right, it ends up like this: ,_,16,2. however in the actual game, after one swipe right, it should look like this: ___,8,2.

Basically, how can I fix this? You don't need to tell me the code, it's my project for my final, but I'd like to get some sort of explanation as to why this is happening.

I've attempted to loop through the array from right to left but that resulted in the numbers not even moving.

   processUserChoice(String i) {
    if (i.equals("d")) {
     while ((slideRight())) {
      moveRight();
     }
    }
    printBoard();
   }

   public boolean slideRight() {
    for (int i = 0; i < board.length; i++) {
     for (int j = 0; j < board[i].length - 1; j++) {
      if (board[i][j + 1] == 0 && board[i][j] != 0) {
       return true;
      } else if (board[i][j + 1] == board[i][j] && board[i][j] != 0) {
       return true;
      }
     }
    }
    return false;
   }
   public void moveRight() {
    for (int i = 0; i < board.length; i++) {
     for (int j = 0; j < board[i].length - 1; j++) {
      if (board[i][j + 1] == 0 && board[i][j] != 0) {
       board[i][j + 1] = board[i][j];
       board[i][j] = 0;
      } else if (board[i][j + 1] == board[i][j] && board[i][j] != 0) {
       board[i][j + 1] = board[i][j + 1] + board[i][j];
       board[i][j] = 0;
      }
     }
    }
    //checkLose();
   }

After one swipe right, it should look like this:" ___,8,2 "(From the example before).


Solution

  • I did something similar to this in the past. I would to do it pretty much the same way as you are at the moment but add a Boolean array that checks if the tile has collided or not and only merges tiles that haven't been collided.

    class Tile {
        public int value;
        public Boolean collided;
    
        public Tile(int value) {
            this.value = value;
            collided = false;
        }
    
        public Tile attemptMerge(Tile target) {
            if (target.value == value) {
                Tile t = new Tile(value * 2);
                t.collided = true;
                return t;
            } else {
                return null;
            }
        }
    
        public void reset() {
            value = 0;
            collided = false;
        }
    }
    

    Somewhere in your main update loop:

    void slideRight() {
        for (int row = 0; row < 4; row++) {
            for (int column = 3; column >= 0; column--) {
                Tile current = board[row][column];
    
                if (current.value == 0) continue;
    
                for (int slot = column + 1; slot < 3; slot++) {
                    Tile target = board[row][slot];
    
                    if (target.value == 0) {
                        target.value = current.value;
                        current = target;
                        board[row][slot - 1].reset();
                    } else if (target.value == current.value) {
                        Tile product = target.merge(current);
    
                        if (!target.collided && !current.collided) {
                            current = product;
                            board[row][slot - 1].reset();
                        } else {
                            break;
                        }
                    } else {
                        break;
                    }
                }
            }
        }
    }
    

    I believe something along those lines should work. Sorry if the logic is a bit flawed.