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

2020/3/7

2048

whattheheck whattheheck

2020/3/7

#
I need help with finishing my 2048 code, I have trouble with my final merging, with the code below:
if(merge(sqr.getValue())) {
                   getWorld().removeObject(sqr);
                   setLocation(xval,yval);
                   movable = canMove(direction);
                   continue;
                } else {
                    movable = canMove(direction);
                    continue;
                }
            } else {
                movable = canMove(direction);
                continue;
            }
        }
    }
This code seems to cause error by just combining squares, not changing the value, and not moving them afterwards. It's like the square just gets stuck in place. I don't quite see how to fix this issue of merging, what should the code be? Full source code: World.GameBoard:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.List;
public class GameBoard extends World
{
    //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:
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);
         
    }
}
danpost danpost

2020/3/7

#
Line 78 in the GameSquare class seems to allow continued move checking even though a game square that was not merged was found. Setting movable to zero there stops the freezing of the scenario.
whattheheck whattheheck

2020/3/7

#
Doing this doesn't seem to affect the game in anyway, the same sort of error still occurs
danpost danpost

2020/3/7

#
whattheheck wrote...
Doing this doesn't seem to affect the game in anyway, the same sort of error still occurs
The issue with values not doubling still will occur, but the "stuck in place" issue should be fixed by that change. I will look for a solution to the non-doubling during a merge.
whattheheck whattheheck

2020/3/8

#
danpost wrote...
whattheheck wrote...
Doing this doesn't seem to affect the game in anyway, the same sort of error still occurs
The issue with values not doubling still will occur, but the "stuck in place" issue should be fixed by that change. I will look for a solution to the non-doubling during a merge.
Did you manage to find a solution?
danpost danpost

2020/3/8

#
whattheheck wrote...
Did you manage to find a solution?
Update: doubling of values actually works; problem is that you are having GameSquare objects piling atop one another.
danpost danpost

2020/3/8

#
In your move(int direction) method, reverse the order of the two lines in the if (movable == 1) block.
whattheheck whattheheck

2020/3/8

#
danpost wrote...
In your move(int direction) method, reverse the order of the two lines in the if (movable == 1) block.
Thanks! Do you know why that made a difference?
danpost danpost

2020/3/8

#
whattheheck wrote...
Do you know why that made a difference?
The next move is based on the value of movable. If you compute it prior to the current move then the movability of the next move is based on the wrong state -- it will move twice on the same computation (which is why you were having the actors pile atop one another.
You need to login to post a reply.