This site requires JavaScript, please enable it in your browser!
Greenfoot back
whattheheck
whattheheck wrote ...

2020/3/4

2048 merge error?

whattheheck whattheheck

2020/3/4

#
I'm trying to program 2048, but seem to be having a issue with blocks merging. World.GameBoard code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.List;

    //Instance Constants

    //Define some directions to make it easier to reference which way the blocks are moving
    private static final int UP = 0;
    private static final int RIGHT = 1;
    private static final int DOWN = 2;
    private static final int LEFT = 3;
    int sqrCount = 0;
    
    
    /**
     * Constructor for objects of class MyWorld.
     * 
     */
    public GameBoard()
    {    
        // Create a new world with 4x4 cells with a cell size of 50x50 pixels.
        super(4, 4, 50); 
        
        //populate gameboard with x randomly placed objects
        while(sqrCount<1) {
            if(placeRandomBlock()){
                sqrCount++;
            } else {
                continue;
            }
        }
    }
    
    
    /**
     * Place a block on a random location on the board
     * 
     * @return Returns true if successful, false if not successful
     */
    private boolean placeRandomBlock()
    {

        GameSquare gs = new GameSquare(); //make new game square
        int x = (Greenfoot.getRandomNumber(4)); //Get random num from 0-3, and add 1
        int y = (Greenfoot.getRandomNumber(4));
        
        //Check to ensure random location is not yet taken, if the spot is free add it to the world
        if (getObjectsAt(x, y, GameSquare.class).isEmpty()) {
            addObject(gs,x,y);
            return true;
        } else {
            return false;
        }
    }
    
    /**
     * Act - Check for key presses and tell each block to move itself.
     */
    public void act() 
    {
        //Add key press actoins here
        String key = Greenfoot.getKey();
        //If a key was pressed...do something
        if (key != null) {
            switch(key) {
                case "up": 
                    //Tell the blocks to move up
                    //Start checking from the top, then move downwards

                    for (int i=0; i<getWidth(); i++) {
                        for (int j=0; j<getHeight(); j++) {
                            //Get a list containing all of the GameSquare objects at position (i,j)
                            List blockList = getObjectsAt(i,j,GameSquare.class);
            
                            //Tell the other block object we wish to merge with it.  If successful, delete this block from the game
                            if (blockList.size() == 1) { //Error checking
                                Object tempObject;
                                tempObject = blockList.get(0);
                                GameSquare tempSquare;
                                tempSquare = (GameSquare)tempObject;
                                tempSquare.move(UP);
                            }
                        }
                    }
                    break;

                case "right":
                    //Tell the blocks to move right
                    //Start checking from the right most col, then move left                    
                    for (int i=3; i>=0; i--) {
                        for (int j=0; j<getHeight(); j++) {
                            //Get a list containing all of the GameSquare objects at position (i,j)
                            List blockList = getObjectsAt(i,j,GameSquare.class);
            
                            //Tell the other block object we wish to merge with it.  If successful, delete this block from the game
                            if (blockList.size() == 1) { //Error checking
                                Object tempObject;
                                tempObject = blockList.get(0);
                                GameSquare tempSquare;
                                tempSquare = (GameSquare)tempObject;
                                tempSquare.move(RIGHT);
                            }
                        }
                    }
                    break;

                case "down":
                    //Tell the blocks to move down
                    //Start checking from the bottom, then move up
                    for (int i=3; i>=0; i--) {
                        for (int j=3; j>=0; j--) {
                            //Get a list containing all of the GameSquare objects at position (i,j)
                            List blockList = getObjectsAt(j,i,GameSquare.class);
            
                            //Tell the other block object we wish to merge with it.  If successful, delete this block from the game
                            if (blockList.size() == 1) { //Error checking
                                Object tempObject;
                                tempObject = blockList.get(0);
                                GameSquare tempSquare;
                                tempSquare = (GameSquare)tempObject;
                                tempSquare.move(DOWN);
                            }
                        }
                    }
                    break;

                case "left":
                    //Tell the blocks to move left
                    //Start checking from the left, then move right
                    for (int i=0; i<getWidth(); i++) {
                        for (int j=0; j<getHeight(); j++) {
                            //Get a list containing all of the GameSquare objects at position (i,j)
                            List blockList = getObjectsAt(j,i,GameSquare.class);
            
                            //Tell the other block object we wish to merge with it.  If successful, delete this block from the game
                            if (blockList.size() == 1) { //Error checking
                                Object tempObject;
                                tempObject = blockList.get(0);
                                GameSquare tempSquare;
                                tempSquare = (GameSquare)tempObject;
                                tempSquare.move(LEFT);
                            }
                        }
                    }
                    break;

                }
                

            int count = 0;
            if(numberOfObjects() < 16) {
                while (count < 1) {
                    if (placeRandomBlock()) {
                        count++;
                    }
                }
            }
        }
        
    }
}
Actor.GameSquare code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.List;

public class GameSquare extends Actor
{
    //Instance Constants
    
    //Define some directions to make it easier to reference which way the blocks are moving
    private static final int UP = 0;
    private static final int RIGHT = 1;
    private static final int DOWN = 2;
    private static final int LEFT = 3;
    
    //Define a debugging variable (See video linked in assignment outline)
    private final boolean debug = false;
    
    //Instance Variables    
    private int value;
        
    //Constructor
    public GameSquare()
    {
        this(2);
    }
    
    public GameSquare(int valueIn)
    {
        setValue(valueIn);
        displayValue();
    }
    
    /**
     * Tell the block to move in the given direction until it hits an obstacle
     * 
     * @param The direction in which the block is to move (UP = 0; RIGHT = 1; DOWN = 2; LEFT = 3;
     */
    public void move(int direction) 
    {
        //check if can move
        int movable = canMove(direction);
        System.out.println(movable);
        
        //if moveable, start a loop
        while (movable > 0)
        {
            //Get current coordinates
            int xval = getX();
            int yval = getY();
            //Change x and y values to the "new" location based on direction
            if (direction == 0) {
                yval-=1;
            } else if (direction == 1) {
                xval+=1;
            } else if (direction == 2) {
                yval+=1;
            } else if (direction == 3) {
                xval-=1;
            }
            
            //If Nothing in the way - move the block
            if (movable == 1) {  
                
                movable = canMove(direction);
                setLocation(xval,yval);
                continue;
                //return;
            }
            //Merge the blocks
            else {
                if (!getWorld().getObjectsAt(xval,yval,GameSquare.class).isEmpty()) {
                    GameSquare sqr = (GameSquare)getWorld().getObjectsAt(xval,yval,GameSquare.class).get(0);
                    if(merge(sqr.getValue())) {
                       getWorld().removeObject(sqr);
                       setLocation(xval,yval);
                       movable = canMove(direction);
                       continue;
                    } else {
                        movable = canMove(direction);
                        continue;
                    }
                } else {
                    movable = canMove(direction);
                    continue;
                }
            }
        }
        
        
        //can't move, so don't move.
        return;
    }

    /**
     * Sets the value of the game square to the value of the input parameter.
     * Will only work if the value is a factor of 2
     * 
     * @param The number to use as the new value
     * @return If the number was set correctly return true, otherwise return false
     */
    
    boolean setValue(int valueIn) {
        if(valueIn % 2 != 0) {
            return false;
        } else {
            value = valueIn;
            return true;
        }
    }
    
    /**
     * Merge with another block and combine values.
     * Will only work if the two blocks are of the same value
     * 
     * @param The value of the block to be added
     * 
     * @return Return true if the merge is successful.
     */

    public boolean merge(int valueIn) {
        int sqrVal = getValue();
        if (sqrVal == valueIn) {
            setValue((sqrVal*2));
            return true;
        } else {
            return false;
        }
    }
    
    /**
     * Returns the current value of the gameSquare
     * 
     * @return The current value (int) of the game square
     */
    
    public int getValue() {
        return this.value;
    }

    /**
     * Checks to see if the block can move
     * 
     * @return int value representing what is in the space to be moved to.  0 -> Path Blocked, 1 -> Empty Space, int>1 value of block in the space to be moved to.
     */
    private int canMove(int direction)
    {
        //Get World
        World world = getWorld();
        
        //Get x and y values of current object
        int xval = getX();
        int yval = getY();
        
        //Change x and y values to the "new" location based on direction
        if (direction == 0) {
            yval-=1;
        } else if (direction == 1) {
            xval+=1;
        } else if (direction == 2) {
            yval+=1;
        } else if (direction == 3) {
            xval-=1;
        }
        
        //Test for outside border
        if (xval<0 || xval>3 || yval<0 || yval>3) {
            return 0;
        }
        
        //Check to see if there is a block in the way
        if(!world.getObjectsAt(xval, yval, GameSquare.class).isEmpty()) {
            GameSquare sqr = (GameSquare)world.getObjectsAt(xval,yval,GameSquare.class).get(0);
            return sqr.getValue();
        }
        
        return 1;
    }
    
    /**
     * displayValue - Displays the current value of a block in an image, then sets that image to the block display image
     */    
    private void displayValue() 
    {
        //Create an image consisting of the display value using built in greenfoot commands
        GreenfootImage displayImage;
        displayImage = new GreenfootImage( Integer.toString(value), 20, Color.BLACK, Color.WHITE);
        
        //Add the image as the new image for this object
        setImage(displayImage);
        
    }
}
The issue seems to be within:
if(merge(sqr.getValue())) {
                       getWorld().removeObject(sqr);
                       setLocation(xval,yval);
                       movable = canMove(direction);
                       continue;
                    } else {
                        movable = canMove(direction);
                        continue;
                    }
                } else {
                    movable = canMove(direction);
                    continue;
                }
            }
        }
I can't see how I would be able to fix it
danpost danpost

2020/3/4

#
Could it be that you are just not updating the image after a merge?
whattheheck whattheheck

2020/3/4

#
Adding the displayValue function doesn't seem to fix the issue. It seems like when squares merge, they get stuck in place
You need to login to post a reply.