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();
}
}