兼 叚 2021-06-13 10:25 采纳率: 75%
浏览 33

想把这段代码拆成至少三个类(包括下面的Tile类),但是拆了半天拆不开

package Game2048;

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;
	//生成4x4的方格界面
	private int side = 4;
	//游戏状态:开始
	private State gamestate = State.start;
	//判断能否发生移动
	private boolean checkingAvailableMoves;

	public Game2048() {
		//设定游戏窗体宽和高900x700
		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 {
			//给4*4的方块分配地址值
			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;
		//遍历16个数字块
		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) {
		//为了避免线程问题,使用invokeLater在事件分发线程中为所有新应用程序创建GUI
		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 {
	//merged判断能否合并
	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;
	}
}
  • 写回答

1条回答 默认 最新

  • 苜蓿花乐园 2022-12-30 16:23
    关注

    可以将游戏的逻辑和UI拆分开,画图对象可以做为参数传进去

    评论

报告相同问题?

悬赏问题

  • ¥15 拟通过pc下指令到安卓系统,如果追求响应速度,尽可能无延迟,是不是用安卓模拟器会优于实体的安卓手机?如果是,可以快多少毫秒?
  • ¥20 神经网络Sequential name=sequential, built=False
  • ¥16 Qphython 用xlrd读取excel报错
  • ¥15 单片机学习顺序问题!!
  • ¥15 ikuai客户端多拨vpn,重启总是有个别重拨不上
  • ¥20 关于#anlogic#sdram#的问题,如何解决?(关键词-performance)
  • ¥15 相敏解调 matlab
  • ¥15 求lingo代码和思路
  • ¥15 公交车和无人机协同运输
  • ¥15 stm32代码移植没反应