-
-
Save jabrena/057b6e3b666d3e66a9aa1ea5fa14b8e1 to your computer and use it in GitHub Desktop.
2048 terminal game
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Terminal 2048 | |
// By: Andrew Tam | |
// There is currently no GUI for this game and is played completely on the Terminal. | |
// Type in the instructions such as "up", "down", "left", "right" to move the tiles | |
// Type in "reset" to reset the game | |
import java.util.Scanner; | |
import java.util.Arrays; | |
import java.util.ArrayList; | |
import java.util.Random; | |
import java.util.HashMap; | |
import java.util.Map; | |
public class TwentyFourtyEight { | |
private static final int UP = 1; | |
private static final int DOWN = 2; | |
private static final int LEFT = 3; | |
private static final int RIGHT = 4; | |
private int[][] board; | |
private Map<Integer, int[]> OFFSETS = new HashMap<Integer, int[]>(); | |
private ArrayList<int[]> upTileIndices = new ArrayList<int[]>(); | |
private ArrayList<int[]> downTileIndices = new ArrayList<int[]>(); | |
private ArrayList<int[]> leftTileIndices = new ArrayList<int[]>(); | |
private ArrayList<int[]> rightTileIndices = new ArrayList<int[]>(); | |
private Map<Integer, ArrayList<int[]>> edgeTileIndices = new HashMap<Integer, ArrayList<int[]>>(); | |
public static void main(String[] args) { | |
String input; | |
TwentyFourtyEight game = new TwentyFourtyEight(); | |
game.newTile(); | |
game.displayBoard(); | |
do { | |
System.out.println("Please enter a direction: up, down, left, right"); | |
Scanner in = new Scanner(System.in); | |
input = in.nextLine(); | |
if ("up".equalsIgnoreCase(input)) { | |
game.move(UP); | |
game.displayBoard(); | |
} else if ("down".equalsIgnoreCase(input)) { | |
game.move(DOWN); | |
game.displayBoard(); | |
} else if ("right".equalsIgnoreCase(input)) { | |
game.move(RIGHT); | |
game.displayBoard(); | |
} else if ("left".equalsIgnoreCase(input)) { | |
game.move(LEFT); | |
game.displayBoard(); | |
} else if ("reset".equalsIgnoreCase(input)) { | |
System.out.println("Game reset!"); | |
game.reset(); | |
game.displayBoard(); | |
} else { | |
System.out.println("Input not recognized"); | |
} | |
} while (!game.gameFinished()); | |
} | |
public TwentyFourtyEight(int boardHeight, int boardWidth) { | |
// Populate board with zeros | |
board = new int[boardHeight][boardWidth]; | |
// Populate OFFSET map | |
OFFSETS.put(UP, new int[]{1, 0}); | |
OFFSETS.put(DOWN, new int[]{-1, 0}); | |
OFFSETS.put(LEFT, new int[]{0, 1}); | |
OFFSETS.put(RIGHT, new int[]{0, -1}); | |
// Populate edge tile indices | |
for (int i = 0; i < boardHeight; i++) { | |
leftTileIndices.add(new int[]{i, 0}); | |
rightTileIndices.add(new int[]{i, getBoardWidth() - 1}); | |
} | |
for (int i = 0; i < boardWidth; i++) { | |
upTileIndices.add(new int[]{0, i}); | |
downTileIndices.add(new int[]{getBoardHeight() - 1, i}); | |
} | |
// Edge Tiles and direction map | |
edgeTileIndices.put(UP, upTileIndices); | |
edgeTileIndices.put(DOWN, downTileIndices); | |
edgeTileIndices.put(LEFT, leftTileIndices); | |
edgeTileIndices.put(RIGHT, rightTileIndices); | |
} | |
// Default to 4 by 4 game | |
public TwentyFourtyEight() { | |
this(4, 4); | |
} | |
//Reset board to zero | |
public void reset() { | |
for (int i = 0; i < getBoardHeight(); i++) { | |
for (int j = 0; j < getBoardWidth(); j++) { | |
setTile(i, j, 0); | |
} | |
} | |
} | |
// Move all tiles in the give direction and add a new tile if any tiles moved. | |
public void move(int direction) { | |
boolean tilesChanged = false; | |
int lineLength = 0; | |
int[] offset = OFFSETS.get(direction); | |
ArrayList<int[]> edgeTileIndicesDirection = edgeTileIndices.get(direction); | |
if (direction == UP || direction == DOWN) { | |
lineLength = getBoardHeight(); | |
} else { | |
lineLength = getBoardWidth(); | |
} | |
// Based on direction, we go down each line element of edge of the respective direction. | |
for (int i = 0; i < edgeTileIndicesDirection.size(); i++) { | |
int[] tempList = new int[lineLength]; | |
int[] currEdgeTileIndices = edgeTileIndicesDirection.get(i); | |
for (int j = 0; j < lineLength; j++) { | |
tempList[j] = getTile(currEdgeTileIndices[0] + j * offset[0], | |
currEdgeTileIndices[1] + j * offset[1]); | |
} | |
// Create new merged list | |
int[] mergedList = merge(tempList); | |
// Check to see if list changed | |
if (Arrays.equals(tempList, mergedList)) { | |
tilesChanged = true; | |
} | |
// Modify board line to show new values | |
for (int j = 0; j < lineLength; j++) { | |
setTile(currEdgeTileIndices[0] + j * offset[0], | |
currEdgeTileIndices[1] + j * offset[1], | |
mergedList[j]); | |
} | |
} | |
if (tilesChanged) { | |
newTile(); | |
} | |
} | |
// This method merges a single row or column | |
private int[] merge(int[] line) { | |
int[] resultLine = new int[line.length]; | |
int resultIndex = 0; | |
boolean lastTileMerged = false; | |
int lastTileAdded = 0; | |
// Shift blocks over. If 2 tiles are equal in value, then merge them. But only merge the first pair. | |
// When it is merged, you multiply it by 2 | |
for (int i = 0; i < line.length; i++) { | |
int currTile = line[i]; | |
if (currTile > 0) { | |
// Merge | |
if ((currTile == lastTileAdded) && !lastTileMerged) { | |
resultLine[resultIndex - 1] = currTile * 2; | |
lastTileAdded = currTile * 2; | |
lastTileMerged = true; | |
} else { | |
// Don't merge | |
resultLine[resultIndex] = currTile; | |
lastTileAdded = currTile; | |
lastTileMerged = false; | |
resultIndex += 1; | |
} | |
} | |
} | |
return resultLine; | |
} | |
// Create a new tile in a randomly selected empty square | |
public void newTile() { | |
ArrayList<int[]> emptyTileList = new ArrayList<int[]>(); | |
// Get the index of empty tiles | |
for (int i = 0; i < getBoardHeight(); i++) { | |
for (int j = 0; j < getBoardWidth(); j++) { | |
if (getTile(i, j) == 0) { | |
int[] emptyIndex = {i, j}; | |
emptyTileList.add(emptyIndex); | |
} | |
} | |
} | |
// Set one tile from empty list and set to a value. Tile is 2 90% of the time and 4 10% of the time | |
if (emptyTileList.size() > 0) { | |
Random rand = new Random(); | |
int randomIndex = rand.nextInt(emptyTileList.size()); | |
int[] emptyTileIndex = emptyTileList.get(randomIndex); | |
int[] possibleValues = {2, 2, 2, 2, 2, 2, 2, 2, 2, 4}; | |
setTile(emptyTileIndex[0], emptyTileIndex[1], possibleValues[rand.nextInt(possibleValues.length)]); | |
} | |
} | |
// Display board on terminal | |
public void displayBoard() { | |
for (int i = 0; i < getBoardHeight(); i++) { | |
for (int j = 0; j < getBoardWidth(); j++) { | |
System.out.print(board[i][j] + " "); | |
} | |
System.out.println(); | |
} | |
System.out.println(); | |
} | |
//Determine whether game is finished or not | |
public boolean gameFinished() { | |
// If 2048 achieved | |
for (int i = 0; i < getBoardHeight(); i++) { | |
for (int j = 0; j < getBoardWidth(); j++) { | |
if (board[i][j] == 2048) { | |
System.out.println("You win!!"); | |
return true; | |
} | |
} | |
} | |
// If no more moves left. For each row and colsee if there are repeated values | |
// Go through each row | |
for (int i = 0; i < getBoardHeight(); i++) { | |
int prevTile = board[i][0]; | |
for (int j = 0; j < getBoardWidth(); j++) { | |
if (j > 0) { | |
if (board[i][j] == prevTile) { | |
return false; | |
} | |
prevTile = board[i][j]; | |
} | |
} | |
} | |
// Go through each col | |
for (int i = 0; i < getBoardWidth(); i++) { | |
int prevTile = board[0][i]; | |
for (int j = 0; j < getBoardHeight(); j++) { | |
if (j > 0) { | |
if (board[j][i] == prevTile) { | |
return false; | |
} | |
prevTile = board[j][i]; | |
} | |
} | |
} | |
System.out.println("game over!!"); | |
return true; | |
} | |
// Setters and Getters | |
private void setTile(int row, int col, int value) { | |
board[row][col] = value; | |
} | |
private int getTile(int row, int col) { | |
return board[row][col]; | |
} | |
private int getBoardHeight() { | |
return board.length; | |
} | |
private int getBoardWidth() { | |
return board[0].length; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment