Hi guys, this is my attempt at 2048 machine coding problem from work@tech, do share your insights and feedback. I'm still new to lld so any help is appreciated.

SlideDirection.java

public enum SlideDirection {
    LEFT(0), RIGHT(1), UP(2), DOWN(3);

    private final int direction;
    private static final Map<Integer, SlideDirection> map = new HashMap<>();

    SlideDirection(int direction) {
        this.direction = direction;
    }

    static {
        for(SlideDirection sd : SlideDirection.values()) {
            map.put(sd.getDirection(), sd);
        }
    }

    public static SlideDirection valueOf(int direction) {
        if(map.containsKey(direction)) {
            return map.get(direction);
        }
        else {
            throw new InvalidParameterException("Invalid Input");
        }
    }

    public int getDirection() {
        return direction;
    }
}

Tile.java

public class Tile {
    private final int value;

    public Tile(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || this.getClass() != o.getClass()) return false;
        Tile tile = (Tile) o;
        return value == tile.value;
    }

    @Override
    public int hashCode() {
        return Objects.hash(value);
    }
}

Board.java

public class Board {

    private final List<List<Tile>> tiles;

    private final int size;

    public Board(int size) {
        this.size = size;
        this.tiles = new ArrayList<>();

        for(int i=0; i<size; i++) {
            List<Tile> row = new ArrayList<>();
            for(int j=0; j<size; j++) {
                row.add(new Tile(0));
            }
            this.tiles.add(row);
        }
    }

    public void slide(SlideDirection slideDirection) {
        switch (slideDirection) {
            case LEFT:
                slideLeft();
                break;
            case RIGHT:
                slideRight();
                break;
            case UP:
                slideUp();
                break;
            case DOWN:
                slideDown();
                break;
        }
    }

    private void slideLeft() {
        for(int i=0; i<size; i++) {
            List<Tile> row = this.tiles.get(i);
            List<Tile> newRow = new ArrayList<>();
            int prev=0;
            for(int j=0; j<size; j++) {
                int cur = row.get(j).getValue();
                if(cur == 0) {
                    continue;
                }
                if(prev == 0) {
                    prev = cur;
                    continue;
                }
                if(prev == cur) {
                    newRow.add(new Tile(prev + cur));
                    prev = 0;
                }
                else {
                    newRow.add(new Tile(prev));
                    prev = cur;
                }
            }
            newRow.add(new Tile(prev));
            while(newRow.size() != row.size()) {
                newRow.add(new Tile(0));
            }
            this.tiles.set(i, newRow);
        }
    }

    private void slideRight() {
        reverse();
        slideLeft();
        reverse();
    }

    private void reverse() {
        for(List<Tile> row : tiles) {
            Collections.reverse(row);
        }
    }

    private void slideUp() {
        transpose();
        slideLeft();
        transpose();
    }

    private void slideDown() {
        transpose();
        slideRight();
        transpose();
    }

    private void transpose() {
        for(int i=0; i<size; i++) {
            for(int j=i+1; j<size; j++) {
                Tile temp1 = tiles.get(i).get(j);
                Tile temp2 = tiles.get(j).get(i);
                tiles.get(i).set(j, temp2);
                tiles.get(j).set(i, temp1);
            }
        }
    }

    public boolean addTile(Tile tile) {
        if(boardFilled()) {
            return false;
        }
        int i = (int) (Math.random() * size);
        int j = (int) (Math.random() * size);
        while(!isTileEmpty(i, j)) {
            i = (int) (Math.random() * size);
            j = (int) (Math.random() * size);
        }
        this.tiles.get(i).set(j, tile);
        return true;
    }

    private boolean isTileEmpty(int i, int j) {
        return this.tiles.get(i).get(j).getValue() == 0;
    }

    public boolean boardFilled() {
        for(int i=0; i<size; i++) {
            for(int j=0; j<size; j++) {
                if(isTileEmpty(i, j)) return false;
            }
        }
        return true;
    }

    public boolean slidePossible() {
        for(int i=1; i<size-1; i++) {
            for(int j=1; j<size-1; j++) {
                Tile cur = tiles.get(i).get(j);
                Tile left = tiles.get(i).get(j-1);
                Tile right = tiles.get(i).get(j+1);
                Tile top = tiles.get(i-1).get(j);
                Tile down = tiles.get(i+1).get(j);
                if(cur.equals(left) || cur.equals(right) || cur.equals(top) || cur.equals(down)) {
                    return true;
                }
            }
        }
        return false;
    }

    public Tile getMaxTile() {
        Tile maxTile = new Tile(0);
        for(int i=0; i<size; i++) {
            for(int j=0; j<size; j++) {
                Tile cur = tiles.get(i).get(j);
                if(cur.getValue() > maxTile.getValue()) {
                    maxTile = cur;
                }
            }
        }
        return maxTile;
    }

    public void print() {
        for(int i=0; i<size; i++) {
            for(int j=0; j<size; j++) {
                int val = this.tiles.get(i).get(j).getValue();
                System.out.print((val > 0 ? val : "_") + " ");
            }
            System.out.println();
        }
    }
}

GameService.java

public class GameService {

    private final Board board;
    private final int winValue;
    private final boolean endGameAtWinValue;
    private final int multiplicationFactor;
    private final int initialTiles = 2;

    public GameService(Board board, int winValue, boolean endGameAtWinValue, int multiplicationFactor) {
        this.board = board;
        this.winValue = winValue;
        this.endGameAtWinValue = endGameAtWinValue;
        this.multiplicationFactor = multiplicationFactor;
    }

    public void startGame() {
        for(int i=0; i<initialTiles; i++) {
            spawnTile();
        }
        board.print();
        Scanner sc = new Scanner(System.in);
        while(!board.boardFilled() || board.slidePossible()) {
            System.out.println("Enter Slide Direction :");
            SlideDirection slideDirection = SlideDirection.valueOf(sc.nextInt());
            board.slide(slideDirection);
            if(checkIfPlayerWon()) {
                break;
            }
            boolean spawnSuccessful = spawnTile();
            if(spawnSuccessful) {
                board.print();
            }
            else {
                System.out.println("Game over");
                break;
            }
        }
    }

    private boolean spawnTile() {
//        double power = Math.floor((Math.random() * 10) + 1);
//        int value = (int) Math.pow(multiplicationFactor, power);
        Tile tile = new Tile(2);
        return board.addTile(tile);
    }

    private boolean checkIfPlayerWon() {
        Tile maxTile = board.getMaxTile();
        if(maxTile.getValue() == winValue) {
            System.out.println("Congratulations");
            return true;
        }
        return false;
    }
}

TwoZeroFourEight.java

public class TwoZeroFourEight {
    public static void main(String[] args) {
        Board board = new Board(4);
        GameService gameService = new GameService(board, 2048, true, 2);
        gameService.startGame();
    }
}
Comments (0)