JAVA200 lines of code to achieve 2048 small games

Effect picture:
Insert picture description here
Game introduction:
1.2048 is a puzzle game. At the beginning, two numbers appear randomly. You can control the movement of numbers up, down, left, and right.
2. When you choose to move in one direction, all the numbers will move to the end of the table in that direction, and the empty table will randomly appear 2 or 4. When you encounter the same two numbers, the two numbers will be combined and added into one Numbers until the largest number becomes 2048. The game succeeds
. 3. Otherwise, the game fails when the number fills the form and cannot move anymore.
Game code:


import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;

public class Game2048 extends JPanel {
	enum State {
		start, won, running, over
	}

	final Color[] colorTable = { new Color(0x701710), new Color(0xFFE4C3), new Color(0xfff4d3), new Color(0xffdac3),
			new Color(0xe7b08e), new Color(0xe7bf8e), new Color(0xffc4c3), new Color(0xE7948e), new Color(0xbe7e56),
			new Color(0xbe5e56), new Color(0x9c3931), new Color(0x701710) };
	final static int target = 2048;
	static int highest;
	static int score;
	private Color gridColor = new Color(0xBBADA0);
	private Color emptyColor = new Color(0xCDC1B4);
	private Color startColor = new Color(0xFFEBCD);
	private Random rand = new Random();
	private Tile[][] tiles;
	private int side = 4;
	private State gamestate = State.start;
	private boolean checkingAvailableMoves;

	public Game2048() {
		setPreferredSize(new Dimension(900, 700));
		setBackground(new Color(0xFAF8EF));
		setFont(new Font("SansSerif", Font.BOLD, 48));
		setFocusable(true);
		addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent e) {
				startGame();
				repaint();
			}
		});
		addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				switch (e.getKeyCode()) {
				case KeyEvent.VK_UP:
					moveUp();
					break;
				case KeyEvent.VK_DOWN:
					moveDown();
					break;
				case KeyEvent.VK_LEFT:
					moveLeft();
					break;
				case KeyEvent.VK_RIGHT:
					moveRight();
					break;
				}
				repaint();
			}
		});
	}

	@Override
	public void paintComponent(Graphics gg) {
		super.paintComponent(gg);
		Graphics2D g = (Graphics2D) gg;
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		drawGrid(g);
	}

	void startGame() {
		if (gamestate != State.running) {
			score = 0;
			highest = 0;
			gamestate = State.running;
			tiles = new Tile[side][side];
			addRandomTile();
			addRandomTile();
		}
	}

	void drawGrid(Graphics2D g) {
		g.setColor(gridColor);
		g.fillRoundRect(200, 100, 499, 499, 15, 15);
		if (gamestate == State.running) {
			for (int r = 0; r < side; r++) {
				for (int c = 0; c < side; c++) {
					if (tiles[r][c] == null) {
						g.setColor(emptyColor);
						g.fillRoundRect(215 + c * 121, 115 + r * 121, 106, 106, 7, 7);
					} else {
						drawTile(g, r, c);
					}
				}
			}
		} else {
			g.setColor(startColor);
			g.fillRoundRect(215, 115, 469, 469, 7, 7);
			g.setColor(gridColor.darker());
			g.setFont(new Font("SansSerif", Font.BOLD, 128));
			g.drawString("2048", 310, 270);
			g.setFont(new Font("SansSerif", Font.BOLD, 20));
			if (gamestate == State.won) {
				g.drawString("you made it!", 390, 350);
			} else if (gamestate == State.over)
				g.drawString("game over", 400, 350);
			g.setColor(gridColor);
			g.drawString("click to start a new game", 330, 470);
			g.drawString("(use arrow keys to move tiles)", 310, 530);
		}
	}

	void drawTile(Graphics2D g, int r, int c) {
		int value = tiles[r][c].getValue();
		g.setColor(colorTable[(int) (Math.log(value) / Math.log(2)) + 1]);
		g.fillRoundRect(215 + c * 121, 115 + r * 121, 106, 106, 7, 7);
		String s = String.valueOf(value);
		g.setColor(value < 128 ? colorTable[0] : colorTable[1]);
		FontMetrics fm = g.getFontMetrics();
		int asc = fm.getAscent();
		int dec = fm.getDescent();
		int x = 215 + c * 121 + (106 - fm.stringWidth(s)) / 2;
		int y = 115 + r * 121 + (asc + (106 - (asc + dec)) / 2);
		g.drawString(s, x, y);
	}

	private void addRandomTile() {
		int pos = rand.nextInt(side * side);
		int row, col;
		do {
			pos = (pos + 1) % (side * side);
			row = pos / side;
			col = pos % side;
		} while (tiles[row][col] != null);
		int val = rand.nextInt(10) == 0 ? 4 : 2;
		tiles[row][col] = new Tile(val);
	}

	private boolean move(int countDownFrom, int yIncr, int xIncr) {
		boolean moved = false;
		for (int i = 0; i < side * side; i++) {
			int j = Math.abs(countDownFrom - i);
			int r = j / side;
			int c = j % side;
			if (tiles[r][c] == null)
				continue;
			int nextR = r + yIncr;
			int nextC = c + xIncr;
			while (nextR >= 0 && nextR < side && nextC >= 0 && nextC < side) {
				Tile next = tiles[nextR][nextC];
				Tile curr = tiles[r][c];
				if (next == null) {
					if (checkingAvailableMoves)
						return true;
					tiles[nextR][nextC] = curr;
					tiles[r][c] = null;
					r = nextR;
					c = nextC;
					nextR += yIncr;
					nextC += xIncr;
					moved = true;
				} else if (next.canMergeWith(curr)) {
					if (checkingAvailableMoves)
						return true;
					int value = next.mergeWith(curr);
					if (value > highest)
						highest = value;
					score += value;
					tiles[r][c] = null;
					moved = true;
					break;
				} else
					break;
			}
		}
		if (moved) {
			if (highest < target) {
				clearMerged();
				addRandomTile();
				if (!movesAvailable()) {
					gamestate = State.over;
				}
			} else if (highest == target)
				gamestate = State.won;
		}
		return moved;
	}

	boolean moveUp() {
		return move(0, -1, 0);
	}

	boolean moveDown() {
		return move(side * side - 1, 1, 0);
	}

	boolean moveLeft() {
		return move(0, 0, -1);
	}

	boolean moveRight() {
		return move(side * side - 1, 0, 1);
	}

	void clearMerged() {
		for (Tile[] row : tiles)
			for (Tile tile : row)
				if (tile != null)
					tile.setMerged(false);
	}

	boolean movesAvailable() {
		checkingAvailableMoves = true;
		boolean hasMoves = moveUp() || moveDown() || moveLeft() || moveRight();
		checkingAvailableMoves = false;
		return hasMoves;
	}

	public static void main(String[] args) {
		SwingUtilities.invokeLater(() -> {
			JFrame f = new JFrame();
			f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			f.setTitle("2048");
			f.setResizable(true);
			f.add(new Game2048(), BorderLayout.CENTER);
			f.pack();
			f.setLocationRelativeTo(null);
			f.setVisible(true);
		});
	}
}

class Tile {
	private boolean merged;
	private int value;

	Tile(int val) {
		value = val;
	}

	int getValue() {
		return value;
	}

	void setMerged(boolean m) {
		merged = m;
	}

	boolean canMergeWith(Tile other) {
		return !merged && other != null && !other.merged && value == other.getValue();
	}

	int mergeWith(Tile other) {
		if (canMergeWith(other)) {
			value *= 2;
			merged = true;
			return value;
		}
		return -1;
	}
}
Published 99 original articles · 67 praises · 10,000+ views

Guess you like

Origin blog.csdn.net/qq_44867340/article/details/105589040
Recommended